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

This commit is contained in:
Serge Tupchii 2023-11-28 15:16:47 +02:00
parent 2a3f6b749c
commit c8e69357cc
7 changed files with 95 additions and 104 deletions

View File

@ -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) ->

View File

@ -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 => #{

View File

@ -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(

View File

@ -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.

View File

@ -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}}.

View File

@ -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}]),

View File

@ -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."""