Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #3 from blinkov/master

Support for Erlang VM stats reporting
  • Loading branch information...
commit 2643d305154af098650865bec28c9131964fea1f 2 parents c9e1b99 + 14eb2a3
@RJ authored
Showing with 71 additions and 18 deletions.
  1. +62 −13 src/estatsd_server.erl
  2. +9 −5 src/estatsd_sup.erl
View
75 src/estatsd_server.erl
@@ -11,7 +11,7 @@
-module(estatsd_server).
-behaviour(gen_server).
--export([start_link/3]).
+-export([start_link/4]).
%-export([key2str/1,flush/0]). %% export for debugging
@@ -22,18 +22,19 @@
flush_interval, % ms interval between stats flushing
flush_timer, % TRef of interval timer
graphite_host, % graphite server host
- graphite_port % graphite server port
+ graphite_port, % graphite server port
+ vm_metrics % flag to enable sending VM metrics on flush
}).
-start_link(FlushIntervalMs, GraphiteHost, GraphitePort) ->
+start_link(FlushIntervalMs, GraphiteHost, GraphitePort, VmMetrics) ->
gen_server:start_link({local, ?MODULE},
?MODULE,
- [FlushIntervalMs, GraphiteHost, GraphitePort],
+ [FlushIntervalMs, GraphiteHost, GraphitePort, VmMetrics],
[]).
%%
-init([FlushIntervalMs, GraphiteHost, GraphitePort]) ->
+init([FlushIntervalMs, GraphiteHost, GraphitePort, VmMetrics]) ->
error_logger:info_msg("estatsd will flush stats to ~p:~w every ~wms\n",
[ GraphiteHost, GraphitePort, FlushIntervalMs ]),
ets:new(statsd, [named_table, set]),
@@ -45,7 +46,8 @@ init([FlushIntervalMs, GraphiteHost, GraphitePort]) ->
flush_interval = FlushIntervalMs,
flush_timer = Tref,
graphite_host = GraphiteHost,
- graphite_port = GraphitePort
+ graphite_port = GraphitePort,
+ vm_metrics = VmMetrics
},
{ok, State}.
@@ -135,18 +137,20 @@ unixtime() -> {Meg,S,_Mic} = erlang:now(), Meg*1000000 + S.
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),
+ {MsgCounters, NumCounters} = do_report_counters(All, TsStr, State),
+ {MsgTimers, NumTimers} = do_report_timers(TsStr, State),
+ {MsgGauges, NumGauges} = do_report_gauges(Gauges),
+ {MsgVmMetrics, NumVmMetrics} = do_report_vm_metrics(TsStr, State),
%% REPORT TO GRAPHITE
- case NumTimers + NumCounters + NumGauges of
+ case NumTimers + NumCounters + NumGauges + NumVmMetrics of
0 -> nothing_to_report;
NumStats ->
FinalMsg = [ MsgCounters,
MsgTimers,
MsgGauges,
+ MsgVmMetrics,
%% Also graph the number of graphs we're graphing:
- "statsd.numStats ", num2str(NumStats), " ", TsStr, "\n"
+ "stats.num_stats ", num2str(NumStats), " ", TsStr, "\n"
],
send_to_graphite(FinalMsg, State)
end.
@@ -157,11 +161,11 @@ do_report_counters(All, TsStr, State) ->
KeyS = key2str(Key),
Val = Val0 / (State#state.flush_interval/1000),
%% Build stats string for graphite
- Fragment = [ "stats.", KeyS, " ",
+ Fragment = [ "stats.counters.", KeyS, " ",
io_lib:format("~w", [Val]), " ",
TsStr, "\n",
- "stats_counts.", KeyS, " ",
+ "stats.counters.counts.", KeyS, " ",
io_lib:format("~w",[NumVals]), " ",
TsStr, "\n"
],
@@ -217,3 +221,48 @@ do_report_gauges(Gauges) ->
end, [], Gauges
),
{Msg, length(Gauges)}.
+
+do_report_vm_metrics(TsStr, State) ->
+ case State#state.vm_metrics of
+ true ->
+ NodeKey = node_key(),
+ {TotalReductions, Reductions} = erlang:statistics(reductions),
+ {NumberOfGCs, WordsReclaimed, _} = erlang:statistics(garbage_collection),
+ {{input, Input}, {output, Output}} = erlang:statistics(io),
+ RunQueue = erlang:statistics(run_queue),
+ StatsData = [
+ {process_count, erlang:system_info(process_count)},
+ {reductions, Reductions},
+ {total_reductions, TotalReductions},
+ {number_of_gcs, NumberOfGCs},
+ {words_reclaimed, WordsReclaimed},
+ {input, Input},
+ {output, Output},
+ {run_queue, RunQueue}
+ ],
+ StatsMsg = lists:map(fun({Key, Val}) ->
+ [
+ "stats.vm.", NodeKey, ".stats.", key2str(Key), " ",
+ io_lib:format("~w", [Val]), " ",
+ TsStr, "\n"
+ ]
+ end, StatsData),
+ MemoryMsg = lists:map(fun({Key, Val}) ->
+ [
+ "stats.vm.", NodeKey, ".memory.", key2str(Key), " ",
+ io_lib:format("~w", [Val]), " ",
+ TsStr, "\n"
+ ]
+ end, erlang:memory()),
+ Msg = StatsMsg ++ MemoryMsg;
+ false ->
+ Msg = []
+ end,
+ {Msg, length(Msg)}.
+
+node_key() ->
+ NodeList = atom_to_list(node()),
+ {ok, R} = re:compile("[\@\.]"),
+ Opts = [global, {return, list}],
+ S = re:replace(NodeList, R, "_", Opts),
+ key2str(S).
View
14 src/estatsd_sup.erl
@@ -11,6 +11,7 @@
-define(FLUSH_INTERVAL, appvar(flush_interval, 10000)).
-define(GRAPHITE_HOST, appvar(graphite_host, "127.0.0.1")).
-define(GRAPHITE_PORT, appvar(graphite_port, 2003)).
+-define(VM_METRICS, appvar(vm_metrics, true)).
%% ===================================================================
%% API functions
@@ -18,25 +19,28 @@
start_link() ->
- start_link( ?FLUSH_INTERVAL, ?GRAPHITE_HOST, ?GRAPHITE_PORT).
+ start_link( ?FLUSH_INTERVAL, ?GRAPHITE_HOST, ?GRAPHITE_PORT, ?VM_METRICS).
start_link(FlushIntervalMs) ->
- start_link( FlushIntervalMs, ?GRAPHITE_HOST, ?GRAPHITE_PORT).
+ start_link( FlushIntervalMs, ?GRAPHITE_HOST, ?GRAPHITE_PORT, ?VM_METRICS).
start_link(FlushIntervalMs, GraphiteHost, GraphitePort) ->
+ start_link( FlushIntervalMs, GraphiteHost, GraphitePort, ?VM_METRICS).
+
+start_link(FlushIntervalMs, GraphiteHost, GraphitePort, VmMetrics) ->
supervisor:start_link({local, ?MODULE},
?MODULE,
- [FlushIntervalMs, GraphiteHost, GraphitePort]).
+ [FlushIntervalMs, GraphiteHost, GraphitePort, VmMetrics]).
%% ===================================================================
%% Supervisor callbacks
%% ===================================================================
-init([FlushIntervalMs, GraphiteHost, GraphitePort]) ->
+init([FlushIntervalMs, GraphiteHost, GraphitePort, VmMetrics]) ->
Children = [
{estatsd_server,
{estatsd_server, start_link,
- [FlushIntervalMs, GraphiteHost, GraphitePort]},
+ [FlushIntervalMs, GraphiteHost, GraphitePort, VmMetrics]},
permanent, 5000, worker, [estatsd_server]}
],
{ok, { {one_for_one, 10000, 10}, Children} }.
Please sign in to comment.
Something went wrong with that request. Please try again.