فهرست منبع

feat(emqx_opentelemetry): use one global exporter config for all otel signals

Serge Tupchii 2 سال پیش
والد
کامیت
c8e69357cc

+ 1 - 1
apps/emqx_opentelemetry/src/emqx_otel_app.erl

@@ -24,7 +24,7 @@
 start(_StartType, _StartArgs) ->
     emqx_otel_config:add_handler(),
     ok = emqx_otel_config:add_otel_log_handler(),
-    ok = emqx_otel_trace:ensure_traces(emqx:get_config([opentelemetry, traces])),
+    ok = emqx_otel_trace:ensure_traces(emqx:get_config([opentelemetry])),
     emqx_otel_sup:start_link().
 
 stop(_State) ->

+ 22 - 13
apps/emqx_opentelemetry/src/emqx_otel_config.erl

@@ -85,30 +85,40 @@ otel_exporter(ExporterConf) ->
 
 %% Internal functions
 
-ensure_otel_metrics(#{metrics := MetricsConf}, #{metrics := MetricsConf}) ->
+ensure_otel_metrics(
+    #{metrics := MetricsConf, exporter := Exporter},
+    #{metrics := MetricsConf, exporter := Exporter}
+) ->
     ok;
-ensure_otel_metrics(#{metrics := #{enable := true} = MetricsConf}, _Old) ->
+ensure_otel_metrics(#{metrics := #{enable := true}} = Conf, _Old) ->
     _ = emqx_otel_metrics:stop_otel(),
-    emqx_otel_metrics:start_otel(MetricsConf);
+    emqx_otel_metrics:start_otel(Conf);
 ensure_otel_metrics(#{metrics := #{enable := false}}, _Old) ->
     emqx_otel_metrics:stop_otel();
 ensure_otel_metrics(_, _) ->
     ok.
 
-ensure_otel_logs(#{logs := LogsConf}, #{logs := LogsConf}) ->
+ensure_otel_logs(
+    #{logs := LogsConf, exporter := Exporter},
+    #{logs := LogsConf, exporter := Exporter}
+) ->
     ok;
-ensure_otel_logs(#{logs := #{enable := true} = LogsConf}, _OldConf) ->
+ensure_otel_logs(#{logs := #{enable := true}} = Conf, _OldConf) ->
     ok = remove_handler_if_present(?OTEL_LOG_HANDLER_ID),
-    HandlerConf = tr_handler_conf(LogsConf),
+    HandlerConf = tr_handler_conf(Conf),
     %% NOTE: should primary logger level be updated if it's higher than otel log level?
     logger:add_handler(?OTEL_LOG_HANDLER_ID, ?OTEL_LOG_HANDLER, HandlerConf);
 ensure_otel_logs(#{logs := #{enable := false}}, _OldConf) ->
     remove_handler_if_present(?OTEL_LOG_HANDLER_ID).
 
-ensure_otel_traces(#{traces := TracesConf}, #{traces := TracesConf}) ->
+ensure_otel_traces(
+    #{traces := TracesConf, exporter := Exporter},
+    #{traces := TracesConf, exporter := Exporter}
+) ->
     ok;
-ensure_otel_traces(#{traces := #{enable := true} = TracesConf}, _OldConf) ->
-    emqx_otel_trace:start(TracesConf);
+ensure_otel_traces(#{traces := #{enable := true}} = Conf, _OldConf) ->
+    _ = emqx_otel_trace:stop(),
+    emqx_otel_trace:start(Conf);
 ensure_otel_traces(#{traces := #{enable := false}}, _OldConf) ->
     emqx_otel_trace:stop().
 
@@ -120,14 +130,13 @@ remove_handler_if_present(HandlerId) ->
             ok
     end.
 
-tr_handler_conf(Conf) ->
+tr_handler_conf(#{logs := LogsConf, exporter := ExporterConf}) ->
     #{
         level := Level,
         max_queue_size := MaxQueueSize,
         exporting_timeout := ExportingTimeout,
-        scheduled_delay := ScheduledDelay,
-        exporter := ExporterConf
-    } = Conf,
+        scheduled_delay := ScheduledDelay
+    } = LogsConf,
     #{
         level => Level,
         config => #{

+ 5 - 2
apps/emqx_opentelemetry/src/emqx_otel_metrics.erl

@@ -65,7 +65,7 @@ handle_info(_Msg, State) ->
 terminate(_Reason, _State) ->
     ok.
 
-setup(Conf = #{enable := true}) ->
+setup(Conf = #{metrics := #{enable := true}}) ->
     ensure_apps(Conf),
     create_metric_views();
 setup(_Conf) ->
@@ -73,7 +73,10 @@ setup(_Conf) ->
     ok.
 
 ensure_apps(Conf) ->
-    #{exporter := #{interval := ExporterInterval} = Exporter} = Conf,
+    #{
+        exporter := Exporter,
+        metrics := #{interval := ExporterInterval}
+    } = Conf,
 
     _ = opentelemetry_experimental:stop_default_metrics(),
     ok = application:set_env(

+ 58 - 77
apps/emqx_opentelemetry/src/emqx_otel_schema.erl

@@ -30,15 +30,27 @@
 upgrade_legacy_metrics(RawConf) ->
     case RawConf of
         #{<<"opentelemetry">> := Otel} ->
-            LegacyMetricsFields = [<<"enable">>, <<"exporter">>],
-            Otel1 = maps:without(LegacyMetricsFields, Otel),
-            Metrics = maps:with(LegacyMetricsFields, Otel),
-            case Metrics =:= #{} of
-                true ->
-                    RawConf;
-                false ->
-                    RawConf#{<<"opentelemetry">> => Otel1#{<<"metrics">> => Metrics}}
-            end;
+            Otel1 =
+                case maps:take(<<"enable">>, Otel) of
+                    {MetricsEnable, OtelConf} ->
+                        emqx_utils_maps:deep_put(
+                            [<<"metrics">>, <<"enable">>], OtelConf, MetricsEnable
+                        );
+                    error ->
+                        Otel
+                end,
+            Otel2 =
+                case Otel1 of
+                    #{<<"exporter">> := #{<<"interval">> := Interval} = Exporter} ->
+                        emqx_utils_maps:deep_put(
+                            [<<"metrics">>, <<"interval">>],
+                            Otel1#{<<"exporter">> => maps:remove(<<"interval">>, Exporter)},
+                            Interval
+                        );
+                    _ ->
+                        Otel1
+                end,
+            RawConf#{<<"opentelemetry">> => Otel2};
         _ ->
             RawConf
     end.
@@ -69,6 +81,13 @@ fields("opentelemetry") ->
                 #{
                     desc => ?DESC(otel_traces)
                 }
+            )},
+        {exporter,
+            ?HOCON(
+                ?R_REF("otel_exporter"),
+                #{
+                    desc => ?DESC(otel_exporter)
+                }
             )}
     ];
 fields("otel_metrics") ->
@@ -82,10 +101,15 @@ fields("otel_metrics") ->
                     desc => ?DESC(enable)
                 }
             )},
-        {exporter,
+        {interval,
             ?HOCON(
-                ?R_REF("otel_metrics_exporter"),
-                #{desc => ?DESC(exporter)}
+                emqx_schema:timeout_duration_ms(),
+                #{
+                    aliases => [scheduled_delay],
+                    default => <<"10s">>,
+                    desc => ?DESC(scheduled_delay),
+                    importance => ?IMPORTANCE_HIDDEN
+                }
             )}
     ];
 fields("otel_logs") ->
@@ -134,14 +158,6 @@ fields("otel_logs") ->
                     desc => ?DESC(scheduled_delay),
                     importance => ?IMPORTANCE_HIDDEN
                 }
-            )},
-        {exporter,
-            ?HOCON(
-                ?R_REF("otel_logs_exporter"),
-                #{
-                    desc => ?DESC(exporter),
-                    importance => ?IMPORTANCE_HIGH
-                }
             )}
     ];
 fields("otel_traces") ->
@@ -182,14 +198,6 @@ fields("otel_traces") ->
                     importance => ?IMPORTANCE_HIDDEN
                 }
             )},
-        {exporter,
-            ?HOCON(
-                ?R_REF("otel_traces_exporter"),
-                #{
-                    desc => ?DESC(exporter),
-                    importance => ?IMPORTANCE_HIGH
-                }
-            )},
         {filter,
             ?HOCON(
                 ?R_REF("trace_filter"),
@@ -199,42 +207,7 @@ fields("otel_traces") ->
                 }
             )}
     ];
-fields("otel_metrics_exporter") ->
-    exporter_fields(metrics);
-fields("otel_logs_exporter") ->
-    exporter_fields(logs);
-fields("ssl_opts") ->
-    Schema = emqx_schema:client_ssl_opts_schema(#{}),
-    lists:keydelete("enable", 1, Schema);
-fields("otel_traces_exporter") ->
-    exporter_fields(traces);
-fields("trace_filter") ->
-    %% More filters can be implemented in future, e.g. topic, clientid
-    [
-        {trace_all,
-            ?HOCON(
-                boolean(),
-                #{
-                    default => false,
-                    desc => ?DESC(trace_all),
-                    importance => ?IMPORTANCE_MEDIUM
-                }
-            )}
-    ].
-
-desc("opentelemetry") -> ?DESC(opentelemetry);
-desc("exporter") -> ?DESC(exporter);
-desc("otel_logs_exporter") -> ?DESC(exporter);
-desc("otel_metrics_exporter") -> ?DESC(exporter);
-desc("otel_traces_exporter") -> ?DESC(exporter);
-desc("otel_logs") -> ?DESC(otel_logs);
-desc("otel_metrics") -> ?DESC(otel_metrics);
-desc("otel_traces") -> ?DESC(otel_traces);
-desc("ssl_opts") -> ?DESC(exporter_ssl);
-desc("trace_filter") -> ?DESC(trace_filter);
-desc(_) -> undefined.
-
-exporter_fields(OtelSignal) ->
+fields("otel_exporter") ->
     [
         {endpoint,
             ?HOCON(
@@ -263,21 +236,29 @@ exporter_fields(OtelSignal) ->
                     importance => ?IMPORTANCE_LOW
                 }
             )}
-    ] ++ exporter_extra_fields(OtelSignal).
-
-%% Let's keep it in exporter config for metrics, as it is different from
-%% scheduled_delay_ms opt used for otel traces and logs
-exporter_extra_fields(metrics) ->
+    ];
+fields("ssl_opts") ->
+    Schema = emqx_schema:client_ssl_opts_schema(#{}),
+    lists:keydelete("enable", 1, Schema);
+fields("trace_filter") ->
+    %% More filters can be implemented in future, e.g. topic, clientid
     [
-        {interval,
+        {trace_all,
             ?HOCON(
-                emqx_schema:timeout_duration_ms(),
+                boolean(),
                 #{
-                    default => <<"10s">>,
-                    required => true,
-                    desc => ?DESC(scheduled_delay)
+                    default => false,
+                    desc => ?DESC(trace_all),
+                    importance => ?IMPORTANCE_MEDIUM
                 }
             )}
-    ];
-exporter_extra_fields(_OtelSignal) ->
-    [].
+    ].
+
+desc("opentelemetry") -> ?DESC(opentelemetry);
+desc("otel_exporter") -> ?DESC(otel_exporter);
+desc("otel_logs") -> ?DESC(otel_logs);
+desc("otel_metrics") -> ?DESC(otel_metrics);
+desc("otel_traces") -> ?DESC(otel_traces);
+desc("ssl_opts") -> ?DESC(exporter_ssl);
+desc("trace_filter") -> ?DESC(trace_filter);
+desc(_) -> undefined.

+ 3 - 3
apps/emqx_opentelemetry/src/emqx_otel_sup.erl

@@ -41,8 +41,8 @@ init([]) ->
         period => 512
     },
     Children =
-        case emqx_conf:get([opentelemetry, metrics]) of
-            #{enable := false} -> [];
-            #{enable := true} = Conf -> [worker_spec(emqx_otel_metrics, Conf)]
+        case emqx_conf:get([opentelemetry]) of
+            #{metrics := #{enable := false}} -> [];
+            #{metrics := #{enable := true}} = Conf -> [worker_spec(emqx_otel_metrics, Conf)]
         end,
     {ok, {SupFlags, Children}}.

+ 4 - 6
apps/emqx_opentelemetry/src/emqx_otel_trace.erl

@@ -55,26 +55,24 @@ toggle_registered(false = _Enable) ->
     ok.
 
 -spec ensure_traces(map()) -> ok | {error, term()}.
-ensure_traces(#{enable := true} = Conf) ->
+ensure_traces(#{traces := #{enable := true}} = Conf) ->
     start(Conf);
 ensure_traces(_Conf) ->
     ok.
 
 -spec start(map()) -> ok | {error, term()}.
-start(Conf) ->
-    _ = safe_stop_default_tracer(),
+start(#{traces := TracesConf, exporter := ExporterConf}) ->
     #{
-        exporter := Exporter,
         max_queue_size := MaxQueueSize,
         exporting_timeout := ExportingTimeout,
         scheduled_delay := ScheduledDelay,
         filter := #{trace_all := TraceAll}
-    } = Conf,
+    } = TracesConf,
     OtelEnv = [
         {bsp_scheduled_delay_ms, ScheduledDelay},
         {bsp_exporting_timeout_ms, ExportingTimeout},
         {bsp_max_queue_size, MaxQueueSize},
-        {traces_exporter, emqx_otel_config:otel_exporter(Exporter)}
+        {traces_exporter, emqx_otel_config:otel_exporter(ExporterConf)}
     ],
     set_trace_all(TraceAll),
     ok = application:set_env([{opentelemetry, OtelEnv}]),

+ 2 - 2
rel/i18n/emqx_otel_schema.hocon

@@ -17,8 +17,8 @@ otel_traces.label: "Open Telemetry Traces"
 enable.desc: "Enable or disable Open Telemetry signal."
 enable.label: "Enable."
 
-exporter.desc: "Open Telemetry Exporter"
-exporter.label: "Exporter"
+otel_exporter.desc: "Open Telemetry Exporter"
+otel_exporter.label: "Exporter"
 
 max_queue_size.desc:
 """The maximum queue size. After the size is reached Open Telemetry signals are dropped."""