From bd78cf2877e911e2cc97f77f165f61e09ca5943d Mon Sep 17 00:00:00 2001 From: arthurnovak Date: Mon, 7 Aug 2023 18:24:49 +0100 Subject: [PATCH] Add init_delay to startup args (#70) --- README.md | 2 ++ src/telemetry_poller.erl | 32 +++++++++++++++++++++++--------- test/telemetry_poller_SUITE.erl | 7 ++++++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a941f73..00bb0de 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ telemetry_poller:start_link( {example_app_measurements, dispatch_session_count, []} ]}, {period, timer:seconds(10)}, % configure sampling period - default is timer:seconds(5) + {init_delay, timer:seconds(600)}, % configure sampling initial delay - default is 0 {name, my_app_poller} ]). ``` @@ -56,6 +57,7 @@ children = [ {ExampleApp.Measurements, :dispatch_session_count, []}, ], period: :timer.seconds(10), # configure sampling period - default is :timer.seconds(5) + init_delay: :timer.seconds(600), # configure sampling initial delay - default is 0 name: :my_app_poller} ] diff --git a/src/telemetry_poller.erl b/src/telemetry_poller.erl index 3868a86..d849e27 100644 --- a/src/telemetry_poller.erl +++ b/src/telemetry_poller.erl @@ -4,12 +4,15 @@ %% %% A poller is a process start in your supervision tree with a list %% of measurements to perform periodically. On start it expects the -%% period in milliseconds and a list of measurements to perform: +%% period in milliseconds and a list of measurements to perform. Initial delay +%% is an optional parameter that sets time delay in milliseconds before starting +%% measurements: %% %% ``` %% telemetry_poller:start_link([ %% {measurements, Measurements}, -%% {period, Period} +%% {period, Period}, +%% {init_delay, InitDelay} %% ]) %% ''' %% @@ -204,6 +207,7 @@ -type option() :: {name, atom() | gen_server:server_name()} | {period, period()} + | {init_delay, init_delay()} | {measurements, [measurement()]}. -type measurement() :: memory @@ -212,13 +216,14 @@ | {process_info, [{name, atom()} | {event, [atom()]} | {keys, [atom()]}]} | {module(), atom(), list()}. -type period() :: pos_integer(). +-type init_delay() :: non_neg_integer(). -type state() :: #{measurements => [measurement()], period => period()}. %% @doc Starts a poller linked to the calling process. %% %% Useful for starting Pollers as a part of a supervision tree. %% -%% Default options: [{name, telemetry_poller}, {period, timer:seconds(5)}] +%% Default options: [{name, telemetry_poller}, {period, timer:seconds(5)}, {init_delay, 0}] -spec start_link(options()) -> gen_server:start_ret(). start_link(Opts) when is_list(Opts) -> Args = parse_args(Opts), @@ -237,7 +242,7 @@ list_measurements(Poller) -> -spec init(map()) -> {ok, state()}. init(Args) -> - schedule_measurement(0), + schedule_measurement(maps:get(init_delay, Args)), {ok, #{ measurements => maps:get(measurements, Args), period => maps:get(period, Args)}}. @@ -260,21 +265,30 @@ child_spec(Opts) -> parse_args(Args) -> Measurements = proplists:get_value(measurements, Args, []), - ParsedMeasurements = parse_measurements(Measurements), Period = proplists:get_value(period, Args, timer:seconds(5)), - validate_period(Period), - #{measurements => ParsedMeasurements, period => Period}. + InitDelay = proplists:get_value(init_delay, Args, 0), + #{ + measurements => parse_measurements(Measurements), + period => validate_period(Period), + init_delay => validate_init_delay(InitDelay) + }. -spec schedule_measurement(non_neg_integer()) -> ok. schedule_measurement(CollectInMillis) -> erlang:send_after(CollectInMillis, self(), collect), ok. --spec validate_period(term()) -> ok | no_return(). +-spec validate_period(term()) -> period() | no_return(). validate_period(Period) when is_integer(Period), Period > 0 -> - ok; + Period; validate_period(Term) -> erlang:error({badarg, "Expected period to be a positive integer"}, [Term]). +-spec validate_init_delay(term()) -> init_delay() | no_return(). +validate_init_delay(InitDelay) when is_integer(InitDelay), InitDelay >= 0 -> + InitDelay; +validate_init_delay(Term) -> + erlang:error({badarg, "Expected init_delay to be 0 or a positive integer"}, [Term]). + -spec parse_measurements([measurement()]) -> [{module(), atom(), list()}]. parse_measurements(Measurements) when is_list(Measurements) -> lists:map(fun parse_measurement/1, Measurements); diff --git a/test/telemetry_poller_SUITE.erl b/test/telemetry_poller_SUITE.erl index 1c021fb..cb70b04 100644 --- a/test/telemetry_poller_SUITE.erl +++ b/test/telemetry_poller_SUITE.erl @@ -17,6 +17,7 @@ all() -> [ dispatches_total_run_queue_lengths, doesnt_start_given_invalid_measurements, doesnt_start_given_invalid_period, + doesnt_start_given_invalid_init_delay, measurements_can_be_listed, measurement_removed_if_it_raises, multiple_unnamed @@ -55,13 +56,17 @@ multiple_unnamed(_Config) -> can_configure_sampling_period(_Config) -> Period = 500, - {ok, Pid} = telemetry_poller:start_link([{measurements, []}, {period, Period}]), + {ok, Pid} = telemetry_poller:start_link([{measurements, []}, {period, Period}, {init_delay, 0}]), State = sys:get_state(Pid), Period = maps:get(period, State). doesnt_start_given_invalid_period(_Config) -> ?assertError({badarg, "Expected period to be a positive integer"}, telemetry_poller:start_link([{measurements, []}, {period, "1"}])). +doesnt_start_given_invalid_init_delay(_Config) -> + ?assertError({badarg, "Expected init_delay to be 0 or a positive integer"}, + telemetry_poller:start_link([{measurements, []}, {init_delay, "1"}])). + doesnt_start_given_invalid_measurements(_Config) -> ?assertError({badarg, "Expected measurement " ++ _}, telemetry_poller:start_link([{measurements, [invalid_measurement]}])), ?assertError({badarg, "Expected measurements to be a list"}, telemetry_poller:start_link([{measurements, {}}])).