diff --git a/elvis.config b/elvis.config index de6df82..04894b8 100644 --- a/elvis.config +++ b/elvis.config @@ -20,11 +20,12 @@ #{ignore => [ prometheus_misc, prometheus_registry, - prometheus_sup, + prometheus_startup, prometheus_instrumenter ]}}, {elvis_style, god_modules, #{limit => 54}}, - {elvis_style, dont_repeat_yourself, #{min_complexity => 50}} + {elvis_style, dont_repeat_yourself, #{min_complexity => 50}}, + {elvis_style, state_record_and_type, #{ignore => [prometheus_startup]}} ], ruleset => erl_files }, @@ -80,4 +81,4 @@ } ] } -]. +]. \ No newline at end of file diff --git a/src/prometheus_startup.erl b/src/prometheus_startup.erl new file mode 100644 index 0000000..4f22349 --- /dev/null +++ b/src/prometheus_startup.erl @@ -0,0 +1,107 @@ +-module(prometheus_startup). + +-behaviour(gen_server). + +-include("prometheus.hrl"). + +-export([start_link/0]). +-export([init/1, handle_continue/2, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). +-export([register_metrics/1]). + +start_link() -> + gen_server:start_link(?MODULE, [], []). + +%%% Server functions +init([]) -> + create_tables(), + {ok, [], {continue, []}}. + +handle_continue(_Continue, _State) -> + register_collectors(), + register_metrics(), + setup_instrumenters(), + {noreply, []}. + +%% Gen Server boilerplate + +handle_call(_Request, _From, State) -> + {reply, ignored, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%% Private functions + +create_tables() -> + Tables = + [{?PROMETHEUS_REGISTRY_TABLE, {bag, read_concurrency}}, + {?PROMETHEUS_COUNTER_TABLE, write_concurrency}, + {?PROMETHEUS_GAUGE_TABLE, write_concurrency}, + {?PROMETHEUS_SUMMARY_TABLE, write_concurrency}, + {?PROMETHEUS_QUANTILE_SUMMARY_TABLE, write_concurrency}, + {?PROMETHEUS_HISTOGRAM_TABLE, write_concurrency}, + {?PROMETHEUS_BOOLEAN_TABLE, write_concurrency}], + [maybe_create_table(Name, Concurrency) || {Name, Concurrency} <- Tables], + ok. + +register_collectors() -> + Collectors = prometheus_collector:enabled_collectors(), + prometheus_registry:register_collectors(Collectors). + +register_metrics() -> + [declare_metric(Decl) || Decl <- default_metrics()]. + +register_metrics(Metrics) -> + DefaultMetrics0 = default_metrics(), + DefaultMetrics1 = lists:usort(DefaultMetrics0 ++ Metrics), + application:set_env(prometheus, default_metrics, DefaultMetrics1), + [declare_metric(Decl) || Decl <- Metrics]. + +setup_instrumenters() -> + [prometheus_instrumenter:setup(Instrumenter) + || Instrumenter <- prometheus_instrumenter:enabled_instrumenters()]. + +default_metrics() -> + application:get_env(prometheus, default_metrics, []). + +maybe_create_table(Name, {Type, Concurrency}) -> + case ets:info(Name) of + undefined -> + ets:new(Name, [Type, named_table, public, {Concurrency, true}]); + _ -> + ok + end; +maybe_create_table(Name, Concurrency) -> + maybe_create_table(Name, {set, Concurrency}). + +declare_metric({Metric, Spec}) -> + declare_metric(Metric, Spec); +declare_metric({Registry, Metric, Spec}) -> + declare_metric(Metric, [{registry, Registry}] ++ Spec). + +declare_metric(Metric, Spec) -> + Module = type_to_module(Metric), + Module:declare(Spec). + +type_to_module(counter) -> + prometheus_counter; +type_to_module(gauge) -> + prometheus_gauge; +type_to_module(summary) -> + prometheus_summary; +type_to_module(histogram) -> + prometheus_histogram; +type_to_module(boolean) -> + prometheus_boolean; +type_to_module(Type) -> + Type. \ No newline at end of file diff --git a/src/prometheus_sup.erl b/src/prometheus_sup.erl index de73fc1..211ad1b 100644 --- a/src/prometheus_sup.erl +++ b/src/prometheus_sup.erl @@ -9,12 +9,9 @@ -export([start_link/0]). %% Supervisor callbacks -export([init/1]). --export([register_metrics/1]). -behaviour(supervisor). --include("prometheus.hrl"). - %%==================================================================== %% Macros %%==================================================================== @@ -34,77 +31,11 @@ start_link() -> %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> - create_tables(), - register_collectors(), - register_metrics(), - setup_instrumenters(), - {ok, {{one_for_one, 5, 1}, []}}. - -%%==================================================================== -%% Private Parts -%%==================================================================== - -create_tables() -> - Tables = [ - {?PROMETHEUS_REGISTRY_TABLE, {bag, read_concurrency}}, - {?PROMETHEUS_COUNTER_TABLE, write_concurrency}, - {?PROMETHEUS_GAUGE_TABLE, write_concurrency}, - {?PROMETHEUS_SUMMARY_TABLE, write_concurrency}, - {?PROMETHEUS_QUANTILE_SUMMARY_TABLE, write_concurrency}, - {?PROMETHEUS_HISTOGRAM_TABLE, write_concurrency}, - {?PROMETHEUS_BOOLEAN_TABLE, write_concurrency} - ], - [maybe_create_table(Name, Concurrency) || {Name, Concurrency} <- Tables], - ok. - -register_collectors() -> - Collectors = prometheus_collector:enabled_collectors(), - prometheus_registry:register_collectors(Collectors). - -register_metrics() -> - [declare_metric(Decl) || Decl <- default_metrics()]. - -register_metrics(Metrics) -> - DefaultMetrics0 = default_metrics(), - DefaultMetrics1 = lists:usort(DefaultMetrics0 ++ Metrics), - application:set_env(prometheus, default_metrics, DefaultMetrics1), - [declare_metric(Decl) || Decl <- Metrics]. - -setup_instrumenters() -> - [prometheus_instrumenter:setup(Instrumenter) || - Instrumenter <- prometheus_instrumenter:enabled_instrumenters()]. - -default_metrics() -> - application:get_env(prometheus, default_metrics, []). - -maybe_create_table(Name, {Type, Concurrency}) -> - case ets:info(Name) of - undefined -> - ets:new(Name, [Type, named_table, public, {Concurrency, true}]); - _ -> - ok - end; -maybe_create_table(Name, Concurrency) -> - maybe_create_table(Name, {set, Concurrency}). - -declare_metric({Metric, Spec}) -> - declare_metric(Metric, Spec); -declare_metric({Registry, Metric, Spec}) -> - declare_metric(Metric, [{registry, Registry}] ++ Spec). - -declare_metric(Metric, Spec) -> - Module = type_to_module(Metric), - Module:declare(Spec). - -type_to_module(counter) -> - prometheus_counter; -type_to_module(gauge) -> - prometheus_gauge; -type_to_module(summary) -> - prometheus_summary; -type_to_module(histogram) -> - prometheus_histogram; -type_to_module(boolean) -> - prometheus_boolean; -type_to_module(Type) -> - Type. + ChildSpec = + [{prometheus_startup_server, + {prometheus_startup, start_link, []}, + permanent, + 1000, + worker, + [prometheus_startup]}], + {ok, {{one_for_one, 5, 1}, ChildSpec}}. \ No newline at end of file diff --git a/test/eunit/prometheus_default_metrics_tests.erl b/test/eunit/prometheus_default_metrics_tests.erl index b021e41..c5f1b02 100644 --- a/test/eunit/prometheus_default_metrics_tests.erl +++ b/test/eunit/prometheus_default_metrics_tests.erl @@ -5,22 +5,19 @@ default_metric_test() -> try Name = metric_name, - Spec = [{name, Name}, - {help, ""}, - {registry, qwe}, - {buckets, [1, 2, 3]}], - Spec1 = [{name, Name}, - {help, ""}, - {buckets, [1, 2, 3]}], + Spec = [{name, Name}, {help, ""}, {registry, qwe}, {buckets, [1, 2, 3]}], + Spec1 = [{name, Name}, {help, ""}, {buckets, [1, 2, 3]}], application:stop(prometheus), - application:set_env(prometheus, default_metrics, + application:set_env(prometheus, + default_metrics, [{counter, Spec}, {gauge, Spec}, {qwe, summary, Spec1}, {prometheus_histogram, Spec}, {boolean, Spec}]), application:start(prometheus), + timer:sleep(1000), ?assertEqual(false, prometheus_counter:declare(Spec)), ?assertEqual(false, prometheus_gauge:declare(Spec)), ?assertEqual(false, prometheus_summary:declare([{registry, qwe}] ++ Spec)), @@ -28,4 +25,4 @@ default_metric_test() -> ?assertEqual(false, prometheus_boolean:declare(Spec)) after application:unset_env(prometheus, default_metrics) - end. + end. \ No newline at end of file