Current section
Files
Jump to
Current section
Files
src/statman_poller_sup.erl
%% @doc: Poller supervisor provides API for starting poller
-module(statman_poller_sup).
-behaviour(supervisor).
%% API
-export([start_link/0]).
-export([init/1]).
-export([add_gauge/1, add_gauge/2,
add_counter/1, add_counter/2,
add_histogram/1, add_histogram/2
]).
-export([get_workers/0]).
-export([remove_gauge/1, remove_counter/1, remove_histogram/1]).
-export([add_worker/2, remove_worker/1]).
%% Types
-type types() :: gauge | counter | histogram.
-type typed_fun() :: {types(), fun()}.
-export_type([typed_fun/0, types/0]).
%%%===================================================================
%%% API
%%%===================================================================
-spec add_gauge(fun()) -> {ok, pid()}.
add_gauge(F) -> add_worker({gauge, F}, 10000).
-spec add_gauge(fun(), pos_integer()) -> {ok, pid()}.
add_gauge(F, Interval) -> add_worker({gauge, F}, Interval).
-spec add_counter(fun()) -> {ok, pid()}.
add_counter(F) -> add_worker({counter, F}, 10000).
-spec add_counter(fun(), pos_integer()) -> {ok, pid()}.
add_counter(F, Interval) -> add_worker({counter, F}, Interval).
-spec add_histogram(fun()) -> {ok, pid()}.
add_histogram(F) -> add_worker({histogram, F}, 10000).
-spec add_histogram(fun(), pos_integer()) -> {ok, pid()}.
add_histogram(F, Interval) -> add_worker({histogram, F}, Interval).
-spec remove_gauge(fun()) -> ok.
remove_gauge(F) -> remove_worker({gauge, F}).
-spec remove_counter(fun()) -> ok.
remove_counter(F) -> remove_worker({counter, F}).
-spec remove_histogram(fun()) -> ok.
remove_histogram(F) -> remove_worker({histogram, F}).
-spec get_workers() -> list().
get_workers() ->
supervisor:which_children(?MODULE).
-spec start_link() -> ignore | {error, any()} | {ok, pid()}.
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-spec add_worker(typed_fun(), pos_integer()) -> {ok, pid()}.
add_worker(TypedF, Interval) ->
Id = get_unique_id(TypedF),
ChildSpec = get_worker_spec(Id, TypedF, Interval),
case supervisor:start_child(?MODULE, ChildSpec) of
{error, {already_started, Pid}} ->
{ok, Pid};
{error, Reason} ->
throw({unable_to_start_worker, Id, Reason});
{ok, Pid} ->
{ok, Pid}
end.
-spec remove_worker(typed_fun()) -> ok.
remove_worker(TypedF) ->
Name = get_worker_name(get_unique_id(TypedF)),
ok = supervisor:terminate_child(?MODULE, Name),
ok = supervisor:delete_child(?MODULE, Name),
ok.
%%%===================================================================
%%% Supervisor callbacks
%%%===================================================================
init([]) ->
{ok, {{one_for_one, 5, 10}, []}}.
%%%===================================================================
%%% Internal functionality
%%%===================================================================
get_worker_spec(Id, TypedF, Interval) ->
Name = get_worker_name(Id),
{Name,
{statman_poller_worker, start_link, [Name, TypedF, Interval]},
transient, 5000, worker, [statman_poller_worker]
}.
get_worker_name(Id) ->
list_to_atom(
atom_to_list(statman_poller_worker) ++ "_" ++ integer_to_list(Id)
).
get_unique_id(TypedF) ->
erlang:phash2(TypedF).