Skip to content

Commit

Permalink
Add init_delay to startup args (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurnovak authored Aug 7, 2023
1 parent e6f3df8 commit bd78cf2
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 10 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}
]).
```
Expand Down Expand Up @@ -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}
]

Expand Down
32 changes: 23 additions & 9 deletions src/telemetry_poller.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
%% ])
%% '''
%%
Expand Down Expand Up @@ -204,6 +207,7 @@
-type option() ::
{name, atom() | gen_server:server_name()}
| {period, period()}
| {init_delay, init_delay()}
| {measurements, [measurement()]}.
-type measurement() ::
memory
Expand All @@ -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),
Expand All @@ -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)}}.
Expand All @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion test/telemetry_poller_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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, {}}])).
Expand Down

0 comments on commit bd78cf2

Please sign in to comment.