|
|
@@ -19,9 +19,16 @@
|
|
|
|
|
|
-define(OPTL, [opentelemetry]).
|
|
|
|
|
|
+-define(OTEL_EXPORTER, opentelemetry_exporter).
|
|
|
+-define(OTEL_LOG_HANDLER, otel_log_handler).
|
|
|
+-define(OTEL_LOG_HANDLER_ID, opentelemetry_handler).
|
|
|
+
|
|
|
-export([add_handler/0, remove_handler/0]).
|
|
|
-export([post_config_update/5]).
|
|
|
-export([update/1]).
|
|
|
+-export([add_otel_log_handler/0, remove_otel_log_handler/0]).
|
|
|
+-export([stop_all_otel_apps/0]).
|
|
|
+-export([otel_exporter/1]).
|
|
|
|
|
|
update(Config) ->
|
|
|
case
|
|
|
@@ -45,14 +52,109 @@ remove_handler() ->
|
|
|
ok = emqx_config_handler:remove_handler(?OPTL),
|
|
|
ok.
|
|
|
|
|
|
+post_config_update(?OPTL, _Req, Old, Old, _AppEnvs) ->
|
|
|
+ ok;
|
|
|
post_config_update(?OPTL, _Req, New, _Old, AppEnvs) ->
|
|
|
application:set_env(AppEnvs),
|
|
|
- ensure_otel(New);
|
|
|
+ MetricsRes = ensure_otel_metrics(New),
|
|
|
+ LogsRes = ensure_otel_logs(New),
|
|
|
+ _ = maybe_stop_all_otel_apps(New),
|
|
|
+ case {MetricsRes, LogsRes} of
|
|
|
+ {ok, ok} -> ok;
|
|
|
+ Other -> {error, Other}
|
|
|
+ end;
|
|
|
post_config_update(_ConfPath, _Req, _NewConf, _OldConf, _AppEnvs) ->
|
|
|
ok.
|
|
|
|
|
|
-ensure_otel(#{enable := true} = Conf) ->
|
|
|
- _ = emqx_otel:stop_otel(),
|
|
|
- emqx_otel:start_otel(Conf);
|
|
|
-ensure_otel(#{enable := false}) ->
|
|
|
- emqx_otel:stop_otel().
|
|
|
+stop_all_otel_apps() ->
|
|
|
+ _ = application:stop(opentelemetry),
|
|
|
+ _ = application:stop(opentelemetry_experimental),
|
|
|
+ _ = application:stop(opentelemetry_experimental_api),
|
|
|
+ _ = application:stop(opentelemetry_exporter),
|
|
|
+ ok.
|
|
|
+
|
|
|
+add_otel_log_handler() ->
|
|
|
+ ensure_otel_logs(emqx:get_config(?OPTL)).
|
|
|
+
|
|
|
+remove_otel_log_handler() ->
|
|
|
+ remove_handler_if_present(?OTEL_LOG_HANDLER_ID).
|
|
|
+
|
|
|
+otel_exporter(ExporterConf) ->
|
|
|
+ #{
|
|
|
+ endpoint := Endpoint,
|
|
|
+ protocol := Proto,
|
|
|
+ ssl_options := SSLOpts
|
|
|
+ } = ExporterConf,
|
|
|
+ {?OTEL_EXPORTER, #{
|
|
|
+ endpoint => Endpoint,
|
|
|
+ protocol => Proto,
|
|
|
+ ssl_options => ssl_opts(Endpoint, SSLOpts)
|
|
|
+ }}.
|
|
|
+
|
|
|
+%% Internal functions
|
|
|
+
|
|
|
+ensure_otel_metrics(#{metrics := #{enable := true} = MetricsConf}) ->
|
|
|
+ _ = emqx_otel_metrics:stop_otel(),
|
|
|
+ emqx_otel_metrics:start_otel(MetricsConf);
|
|
|
+ensure_otel_metrics(#{metrics := #{enable := false}}) ->
|
|
|
+ emqx_otel_metrics:stop_otel();
|
|
|
+ensure_otel_metrics(_) ->
|
|
|
+ ok.
|
|
|
+
|
|
|
+ensure_otel_logs(#{logs := #{enable := true} = LogsConf}) ->
|
|
|
+ ok = remove_handler_if_present(?OTEL_LOG_HANDLER_ID),
|
|
|
+ ok = ensure_log_apps(),
|
|
|
+ HandlerConf = tr_handler_conf(LogsConf),
|
|
|
+ %% 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}}) ->
|
|
|
+ remove_handler_if_present(?OTEL_LOG_HANDLER_ID).
|
|
|
+
|
|
|
+remove_handler_if_present(HandlerId) ->
|
|
|
+ case logger:get_handler_config(HandlerId) of
|
|
|
+ {ok, _} ->
|
|
|
+ ok = logger:remove_handler(HandlerId);
|
|
|
+ _ ->
|
|
|
+ ok
|
|
|
+ end.
|
|
|
+
|
|
|
+ensure_log_apps() ->
|
|
|
+ {ok, _} = application:ensure_all_started(opentelemetry_exporter),
|
|
|
+ {ok, _} = application:ensure_all_started(opentelemetry_experimental),
|
|
|
+ ok.
|
|
|
+
|
|
|
+maybe_stop_all_otel_apps(#{metrics := #{enable := false}, logs := #{enable := false}}) ->
|
|
|
+ stop_all_otel_apps();
|
|
|
+maybe_stop_all_otel_apps(_) ->
|
|
|
+ ok.
|
|
|
+
|
|
|
+tr_handler_conf(Conf) ->
|
|
|
+ #{
|
|
|
+ level := Level,
|
|
|
+ max_queue_size := MaxQueueSize,
|
|
|
+ exporting_timeout := ExportingTimeout,
|
|
|
+ scheduled_delay := ScheduledDelay,
|
|
|
+ exporter := ExporterConf
|
|
|
+ } = Conf,
|
|
|
+ #{
|
|
|
+ level => Level,
|
|
|
+ config => #{
|
|
|
+ max_queue_size => MaxQueueSize,
|
|
|
+ exporting_timeout_ms => ExportingTimeout,
|
|
|
+ scheduled_delay_ms => ScheduledDelay,
|
|
|
+ exporter => otel_exporter(ExporterConf)
|
|
|
+ }
|
|
|
+ }.
|
|
|
+
|
|
|
+ssl_opts(Endpoint, SSLOpts) ->
|
|
|
+ case is_ssl(Endpoint) of
|
|
|
+ true ->
|
|
|
+ emqx_tls_lib:to_client_opts(SSLOpts#{enable => true});
|
|
|
+ false ->
|
|
|
+ []
|
|
|
+ end.
|
|
|
+
|
|
|
+is_ssl(<<"https://", _/binary>> = _Endpoint) ->
|
|
|
+ true;
|
|
|
+is_ssl(_Endpoint) ->
|
|
|
+ false.
|