Packages

Statman to the rescue!

Current section

Files

Jump to
statman src statman_poller_worker.erl
Raw

src/statman_poller_worker.erl

-module(statman_poller_worker).
-behaviour(gen_server).
-include_lib("eunit/include/eunit.hrl").
%% API
-export([start_link/3]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state, {typed_fun :: tuple(),
fun_state :: any(),
timer_ref :: term(),
interval :: integer()
}).
%%%===================================================================
%%% API
%%%===================================================================
-spec start_link(atom(), statman_poller_sup:typed_fun(), pos_integer())
-> ignore | {error, any()} | {ok, pid()}.
start_link(Name, TypedF, Interval) ->
gen_server:start_link({local, Name}, ?MODULE, [TypedF, Interval], []).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([TypedF, Interval]) ->
{ok, #state{typed_fun = TypedF,
timer_ref = start_timer(Interval),
interval = Interval,
fun_state = undefined}}.
handle_call(_Msg, _From, State) ->
{reply, unknown_call, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
%%TODO: do we need to spawn here?
handle_info(poll, #state{typed_fun = {Type, F}, fun_state = FunState} = State) ->
NewTimer = start_timer(State#state.interval),
{NewFunState, Updates} = case erlang:fun_info(F, arity) of
{arity, 0} -> {FunState, F()};
{arity, 1} -> F(FunState)
end,
case Type of
gauge ->
[statman_gauge:set(K, V) || {K, V} <- Updates];
counter ->
[statman_counter:incr(K, V) || {K, V} <- Updates];
histogram ->
[statman_histogram:record_value(K, statman_histogram:bin(V))
|| {K, V} <- Updates]
end,
{noreply, State#state{fun_state = NewFunState, timer_ref = NewTimer}};
handle_info(_, State) ->
%% Ignore unknown messages, might come from gen calls that timed
%% out, but response got sent anyway..
{noreply, State}.
terminate(_Reason, #state{timer_ref = undefined}) ->
ok;
terminate(_Reason, #state{timer_ref = TRef}) ->
erlang:cancel_timer(TRef),
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functionality
%%%===================================================================
start_timer(Interval) ->
erlang:send_after(Interval, self(), poll).