Skip to content

Commit

Permalink
Add support for gauges
Browse files Browse the repository at this point in the history
  • Loading branch information
jwheare committed Apr 4, 2012
1 parent c0127ae commit 3016458
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
5 changes: 5 additions & 0 deletions README.txt
Expand Up @@ -28,6 +28,11 @@ application environment vars. See estatsd_sup for details.

The following calls to estatsd are all gen_server:cast, ie non-blocking.

Gauges
--------

estatsd:gauge(temperature, 45). %% set temperature to 45

Counters
--------

Expand Down
4 changes: 4 additions & 0 deletions src/estatsd.erl
@@ -1,6 +1,7 @@
-module(estatsd).

-export([
gauge/2,
increment/1, increment/2, increment/3,
decrement/1, decrement/2, decrement/3,
timing/2
Expand Down Expand Up @@ -34,3 +35,6 @@ decrement(Key, Amount) -> decrement(Key, Amount, 1).
decrement(Key, Amount, Sample) ->
increment(Key, 0 - Amount, Sample).

% Sets a gauge value
gauge(Key, Value) when is_number(Value) ->
gen_server:cast(?SERVER, {gauge, Key, Value}).
41 changes: 38 additions & 3 deletions src/estatsd_server.erl
Expand Up @@ -37,6 +37,7 @@ init([FlushIntervalMs, GraphiteHost, GraphitePort]) ->
error_logger:info_msg("estatsd will flush stats to ~p:~w every ~wms\n",
[ GraphiteHost, GraphitePort, FlushIntervalMs ]),
ets:new(statsd, [named_table, set]),
ets:new(statsdgauge, [named_table, set]),
%% Flush out stats to graphite periodically
{ok, Tref} = timer:apply_interval(FlushIntervalMs, gen_server, cast,
[?MODULE, flush]),
Expand All @@ -48,6 +49,16 @@ init([FlushIntervalMs, GraphiteHost, GraphitePort]) ->
},
{ok, State}.

handle_cast({gauge, Key, Value0}, State) ->
Value = {Value0, num2str(unixtime())},
case ets:lookup(statsdgauge, Key) of
[] ->
ets:insert(statsdgauge, {Key, [Value]});
[{Key, Values}] ->
ets:insert(statsdgauge, {Key, [Value | Values]})
end,
{noreply, State};

handle_cast({increment, Key, Delta0, Sample}, State) when Sample >= 0, Sample =< 1 ->
Delta = Delta0 * ( 1 / Sample ), %% account for sample rates < 1.0
case ets:lookup(statsd, Key) of
Expand All @@ -69,9 +80,11 @@ handle_cast({timing, Key, Duration}, State) ->

handle_cast(flush, State) ->
All = ets:tab2list(statsd),
spawn( fun() -> do_report(All, State) end ),
Gauges = ets:tab2list(statsdgauge),
spawn( fun() -> do_report(All, Gauges, State) end ),
%% WIPE ALL
ets:delete_all_objects(statsd),
ets:delete_all_objects(statsdgauge),
NewState = State#state{timers = gb_trees:empty()},
{noreply, NewState}.

Expand Down Expand Up @@ -119,17 +132,19 @@ num2str(NN) -> lists:flatten(io_lib:format("~w",[NN])).
unixtime() -> {Meg,S,_Mic} = erlang:now(), Meg*1000000 + S.

%% Aggregate the stats and generate a report to send to graphite
do_report(All, State) ->
do_report(All, Gauges, State) ->
% One time stamp string used in all stats lines:
TsStr = num2str(unixtime()),
{MsgCounters, NumCounters} = do_report_counters(All, TsStr, State),
{MsgTimers, NumTimers} = do_report_timers(TsStr, State),
{MsgGauges, NumGauges} = do_report_gauges(Gauges),
%% REPORT TO GRAPHITE
case NumTimers + NumCounters of
case NumTimers + NumCounters + NumGauges of
0 -> nothing_to_report;
NumStats ->
FinalMsg = [ MsgCounters,
MsgTimers,
MsgGauges,
%% Also graph the number of graphs we're graphing:
"statsd.numStats ", num2str(NumStats), " ", TsStr, "\n"
],
Expand Down Expand Up @@ -182,3 +197,23 @@ do_report_timers(TsStr, State) ->
[ Fragment | Acc ]
end, [], Timings),
{Msg, length(Msg)}.

do_report_gauges(Gauges) ->
Msg = lists:foldl(
fun({Key, Vals}, Acc) ->
KeyS = key2str(Key),
Fragments = lists:foldl(
fun ({Val, TsStr}, KeyAcc) ->
%% Build stats string for graphite
Fragment = [
"gauge.", KeyS, " ",
io_lib:format("~w", [Val]), " ",
TsStr, "\n"
],
[ Fragment | KeyAcc ]
end, [], Vals
),
[ Fragments | Acc ]
end, [], Gauges
),
{Msg, length(Gauges)}.

0 comments on commit 3016458

Please sign in to comment.