diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl index 3a2b5d972..45219c3f6 100644 --- a/apps/emqx_conf/src/emqx_conf_schema.erl +++ b/apps/emqx_conf/src/emqx_conf_schema.erl @@ -1190,37 +1190,44 @@ tr_prometheus_collectors(Conf) -> emqx_prometheus, emqx_prometheus_mria %% builtin vm collectors - | tr_vm_dist_collector(Conf) ++ - tr_mnesia_collector(Conf) ++ - tr_vm_statistics_collector(Conf) ++ - tr_vm_system_info_collector(Conf) ++ - tr_vm_memory_collector(Conf) ++ - tr_vm_msacc_collector(Conf) + | prometheus_collectors(Conf) ]. -tr_vm_dist_collector(Conf) -> - Enabled = conf_get("prometheus.vm_dist_collector", Conf, disabled), - collector_enabled(Enabled, prometheus_vm_dist_collector). +prometheus_collectors(Conf) -> + case conf_get("prometheus.enable_basic_auth", Conf, undefined) of + %% legacy + undefined -> + tr_collector("prometheus.vm_dist_collector", prometheus_vm_dist_collector, Conf) ++ + tr_collector("prometheus.mnesia_collector", prometheus_mnesia_collector, Conf) ++ + tr_collector( + "prometheus.vm_statistics_collector", prometheus_vm_statistics_collector, Conf + ) ++ + tr_collector( + "prometheus.vm_system_info_collector", prometheus_vm_system_info_collector, Conf + ) ++ + tr_collector("prometheus.vm_memory_collector", prometheus_vm_memory_collector, Conf) ++ + tr_collector("prometheus.vm_msacc_collector", prometheus_vm_msacc_collector, Conf); + %% new + _ -> + tr_collector("prometheus.collectors.vm_dist", prometheus_vm_dist_collector, Conf) ++ + tr_collector("prometheus.collectors.mnesia", prometheus_mnesia_collector, Conf) ++ + tr_collector( + "prometheus.collectors.vm_statistics", prometheus_vm_statistics_collector, Conf + ) ++ + tr_collector( + "prometheus.collectors.vm_system_info", + prometheus_vm_system_info_collector, + Conf + ) ++ + tr_collector( + "prometheus.collectors.vm_memory", prometheus_vm_memory_collector, Conf + ) ++ + tr_collector("prometheus.collectors.vm_msacc", prometheus_vm_msacc_collector, Conf) + end. -tr_mnesia_collector(Conf) -> - Enabled = conf_get("prometheus.mnesia_collector", Conf, disabled), - collector_enabled(Enabled, prometheus_mnesia_collector). - -tr_vm_statistics_collector(Conf) -> - Enabled = conf_get("prometheus.vm_statistics_collector", Conf, disabled), - collector_enabled(Enabled, prometheus_vm_statistics_collector). - -tr_vm_system_info_collector(Conf) -> - Enabled = conf_get("prometheus.vm_system_info_collector", Conf, disabled), - collector_enabled(Enabled, prometheus_vm_system_info_collector). - -tr_vm_memory_collector(Conf) -> - Enabled = conf_get("prometheus.vm_memory_collector", Conf, disabled), - collector_enabled(Enabled, prometheus_vm_memory_collector). - -tr_vm_msacc_collector(Conf) -> - Enabled = conf_get("prometheus.vm_msacc_collector", Conf, disabled), - collector_enabled(Enabled, prometheus_vm_msacc_collector). +tr_collector(Key, Collect, Conf) -> + Enabled = conf_get(Key, Conf, disabled), + collector_enabled(Enabled, Collect). collector_enabled(enabled, Collector) -> [Collector]; collector_enabled(disabled, _) -> []. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl index c1379d4d6..6b3d5b4fa 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl @@ -185,7 +185,8 @@ fields(meta) -> schema_with_example(Type, Example) -> hoconsc:mk(Type, #{examples => #{<<"example">> => Example}}). --spec schema_with_examples(hocon_schema:type(), map()) -> hocon_schema:field_schema_map(). +-spec schema_with_examples(hocon_schema:type(), map() | list(tuple())) -> + hocon_schema:field_schema_map(). schema_with_examples(Type, Examples) -> hoconsc:mk(Type, #{examples => #{<<"examples">> => Examples}}). diff --git a/apps/emqx_prometheus/src/emqx_prometheus.erl b/apps/emqx_prometheus/src/emqx_prometheus.erl index a242931c4..09ba157a0 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus.erl @@ -42,6 +42,7 @@ %% gen_server callbacks -export([ init/1, + handle_continue/2, handle_call/3, handle_cast/2, handle_info/2, @@ -74,8 +75,8 @@ %% APIs %%-------------------------------------------------------------------- -start_link([]) -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). +start_link(Conf) -> + gen_server:start_link({local, ?MODULE}, ?MODULE, Conf, []). info() -> gen_server:call(?MODULE, info). @@ -84,49 +85,41 @@ info() -> %% gen_server callbacks %%-------------------------------------------------------------------- -init([]) -> - #{interval := Interval} = opts(), - {ok, #{timer => ensure_timer(Interval), ok => 0, failed => 0}}. +init(Conf) -> + {ok, #{}, {continue, Conf}}. -handle_call(info, _From, State = #{timer := Timer}) -> - {reply, State#{opts => opts(), next_push_ms => erlang:read_timer(Timer)}, State}; +handle_continue(Conf, State) -> + Opts = #{interval := Interval} = opts(Conf), + {noreply, State#{ + timer => ensure_timer(Interval), + opts => Opts, + ok => 0, + failed => 0 + }}. + +handle_call(info, _From, State = #{timer := Timer, opts := Opts}) -> + {reply, State#{opts => Opts, next_push_ms => erlang:read_timer(Timer)}, State}; handle_call(_Msg, _From, State) -> {reply, ok, State}. handle_cast(_Msg, State) -> {noreply, State}. -handle_info({timeout, Timer, ?TIMER_MSG}, State = #{timer := Timer}) -> - #{ - interval := Interval, - headers := Headers, - job_name := JobName, - push_gateway_server := Server - } = opts(), - PushRes = push_to_push_gateway(Server, Headers, JobName), +handle_info({timeout, Timer, ?TIMER_MSG}, State = #{timer := Timer, opts := Opts}) -> + #{interval := Interval, headers := Headers, url := Server} = Opts, + PushRes = push_to_push_gateway(Server, Headers), NewTimer = ensure_timer(Interval), NewState = maps:update_with(PushRes, fun(C) -> C + 1 end, 1, State#{timer => NewTimer}), %% Data is too big, hibernate for saving memory and stop system monitor warning. {noreply, NewState, hibernate}; +handle_info({update, Conf}, State = #{timer := Timer}) -> + emqx_utils:cancel_timer(Timer), + handle_continue(Conf, State); handle_info(_Msg, State) -> {noreply, State}. -push_to_push_gateway(Uri, Headers, JobName) when is_list(Headers) -> - [Name, Ip] = string:tokens(atom_to_list(node()), "@"), - % NOTE: allowing errors here to keep rough backward compatibility - {JobName1, Errors} = emqx_template:render( - emqx_template:parse(JobName), - #{<<"name">> => Name, <<"host">> => Ip} - ), - _ = - Errors == [] orelse - ?SLOG(warning, #{ - msg => "prometheus_job_name_template_invalid", - errors => Errors, - template => JobName - }), +push_to_push_gateway(Url, Headers) when is_list(Headers) -> Data = prometheus_text_format:format(), - Url = lists:concat([Uri, "/metrics/job/", unicode:characters_to_list(JobName1)]), case httpc:request(post, {Url, Headers, "text/plain", Data}, ?HTTP_OPTIONS, []) of {ok, {{"HTTP/1.1", 200, _}, _RespHeaders, _RespBody}} -> ok; @@ -152,8 +145,26 @@ ensure_timer(Interval) -> %%-------------------------------------------------------------------- %% prometheus callbacks %%-------------------------------------------------------------------- -opts() -> - emqx_conf:get(?PROMETHEUS). +opts(#{interval := Interval, headers := Headers, job_name := JobName, push_gateway_server := Url}) -> + #{interval => Interval, headers => Headers, url => join_url(Url, JobName)}; +opts(#{push_gateway := #{url := Url, job_name := JobName} = PushGateway}) -> + maps:put(url, join_url(Url, JobName), PushGateway). + +join_url(Url, JobName0) -> + [Name, Ip] = string:tokens(atom_to_list(node()), "@"), + % NOTE: allowing errors here to keep rough backward compatibility + {JobName1, Errors} = emqx_template:render( + emqx_template:parse(JobName0), + #{<<"name">> => Name, <<"host">> => Ip} + ), + _ = + Errors == [] orelse + ?SLOG(warning, #{ + msg => "prometheus_job_name_template_invalid", + errors => Errors, + template => JobName0 + }), + lists:concat([Url, "/metrics/job/", unicode:characters_to_list(JobName1)]). deregister_cleanup(_Registry) -> ok. diff --git a/apps/emqx_prometheus/src/emqx_prometheus_api.erl b/apps/emqx_prometheus/src/emqx_prometheus_api.erl index 987386b61..b08cd8388 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus_api.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus_api.erl @@ -20,8 +20,6 @@ -include_lib("hocon/include/hoconsc.hrl"). --import(hoconsc, [ref/2]). - -export([ api_spec/0, paths/0, @@ -29,11 +27,10 @@ ]). -export([ - prometheus/2, + setting/2, stats/2 ]). --define(SCHEMA_MODULE, emqx_prometheus_schema). -define(TAGS, [<<"Monitor">>]). api_spec() -> @@ -47,21 +44,21 @@ paths() -> schema("/prometheus") -> #{ - 'operationId' => prometheus, + 'operationId' => setting, get => #{ description => ?DESC(get_prom_conf_info), tags => ?TAGS, responses => - #{200 => prometheus_config_schema()} + #{200 => prometheus_setting_schema()} }, put => #{ description => ?DESC(update_prom_conf_info), tags => ?TAGS, - 'requestBody' => prometheus_config_schema(), + 'requestBody' => prometheus_setting_schema(), responses => - #{200 => prometheus_config_schema()} + #{200 => prometheus_setting_schema()} } }; schema("/prometheus/stats") -> @@ -71,19 +68,24 @@ schema("/prometheus/stats") -> #{ description => ?DESC(get_prom_data), tags => ?TAGS, - security => [], + security => security(), responses => #{200 => prometheus_data_schema()} } }. +security() -> + case emqx_config:get([prometheus, enable_basic_auth], false) of + true -> [#{'basicAuth' => []}, #{'bearerAuth' => []}]; + false -> [] + end. %%-------------------------------------------------------------------- %% API Handler funcs %%-------------------------------------------------------------------- -prometheus(get, _Params) -> +setting(get, _Params) -> {200, emqx:get_raw_config([<<"prometheus">>], #{})}; -prometheus(put, #{body := Body}) -> +setting(put, #{body := Body}) -> case emqx_prometheus_config:update(Body) of {ok, NewConfig} -> {200, NewConfig}; @@ -110,20 +112,57 @@ stats(get, #{headers := Headers}) -> %% Internal funcs %%-------------------------------------------------------------------- -prometheus_config_schema() -> - emqx_dashboard_swagger:schema_with_example( - ref(?SCHEMA_MODULE, "prometheus"), - prometheus_config_example() +prometheus_setting_schema() -> + [{prometheus, #{type := Setting}}] = emqx_prometheus_schema:roots(), + emqx_dashboard_swagger:schema_with_examples( + Setting, + [ + recommend_setting_example(), + legacy_setting_example() + ] ). -prometheus_config_example() -> - #{ - enable => true, - interval => "15s", - push_gateway_server => <<"http://127.0.0.1:9091">>, - headers => #{'header-name' => 'header-value'}, - job_name => <<"${name}/instance/${name}~${host}">> - }. +legacy_setting_example() -> + Summary = <<"legacy_deprecated_setting">>, + {Summary, #{ + summary => Summary, + value => #{ + enable => true, + interval => <<"15s">>, + push_gateway_server => <<"http://127.0.0.1:9091">>, + headers => #{<<"Authorization">> => <<"Basic YWRtaW46Y2JraG55eWd5QDE=">>}, + job_name => <<"${name}/instance/${name}~${host}">>, + vm_dist_collector => <<"disabled">>, + vm_memory_collector => <<"disabled">>, + vm_msacc_collector => <<"disabled">>, + mnesia_collector => <<"disabled">>, + vm_statistics_collector => <<"disabled">>, + vm_system_info_collector => <<"disabled">> + } + }}. + +recommend_setting_example() -> + Summary = <<"recommend_setting">>, + {Summary, #{ + summary => Summary, + value => #{ + enable_basic_auth => false, + push_gateway => #{ + interval => <<"15s">>, + url => <<"http://127.0.0.1:9091">>, + headers => #{<<"Authorization">> => <<"Basic YWRtaW46Y2JraG55eWd5QDE=">>}, + job_name => <<"${name}/instance/${name}~${host}">> + }, + collectors => #{ + vm_dist => <<"disabled">>, + vm_memory => <<"disabled">>, + vm_msacc => <<"disabled">>, + mnesia => <<"disabled">>, + vm_statistics => <<"disabled">>, + vm_system_info => <<"disabled">> + } + } + }}. prometheus_data_schema() -> #{ diff --git a/apps/emqx_prometheus/src/emqx_prometheus_config.erl b/apps/emqx_prometheus/src/emqx_prometheus_config.erl index 00dad47f9..66d53f2db 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus_config.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus_config.erl @@ -20,8 +20,9 @@ -include("emqx_prometheus.hrl"). -export([add_handler/0, remove_handler/0]). --export([post_config_update/5]). +-export([pre_config_update/3, post_config_update/5]). -export([update/1]). +-export([conf/0, is_push_gateway_server_enabled/1]). update(Config) -> case @@ -45,9 +46,55 @@ remove_handler() -> ok = emqx_config_handler:remove_handler(?PROMETHEUS), ok. -post_config_update(?PROMETHEUS, _Req, New, _Old, AppEnvs) -> +%% when we import the config with the old version +%% we need to respect it, and convert to new schema. +pre_config_update(?PROMETHEUS, MergeConf, OriginConf) -> + OriginType = emqx_prometheus_schema:is_recommend_type(OriginConf), + MergeType = emqx_prometheus_schema:is_recommend_type(MergeConf), + {ok, + case {OriginType, MergeType} of + {true, false} -> to_recommend_type(MergeConf); + _ -> MergeConf + end}. + +to_recommend_type(Conf) -> + #{ + <<"push_gateway">> => to_push_gateway(Conf), + <<"collectors">> => to_collectors(Conf) + }. + +to_push_gateway(Conf) -> + Init = maps:with([<<"interval">>, <<"headers">>, <<"job_name">>, <<"enable">>], Conf), + case maps:get(<<"push_gateway_server">>, Conf, "") of + "" -> + Init#{<<"enable">> => false}; + Url -> + Init#{<<"url">> => Url} + end. + +to_collectors(Conf) -> + lists:foldl( + fun({From, To}, Acc) -> + case maps:find(From, Conf) of + {ok, Value} -> Acc#{To => Value}; + error -> Acc + end + end, + #{}, + [ + {<<"vm_dist_collector">>, <<"vm_dist">>}, + {<<"mnesia_collector">>, <<"mnesia">>}, + {<<"vm_statistics_collector">>, <<"vm_statistics">>}, + {<<"vm_system_info_collector">>, <<"vm_system_info">>}, + {<<"vm_memory_collector">>, <<"vm_memory">>}, + {<<"vm_msacc_collector">>, <<"vm_msacc">>} + ] + ). + +post_config_update(?PROMETHEUS, _Req, New, Old, AppEnvs) -> update_prometheus(AppEnvs), - update_push_gateway(New); + _ = update_push_gateway(New), + update_auth(New, Old); post_config_update(_ConfPath, _Req, _NewConf, _OldConf, _AppEnvs) -> ok. @@ -64,7 +111,29 @@ update_prometheus(AppEnvs) -> ), application:set_env(AppEnvs). -update_push_gateway(#{enable := true}) -> - emqx_prometheus_sup:start_child(?APP); -update_push_gateway(#{enable := false}) -> - emqx_prometheus_sup:stop_child(?APP). +update_push_gateway(Prometheus) -> + case is_push_gateway_server_enabled(Prometheus) of + true -> + case erlang:whereis(?APP) of + undefined -> emqx_prometheus_sup:start_child(?APP, Prometheus); + Pid -> emqx_prometheus_sup:update_child(Pid, Prometheus) + end; + false -> + emqx_prometheus_sup:stop_child(?APP) + end. + +update_auth(#{enable_basic_auth := New}, #{enable_basic_auth := Old}) when New =/= Old -> + emqx_dashboard_listener:regenerate_minirest_dispatch(), + ok; +update_auth(_, _) -> + ok. + +conf() -> + emqx_config:get(?PROMETHEUS). + +is_push_gateway_server_enabled(#{enable := true, push_gateway_server := Url}) -> + Url =/= ""; +is_push_gateway_server_enabled(#{push_gateway := #{url := Url, enable := Enable}}) -> + Enable andalso Url =/= ""; +is_push_gateway_server_enabled(_) -> + false. diff --git a/apps/emqx_prometheus/src/emqx_prometheus_schema.erl b/apps/emqx_prometheus/src/emqx_prometheus_schema.erl index 3aaf4292f..7df5951f0 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus_schema.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus_schema.erl @@ -27,23 +27,68 @@ desc/1, translation/1, convert_headers/2, - validate_push_gateway_server/1 + validate_url/1, + is_recommend_type/1 ]). -namespace() -> "prometheus". +namespace() -> prometheus. -roots() -> [{"prometheus", ?HOCON(?R_REF("prometheus"), #{translate_to => ["prometheus"]})}]. - -fields("prometheus") -> +roots() -> [ - {push_gateway_server, + {prometheus, + ?HOCON( + ?UNION(setting_union_schema()), + #{translate_to => ["prometheus"], default => #{}} + )} + ]. + +fields(recommend_setting) -> + [ + {enable_basic_auth, + ?HOCON( + boolean(), + #{ + default => false, + required => true, + importance => ?IMPORTANCE_HIGH, + desc => ?DESC(enable_basic_auth) + } + )}, + {push_gateway, + ?HOCON( + ?R_REF(push_gateway), + #{ + required => false, + importance => ?IMPORTANCE_MEDIUM, + desc => ?DESC(push_gateway) + } + )}, + {collectors, + ?HOCON(?R_REF(collectors), #{ + required => false, + importance => ?IMPORTANCE_LOW, + desc => ?DESC(collectors) + })} + ]; +fields(push_gateway) -> + [ + {enable, + ?HOCON( + boolean(), + #{ + default => false, + required => true, + desc => ?DESC(push_gateway_enable) + } + )}, + {url, ?HOCON( string(), #{ + required => false, default => <<"http://127.0.0.1:9091">>, - required => true, - validator => fun ?MODULE:validate_push_gateway_server/1, - desc => ?DESC(push_gateway_server) + validator => fun ?MODULE:validate_url/1, + desc => ?DESC(push_gateway_url) } )}, {interval, @@ -51,7 +96,7 @@ fields("prometheus") -> emqx_schema:timeout_duration_ms(), #{ default => <<"15s">>, - required => true, + required => false, desc => ?DESC(interval) } )}, @@ -70,18 +115,121 @@ fields("prometheus") -> binary(), #{ default => <<"${name}/instance/${name}~${host}">>, - required => true, + required => false, desc => ?DESC(job_name) } + )} + ]; +fields(collectors) -> + [ + {vm_dist, + ?HOCON( + hoconsc:enum([disabled, enabled]), + #{ + default => disabled, + required => true, + desc => ?DESC(vm_dist_collector) + } + )}, + %% Mnesia metrics mainly using mnesia:system_info/1 + {mnesia, + ?HOCON( + hoconsc:enum([enabled, disabled]), + #{ + default => disabled, + required => true, + desc => ?DESC(mnesia_collector) + } + )}, + %% Collects Erlang VM metrics using erlang:statistics/1. + {vm_statistics, + ?HOCON( + hoconsc:enum([enabled, disabled]), + #{ + default => disabled, + required => true, + desc => ?DESC(vm_statistics_collector) + } + )}, + %% Collects Erlang VM metrics using erlang:system_info/1. + {vm_system_info, + ?HOCON( + hoconsc:enum([enabled, disabled]), + #{ + default => disabled, + required => true, + desc => ?DESC(vm_system_info_collector) + } + )}, + %% Collects information about memory dynamically allocated by the Erlang VM using erlang:memory/0, + %% it also provides basic (D)ETS statistics. + {vm_memory, + ?HOCON( + hoconsc:enum([enabled, disabled]), + #{ + default => disabled, + required => true, + desc => ?DESC(vm_memory_collector) + } + )}, + %% Collects microstate accounting metrics using erlang:statistics(microstate_accounting). + {vm_msacc, + ?HOCON( + hoconsc:enum([enabled, disabled]), + #{ + default => disabled, + required => true, + desc => ?DESC(vm_msacc_collector) + } + )} + ]; +fields(legacy_deprecated_setting) -> + [ + {push_gateway_server, + ?HOCON( + string(), + #{ + default => <<"http://127.0.0.1:9091">>, + required => true, + validator => fun ?MODULE:validate_url/1, + desc => ?DESC(legacy_push_gateway_server) + } + )}, + {interval, + ?HOCON( + emqx_schema:timeout_duration_ms(), + #{ + default => <<"15s">>, + required => true, + desc => ?DESC(legacy_interval) + } + )}, + {headers, + ?HOCON( + typerefl:alias("map", list({string(), string()}), #{}, [string(), string()]), + #{ + default => #{}, + required => false, + converter => fun ?MODULE:convert_headers/2, + desc => ?DESC(legacy_headers) + } + )}, + {job_name, + ?HOCON( + binary(), + #{ + default => <<"${name}/instance/${name}~${host}">>, + required => true, + desc => ?DESC(legacy_job_name) + } )}, - {enable, ?HOCON( boolean(), #{ default => false, required => true, - desc => ?DESC(enable) + desc => ?DESC(legacy_enable) } )}, {vm_dist_collector, @@ -91,7 +239,7 @@ fields("prometheus") -> default => disabled, required => true, importance => ?IMPORTANCE_LOW, - desc => ?DESC(vm_dist_collector) + desc => ?DESC(legacy_vm_dist_collector) } )}, %% Mnesia metrics mainly using mnesia:system_info/1 @@ -102,7 +250,7 @@ fields("prometheus") -> default => disabled, required => true, importance => ?IMPORTANCE_LOW, - desc => ?DESC(mnesia_collector) + desc => ?DESC(legacy_mnesia_collector) } )}, %% Collects Erlang VM metrics using erlang:statistics/1. @@ -113,7 +261,7 @@ fields("prometheus") -> default => disabled, required => true, importance => ?IMPORTANCE_LOW, - desc => ?DESC(vm_statistics_collector) + desc => ?DESC(legacy_vm_statistics_collector) } )}, %% Collects Erlang VM metrics using erlang:system_info/1. @@ -124,7 +272,7 @@ fields("prometheus") -> default => disabled, required => true, importance => ?IMPORTANCE_LOW, - desc => ?DESC(vm_system_info_collector) + desc => ?DESC(legacy_vm_system_info_collector) } )}, %% Collects information about memory dynamically allocated by the Erlang VM using erlang:memory/0, @@ -136,7 +284,7 @@ fields("prometheus") -> default => disabled, required => true, importance => ?IMPORTANCE_LOW, - desc => ?DESC(vm_memory_collector) + desc => ?DESC(legacy_vm_memory_collector) } )}, %% Collects microstate accounting metrics using erlang:statistics(microstate_accounting). @@ -147,14 +295,48 @@ fields("prometheus") -> default => disabled, required => true, importance => ?IMPORTANCE_LOW, - desc => ?DESC(vm_msacc_collector) + desc => ?DESC(legacy_vm_msacc_collector) } )} ]. -desc("prometheus") -> ?DESC(prometheus); +setting_union_schema() -> + RecommendSetting = ?R_REF(recommend_setting), + LegacySetting = ?R_REF(legacy_deprecated_setting), + fun + (all_union_members) -> + [RecommendSetting, LegacySetting]; + ({value, Setting}) -> + case is_recommend_type(Setting) of + true -> [RecommendSetting]; + false -> [LegacySetting] + end + end. + +%% For it to be considered as new schema, +%% all keys must be included in the new configuration. +is_recommend_type(Setting) -> + case maps:keys(Setting) of + [] -> + true; + Keys -> + NewKeys = fields(recommend_setting), + Fun = fun(Key0) -> + Key = binary_to_existing_atom(Key0), + lists:keymember(Key, 1, NewKeys) + end, + lists:all(Fun, Keys) + end. + +desc(prometheus) -> ?DESC(prometheus); +desc(collectors) -> ?DESC(collectors); +desc(legacy_deprecated_setting) -> ?DESC(legacy_deprecated_setting); +desc(recommend_setting) -> ?DESC(recommend_setting); +desc(push_gateway) -> ?DESC(push_gateway); desc(_) -> undefined. +convert_headers(undefined, _) -> + undefined; convert_headers(Headers, #{make_serializable := true}) -> Headers; convert_headers(<<>>, _Opts) -> @@ -170,10 +352,17 @@ convert_headers(Headers, _Opts) when is_map(Headers) -> convert_headers(Headers, _Opts) when is_list(Headers) -> Headers. -validate_push_gateway_server(Url) -> +validate_url(Url) -> case uri_string:parse(Url) of - #{scheme := S} when S =:= "https" orelse S =:= "http" -> ok; - _ -> {error, "Invalid url"} + #{scheme := S} when + S =:= "https"; + S =:= "http"; + S =:= <<"https">>; + S =:= <<"http">> + -> + ok; + _ -> + {error, "Invalid url"} end. %% for CI test, CI don't load the whole emqx_conf_schema. diff --git a/apps/emqx_prometheus/src/emqx_prometheus_sup.erl b/apps/emqx_prometheus/src/emqx_prometheus_sup.erl index c284328ff..ea8a2ebaa 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus_sup.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus_sup.erl @@ -21,6 +21,8 @@ -export([ start_link/0, start_child/1, + start_child/2, + update_child/2, stop_child/1 ]). @@ -39,11 +41,18 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). --spec start_child(supervisor:child_spec() | atom()) -> ok. -start_child(ChildSpec) when is_map(ChildSpec) -> - assert_started(supervisor:start_child(?MODULE, ChildSpec)); +-spec start_child(atom()) -> ok. start_child(Mod) when is_atom(Mod) -> - assert_started(supervisor:start_child(?MODULE, ?CHILD(Mod, []))). + start_child(Mod, emqx_prometheus_config:conf()). + +-spec start_child(atom(), map()) -> ok. +start_child(Mod, Conf) when is_atom(Mod) -> + assert_started(supervisor:start_child(?MODULE, ?CHILD(Mod, Conf))). + +-spec update_child(pid() | atom(), map()) -> ok. +update_child(Pid, Conf) -> + erlang:send(Pid, {update, Conf}), + ok. -spec stop_child(any()) -> ok | {error, term()}. stop_child(ChildId) -> @@ -54,10 +63,11 @@ stop_child(ChildId) -> end. init([]) -> + Conf = emqx_prometheus_config:conf(), Children = - case emqx_conf:get([prometheus, enable], false) of + case emqx_prometheus_config:is_push_gateway_server_enabled(Conf) of false -> []; - true -> [?CHILD(emqx_prometheus, [])] + true -> [?CHILD(emqx_prometheus, Conf)] end, {ok, {{one_for_one, 10, 3600}, Children}}. diff --git a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl index 3f9e743f3..c50813938 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl @@ -22,7 +22,7 @@ -compile(export_all). -define(CLUSTER_RPC_SHARD, emqx_cluster_rpc_shard). --define(CONF_DEFAULT, << +-define(LEGACY_CONF_DEFAULT, << "\n" "prometheus {\n" " push_gateway_server = \"http://127.0.0.1:9091\"\n" @@ -38,45 +38,121 @@ " vm_msacc_collector = disabled\n" "}\n" >>). +-define(CONF_DEFAULT, #{ + <<"prometheus">> => + #{ + <<"enable_basic_auth">> => false, + <<"collectors">> => + #{ + <<"mnesia">> => <<"disabled">>, + <<"vm_dist">> => <<"disabled">>, + <<"vm_memory">> => <<"disabled">>, + <<"vm_msacc">> => <<"disabled">>, + <<"vm_statistics">> => <<"disabled">>, + <<"vm_system_info">> => <<"disabled">> + }, + <<"push_gateway">> => + #{ + <<"enable">> => true, + <<"headers">> => #{<<"Authorization">> => <<"some-authz-tokens">>}, + <<"interval">> => <<"1s">>, + <<"job_name">> => <<"${name}~${host}">>, + <<"url">> => <<"http://127.0.0.1:9091">> + } + } +}). %%-------------------------------------------------------------------- %% Setups %%-------------------------------------------------------------------- +all() -> + [ + {group, new_config}, + {group, legacy_config} + ]. -all() -> emqx_common_test_helpers:all(?MODULE). +groups() -> + [ + {new_config, [sequence], common_tests()}, + {legacy_config, [sequence], common_tests()} + ]. -init_per_suite(Cfg) -> +suite() -> + [{timetrap, {seconds, 30}}]. + +common_tests() -> + emqx_common_test_helpers:all(?MODULE). + +init_per_group(new_config, Config) -> + init_group(), + load_config(), + emqx_common_test_helpers:start_apps([emqx_prometheus]), + %% coverage olp metrics + {ok, _} = emqx:update_config([overload_protection, enable], true), + Config; +init_per_group(legacy_config, Config) -> + init_group(), + load_legacy_config(), + emqx_common_test_helpers:start_apps([emqx_prometheus]), + {ok, _} = emqx:update_config([overload_protection, enable], false), + Config. + +init_group() -> application:load(emqx_conf), ok = ekka:start(), ok = mria_rlog:wait_for_shards([?CLUSTER_RPC_SHARD], infinity), meck:new(emqx_alarm, [non_strict, passthrough, no_link]), meck:expect(emqx_alarm, activate, 3, ok), - meck:expect(emqx_alarm, deactivate, 3, ok), + meck:expect(emqx_alarm, deactivate, 3, ok). - load_config(), - emqx_common_test_helpers:start_apps([emqx_prometheus]), - Cfg. - -end_per_suite(_Cfg) -> +end_group() -> ekka:stop(), mria:stop(), mria_mnesia:delete_schema(), meck:unload(emqx_alarm), - emqx_common_test_helpers:stop_apps([emqx_prometheus]). +end_per_group(_Group, Config) -> + end_group(), + Config. + +init_per_testcase(t_assert_push, Config) -> + meck:new(httpc, [passthrough]), + Config; +init_per_testcase(t_push_gateway, Config) -> + start_mock_pushgateway(9091), + Config; +init_per_testcase(_Testcase, Config) -> + Config. + +end_per_testcase(t_push_gateway, Config) -> + stop_mock_pushgateway(), + Config; +end_per_testcase(t_assert_push, _Config) -> + meck:unload(httpc), + ok; +end_per_testcase(_Testcase, _Config) -> + ok. + load_config() -> ok = emqx_common_test_helpers:load_config(emqx_prometheus_schema, ?CONF_DEFAULT). +load_legacy_config() -> + ok = emqx_common_test_helpers:load_config(emqx_prometheus_schema, ?LEGACY_CONF_DEFAULT). + %%-------------------------------------------------------------------- %% Test cases %%-------------------------------------------------------------------- t_start_stop(_) -> App = emqx_prometheus, - ?assertMatch(ok, emqx_prometheus_sup:start_child(App)), + Conf = emqx_prometheus_config:conf(), + ?assertMatch(ok, emqx_prometheus_sup:start_child(App, Conf)), %% start twice return ok. - ?assertMatch(ok, emqx_prometheus_sup:start_child(App)), + ?assertMatch(ok, emqx_prometheus_sup:start_child(App, Conf)), + ok = gen_server:call(emqx_prometheus, dump, 1000), + ok = gen_server:cast(emqx_prometheus, dump), + dump = erlang:send(emqx_prometheus, dump), ?assertMatch(ok, emqx_prometheus_sup:stop_child(App)), %% stop twice return ok. ?assertMatch(ok, emqx_prometheus_sup:stop_child(App)), @@ -88,7 +164,6 @@ t_collector_no_crash_test(_) -> ok. t_assert_push(_) -> - meck:new(httpc, [passthrough]), Self = self(), AssertPush = fun(Method, Req = {Url, Headers, ContentType, _Data}, HttpOpts, Opts) -> ?assertEqual(post, Method), @@ -99,13 +174,51 @@ t_assert_push(_) -> meck:passthrough([Method, Req, HttpOpts, Opts]) end, meck:expect(httpc, request, AssertPush), - ?assertMatch(ok, emqx_prometheus_sup:start_child(emqx_prometheus)), + Conf = emqx_prometheus_config:conf(), + ?assertMatch(ok, emqx_prometheus_sup:start_child(emqx_prometheus, Conf)), receive pass -> ok after 2000 -> ct:fail(assert_push_request_failed) end. -t_only_for_coverage(_) -> - ?assertEqual("5.0.0", emqx_prometheus_proto_v1:introduced_in()), +t_push_gateway(_) -> + Conf = emqx_prometheus_config:conf(), + ?assertMatch(ok, emqx_prometheus_sup:stop_child(emqx_prometheus)), + ?assertMatch(ok, emqx_prometheus_sup:start_child(emqx_prometheus, Conf)), + ?assertMatch(#{ok := 0, failed := 0}, emqx_prometheus:info()), + timer:sleep(1100), + ?assertMatch(#{ok := 1, failed := 0}, emqx_prometheus:info()), + ok = emqx_prometheus_sup:update_child(emqx_prometheus, Conf), + ?assertMatch(#{ok := 0, failed := 0}, emqx_prometheus:info()), + ok. + +start_mock_pushgateway(Port) -> + application:ensure_all_started(cowboy), + Dispatch = cowboy_router:compile([{'_', [{'_', ?MODULE, []}]}]), + {ok, _} = cowboy:start_clear( + mock_pushgateway_listener, + [{port, Port}], + #{env => #{dispatch => Dispatch}} + ). + +stop_mock_pushgateway() -> + cowboy:stop_listener(mock_pushgateway_listener). + +init(Req0, Opts) -> + Method = cowboy_req:method(Req0), + Headers = cowboy_req:headers(Req0), + ?assertEqual(<<"POST">>, Method), + ?assertMatch( + #{ + <<"authorization">> := <<"some-authz-tokens">>, + <<"content-length">> := _, + <<"content-type">> := <<"text/plain">>, + <<"host">> := <<"127.0.0.1:9091">> + }, + Headers + ), + RespHeader = #{<<"content-type">> => <<"text/plain; charset=utf-8">>}, + Req = cowboy_req:reply(200, RespHeader, <<"OK">>, Req0), + {ok, Req, Opts}. diff --git a/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl index eb909baf5..ad2b3d5ec 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl @@ -28,40 +28,59 @@ %%-------------------------------------------------------------------- %% Setups %%-------------------------------------------------------------------- - all() -> - emqx_common_test_helpers:all(?MODULE). + [ + {group, new_config}, + {group, legacy_config} + ]. + +groups() -> + [ + {new_config, [sequence], [t_stats_auth_api, t_stats_no_auth_api, t_prometheus_api]}, + {legacy_config, [sequence], [t_stats_no_auth_api, t_legacy_prometheus_api]} + ]. init_per_suite(Config) -> - application:load(emqx_conf), - ok = ekka:start(), - ok = mria_rlog:wait_for_shards([?CLUSTER_RPC_SHARD], infinity), - - meck:new(mria_rlog, [non_strict, passthrough, no_link]), - - emqx_prometheus_SUITE:load_config(), - emqx_mgmt_api_test_util:init_suite([emqx_prometheus]), - + emqx_prometheus_SUITE:init_group(), + emqx_mgmt_api_test_util:init_suite([emqx_conf]), Config. - end_per_suite(Config) -> - ekka:stop(), - mria:stop(), - mria_mnesia:delete_schema(), - - meck:unload(mria_rlog), - - emqx_mgmt_api_test_util:end_suite([emqx_prometheus]), + emqx_prometheus_SUITE:end_group(), + emqx_mgmt_api_test_util:end_suite([emqx_conf]), Config. -init_per_testcase(_, Config) -> - {ok, _} = emqx_cluster_rpc:start_link(), +init_per_group(new_config, Config) -> + emqx_common_test_helpers:start_apps( + [emqx_prometheus], + fun(App) -> set_special_configs(App, new_config) end + ), + Config; +init_per_group(legacy_config, Config) -> + emqx_common_test_helpers:start_apps( + [emqx_prometheus], + fun(App) -> set_special_configs(App, legacy_config) end + ), Config. +end_per_group(_Group, Config) -> + _ = application:stop(emqx_prometheus), + Config. + +set_special_configs(emqx_dashboard, _) -> + emqx_dashboard_api_test_helpers:set_default_config(); +set_special_configs(emqx_prometheus, new_config) -> + emqx_prometheus_SUITE:load_config(), + ok; +set_special_configs(emqx_prometheus, legacy_config) -> + emqx_prometheus_SUITE:load_legacy_config(), + ok; +set_special_configs(_App, _) -> + ok. + %%-------------------------------------------------------------------- %% Cases %%-------------------------------------------------------------------- -t_prometheus_api(_) -> +t_legacy_prometheus_api(_) -> Path = emqx_mgmt_api_test_util:api_path(["prometheus"]), Auth = emqx_mgmt_api_test_util:auth_header_(), {ok, Response} = emqx_mgmt_api_test_util:request_api(get, Path, "", Auth), @@ -145,21 +164,133 @@ t_prometheus_api(_) -> ), ok. -t_stats_api(_) -> - Path = emqx_mgmt_api_test_util:api_path(["prometheus", "stats"]), +t_prometheus_api(_) -> + Path = emqx_mgmt_api_test_util:api_path(["prometheus"]), Auth = emqx_mgmt_api_test_util:auth_header_(), - Headers = [{"accept", "application/json"}, Auth], - {ok, Response} = emqx_mgmt_api_test_util:request_api(get, Path, "", Headers), + {ok, Response} = emqx_mgmt_api_test_util:request_api(get, Path, "", Auth), + Conf = emqx_utils_json:decode(Response, [return_maps]), + ?assertMatch( + #{ + <<"push_gateway">> := #{}, + <<"collectors">> := _, + <<"enable_basic_auth">> := _ + }, + Conf + ), + #{ + <<"push_gateway">> := + #{<<"url">> := Url, <<"enable">> := Enable} = PushGateway, + <<"collectors">> := Collector + } = Conf, + Pid = erlang:whereis(emqx_prometheus), + ?assertEqual(Enable, undefined =/= Pid, {Url, Pid}), + + NewConf = Conf#{ + <<"push_gateway">> => PushGateway#{ + <<"interval">> => <<"2s">>, + <<"headers">> => #{ + <<"test-str1">> => <<"test-value">>, + <<"test-str2">> => <<"42">> + } + }, + <<"collectors">> => Collector#{ + <<"vm_dist">> => <<"enabled">>, + <<"vm_system_info">> => <<"enabled">>, + <<"vm_memory">> => <<"enabled">>, + <<"vm_msacc">> => <<"enabled">>, + <<"mnesia">> => <<"enabled">>, + <<"vm_statistics">> => <<"enabled">> + } + }, + {ok, Response2} = emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, NewConf), + + Conf2 = emqx_utils_json:decode(Response2, [return_maps]), + ?assertMatch(NewConf, Conf2), + + EnvCollectors = application:get_env(prometheus, collectors, []), + PromCollectors = prometheus_registry:collectors(default), + ?assertEqual(lists:sort(EnvCollectors), lists:sort(PromCollectors)), + ?assert(lists:member(prometheus_vm_statistics_collector, EnvCollectors), EnvCollectors), + + lists:foreach( + fun({C, Enabled}) -> + ?assertEqual(Enabled, lists:member(C, EnvCollectors), EnvCollectors) + end, + [ + {prometheus_vm_dist_collector, true}, + {prometheus_vm_system_info_collector, true}, + {prometheus_vm_memory_collector, true}, + {prometheus_mnesia_collector, true}, + {prometheus_vm_msacc_collector, true}, + {prometheus_vm_statistics_collector, true} + ] + ), + + ?assertMatch( + #{ + <<"push_gateway">> := #{ + <<"headers">> := #{ + <<"test-str1">> := <<"test-value">>, + <<"test-str2">> := <<"42">> + } + } + }, + emqx_config:get_raw([prometheus]) + ), + ?assertMatch( + #{ + push_gateway := #{ + headers := [ + {"test-str2", "42"}, + {"test-str1", "test-value"} + ] + } + }, + emqx_config:get([prometheus]) + ), + + NewConf1 = Conf#{<<"push_gateway">> => PushGateway#{<<"enable">> => false}}, + {ok, _Response3} = emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, NewConf1), + ?assertEqual(undefined, erlang:whereis(emqx_prometheus)), + + ConfWithoutScheme = Conf#{ + <<"push_gateway">> => PushGateway#{<<"url">> => <<"127.0.0.1:8081">>} + }, + ?assertMatch( + {error, {"HTTP/1.1", 400, _}}, + emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, ConfWithoutScheme) + ), + ok. + +t_stats_no_auth_api(_) -> + %% undefined is legacy prometheus + case emqx:get_config([prometheus, enable_basic_auth], undefined) of + true -> + {ok, _} = emqx:update_config([prometheus, enable_basic_auth], false), + emqx_dashboard_listener:regenerate_minirest_dispatch(); + _ -> + ok + end, + emqx_dashboard_listener:regenerate_minirest_dispatch(), + Json = [{"accept", "application/json"}], + request_stats(Json, []). + +t_stats_auth_api(_) -> + {ok, _} = emqx:update_config([prometheus, enable_basic_auth], true), + Auth = emqx_mgmt_api_test_util:auth_header_(), + JsonAuth = [{"accept", "application/json"}, Auth], + request_stats(JsonAuth, Auth), + ok. + +request_stats(JsonAuth, Auth) -> + Path = emqx_mgmt_api_test_util:api_path(["prometheus", "stats"]), + {ok, Response} = emqx_mgmt_api_test_util:request_api(get, Path, "", JsonAuth), Data = emqx_utils_json:decode(Response, [return_maps]), ?assertMatch(#{<<"client">> := _, <<"delivery">> := _}, Data), - {ok, _} = emqx_mgmt_api_test_util:request_api(get, Path, "", Auth), - ok = meck:expect(mria_rlog, backend, fun() -> rlog end), - {ok, _} = emqx_mgmt_api_test_util:request_api(get, Path, "", Auth), - - ok. + {ok, _} = emqx_mgmt_api_test_util:request_api(get, Path, "", Auth). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Internal Functions diff --git a/changes/ce/feat-11884.en.md b/changes/ce/feat-11884.en.md new file mode 100644 index 000000000..66d2b0a8e --- /dev/null +++ b/changes/ce/feat-11884.en.md @@ -0,0 +1,4 @@ +Modified the Prometheus API and configuration to: +- Restructure configuration sections to group related settings, improving readability and maintainability +- Introduced `enable_basic_auth` configuration for basic authentication on the scrape API endpoint, enhancing security +- Maintained backwards compatibility while refactoring code, avoiding breaking changes diff --git a/rel/config/examples/prometheus.conf.example b/rel/config/examples/prometheus.conf.example index 3b186e93f..049b11ee3 100644 --- a/rel/config/examples/prometheus.conf.example +++ b/rel/config/examples/prometheus.conf.example @@ -1,10 +1,24 @@ ## Prometheus ## EMQX's Prometheus scraping endpoint is enabled by default without authentication. -## And there is no way to turn it off. +## You can enable basic authentication by setting enable_basic_auth to true. ## You can inspect it with a curl command: curl -f "127.0.0.1:18083/api/v5/prometheus/stats" prometheus { - # turn off this expensive collector - vm_dist_collector = disabled + enable_basic_auth = false + push_gateway { + enable = false + url = "http://127.0.0.1:9091" + headers {Authorization = "Basic YWRtaW46Y2JraG55eWd5QDE="} + interval = 15s + job_name = "${name}/instance/${name}~${host}" + } + collectors { + mnesia = disabled + vm_dist = disabled + vm_memory = disabled + vm_msacc = disabled + vm_statistics = disabled + vm_system_info = enabled + } } diff --git a/rel/i18n/emqx_prometheus_api.hocon b/rel/i18n/emqx_prometheus_api.hocon index c468ccc2f..0d9b5dc5f 100644 --- a/rel/i18n/emqx_prometheus_api.hocon +++ b/rel/i18n/emqx_prometheus_api.hocon @@ -11,8 +11,8 @@ update_prom_conf_info.label: """Update Prometheus config""" get_prom_data.desc: -"""Get Prometheus Data""" +"""Get Prometheus Metrics""" get_prom_data.label: -"""Get Prometheus Data""" +"""Prometheus Metrics""" } diff --git a/rel/i18n/emqx_prometheus_schema.hocon b/rel/i18n/emqx_prometheus_schema.hocon index d665343e9..ef507b520 100644 --- a/rel/i18n/emqx_prometheus_schema.hocon +++ b/rel/i18n/emqx_prometheus_schema.hocon @@ -1,8 +1,5 @@ emqx_prometheus_schema { -enable.desc: -"""Turn Prometheus data pushing on or off""" - headers.desc: """An HTTP Headers when pushing to Push Gateway.
For example, { Authorization = "some-authz-tokens"}""" @@ -14,28 +11,46 @@ job_name.desc: """Job Name that is pushed to the Push Gateway. Available variables:
- ${name}: Name of EMQX node.
- ${host}: Host name of EMQX node.
-For example, when the EMQX node name is emqx@127.0.0.1 then the name variable takes value emqx and the host variable takes value 127.0.0.1.
+For example, when the EMQX node name is emqx@127.0.0.1 then the name +variable takes value emqx and the host variable takes value 127.0.0.1. Default value is: ${name}/instance/${name}~${host}""" -mnesia_collector.desc: -"""Enable or disable Mnesia metrics collector""" - prometheus.desc: """EMQX's Prometheus scraping endpoint is enabled by default without authentication. -You can inspect it with a `curl` command like this: `curl -f "127.0.0.1:18083/api/v5/prometheus/stats"`
-The 'enable' flag is used to turn on and off for the push-gateway integration.""" +You can inspect it with a `curl` command like this: `curl -f "127.0.0.1:18083/api/v5/prometheus/stats"`""" prometheus.label: """Prometheus""" -push_gateway_server.desc: -"""URL of Prometheus server. Pushgateway is optional, should not be configured if prometheus is to scrape EMQX.""" +push_gateway.desc: +"""Push Gateway is optional, should not be configured if prometheus is to scrape EMQX.""" + +enable_basic_auth.desc: +"""Enable or disable basic authentication for prometheus scrape api, not for Push Gateway""" + +collectors.desc: +"""The internal advanced metrics of the virtual machine are initially disabled +and are usually only enabled during performance testing. +Enabling them will increase the CPU load.""" + +recommend_setting.desc: +"""Recommended setting""" + +push_gateway_url.desc: +"""URL of Pushgateway server. Pushgateway is optional, should not be configured if prometheus is to scrape EMQX.""" +push_gateway_enable.desc: +"""Enable or disable Pushgateway""" + +mnesia_collector.desc: +"""Collects Mnesia metrics mainly using mnesia:system_info/1 """ vm_dist_collector.desc: -"""Enable or disable VM distribution collector, collects information about the sockets and processes involved in the Erlang distribution mechanism.""" +"""Enable or disable VM distribution collector, +collects information about the sockets and processes involved in the Erlang distribution mechanism.""" vm_memory_collector.desc: -"""Enable or disable VM memory metrics collector.""" +"""Collects information about memory dynamically allocated by the Erlang emulator using + erlang:memory/0 .""" vm_msacc_collector.desc: """Enable or disable VM microstate accounting metrics collector.""" @@ -46,4 +61,43 @@ vm_statistics_collector.desc: vm_system_info_collector.desc: """Enable or disable VM system info collector.""" +legacy_deprecated_setting.desc: +"""Deprecated since 5.4.0""" + +legacy_enable.desc: +"""Deprecated since 5.4.0, use `prometheus.push_gateway.url` instead""" + +legacy_headers.desc: +"""Deprecated since 5.4.0, use `prometheus.push_gateway.headers` instead""" + +legacy_interval.desc: +"""Deprecated since 5.4.0, use `prometheus.push_gateway.interval` instead""" + +legacy_job_name.desc: +"""Deprecated since 5.4.0, use `prometheus.push_gateway.job_name` instead""" + +legacy_push_gateway_server.desc: +"""Deprecated since 5.4.0, use `prometheus.push_gateway.url` instead""" + +legacy_mnesia_collector.desc: +"""Deprecated since 5.4.0, use `prometheus.collectors.mnesia` instead""" + +legacy_vm_dist_collector.desc: +"""Deprecated since 5.4.0, use `prometheus.collectors.vm_dist` instead""" + +legacy_vm_memory_collector.desc: +"""Deprecated since 5.4.0, use `prometheus.collectors.vm_memory` instead""" + +legacy_vm_msacc_collector.desc: +"""Deprecated since 5.4.0, use `prometheus.collectors.vm_msacc` instead""" + +legacy_vm_statistics_collector.desc: +"""Deprecated since 5.4.0, use `prometheus.collectors.vm_statistics` instead""" + +legacy_vm_system_info_collector.desc: +"""Deprecated, use `prometheus.collectors.vm_system_info` instead""" + +legacy_deprecated_setting.desc: +"""Deprecated since 5.4.0""" + } diff --git a/scripts/spellcheck/dicts/emqx.txt b/scripts/spellcheck/dicts/emqx.txt index 5630404c3..bc05df68a 100644 --- a/scripts/spellcheck/dicts/emqx.txt +++ b/scripts/spellcheck/dicts/emqx.txt @@ -295,3 +295,4 @@ dnstream upstream priv Syskeeper +msacc