Skip to content

Commit

Permalink
Implement a metrics HTTP endpoint.
Browse files Browse the repository at this point in the history
  • Loading branch information
aeden committed Sep 9, 2013
1 parent 8bdd3db commit 2614ad9
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 4 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,11 @@ erldns_zone_cache:put_zone({
}
]}).
```

## Metrics

Folsom is used to gather runtime metrics and statistics. There is an HTTP server included that produces a JSON report containing these metrics. Here's an example script that shows how to get the output with curl and pass through Python to format it in a pretty fashion.

```sh
curl -s http://localhost:8082/ -H "Accept: application/json" | python -mjson.tool
```
3 changes: 2 additions & 1 deletion ebin/erldns.app
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{application,erldns,
[{description,"Erlang Authoritative DNS Server"},
{vsn,"5321c5a"},
{vsn,"8bdd3db"},
{mod,{erldns_app,[]}},
{applications,[kernel,stdlib,inets,crypto,ssl,folsom]},
{start_phases,[{post_start,[]}]},
{modules,[erldns,erldns_app,erldns_axfr,erldns_config,
erldns_dnssec,erldns_edns,erldns_encoder,
erldns_event_logger,erldns_events,erldns_handler,
erldns_metrics,erldns_metrics_root_handler,
erldns_packet_cache,erldns_query_throttle,
erldns_records,erldns_resolver,erldns_server_sup,
erldns_sup,erldns_tcp_server,erldns_txt,
Expand Down
1 change: 1 addition & 0 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
{deps, [
{lager, ".*", {git, "git://github.com/basho/lager.git", "HEAD"}},
{folsom, ".*", {git, "git://github.com/boundary/folsom.git", "HEAD"}},
{cowboy, ".*", {git, "git://github.com/extend/cowboy.git", {tag, "0.8.6"}}},
{poolboy, ".*", {git, "git://github.com/devinus/poolboy.git", "HEAD"}},
{jsx, ".*", {git, "git://github.com/talentdeficit/jsx.git", "HEAD"}},
{dns, ".*", {git, "git://github.com/aeden/dns_erlang.git", "HEAD"}},
Expand Down
2 changes: 2 additions & 0 deletions src/erldns.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ start() ->
ssl:start(),
lager:start(),
folsom:start(),
application:start(ranch),
application:start(cowboy),
application:start(erldns).
6 changes: 3 additions & 3 deletions src/erldns_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
% Application hooks
-export([start/2, start_phase/3, stop/1]).

-export([get_metrics/0, get_stats/0]).
-export([metrics/0, stats/0]).

start(_Type, _Args) ->
define_metrics(),
Expand Down Expand Up @@ -45,13 +45,13 @@ stop(_State) ->
lager:info("Stop erldns application"),
ok.

get_metrics() ->
metrics() ->
lists:map(
fun(Name) ->
{Name, folsom_metrics:get_metric_value(Name)}
end, folsom_metrics:get_metrics()).

get_stats() ->
stats() ->
Histograms = [udp_handoff_histogram, tcp_handoff_histogram, request_handled_histogram],
lists:map(
fun(Name) ->
Expand Down
58 changes: 58 additions & 0 deletions src/erldns_metrics.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
-module(erldns_metrics).

-behavior(gen_server).

-export([start_link/0]).

-define(DEFAULT_PORT, 8082).

% Gen server hooks
-export([init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3
]).

-record(state, {}).

start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init([]) ->
lager:debug("Starting ~p", [?MODULE]),

Dispatch = cowboy_router:compile(
[
{'_',
[
{"/", erldns_metrics_root_handler, []}
]
}
]
),

{ok, _} = cowboy:start_http(http, 10, [{port, port()}], [{env, [{dispatch, Dispatch}]}]),

{ok, #state{}}.

handle_call(_Message, _From, State) ->
{reply, ok, State}.
handle_cast(_, State) ->
{noreply, State}.
handle_info(_, State) ->
{noreply, State}.
terminate(_, _) ->
ok.
code_change(_PreviousVersion, State, _Extra) ->
{ok, State}.

port() ->
proplists:get_value(port, metrics_env(), ?DEFAULT_PORT).

metrics_env() ->
case application:get_env(erldns, metrics) of
{ok, MetricsEnv} -> MetricsEnv;
_ -> []
end.
59 changes: 59 additions & 0 deletions src/erldns_metrics_root_handler.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
-module(erldns_metrics_root_handler).

-export([init/3]).
-export([content_types_provided/2]).
-export([to_html/2, to_json/2, to_text/2]).

-export([filter_stats/1]).

init(_Transport, _Req, []) ->
{upgrade, protocol, cowboy_rest}.

content_types_provided(Req, State) ->
{[
{<<"text/html">>, to_html},
{<<"text/plain">>, to_text},
{<<"application/json">>, to_json}
], Req, State}.

to_html(Req, State) ->
{<<"erldns metrics">>, Req, State}.

to_text(Req, State) ->
{<<"erldns metrics">>, Req, State}.

to_json(Req, State) ->
Body = jsx:encode([{<<"erldns">>,
[
{<<"metrics">>, erldns_app:metrics()},
{<<"stats">>, filter_stats(erldns_app:stats())}
]
}]),
{Body, Req, State}.

% Functions to clean up the stats so they can be returned as JSON.
filter_stats(Stats) ->
filter_stats(Stats, []).

filter_stats([], FilteredStats) ->
FilteredStats;
filter_stats([{Name, Stats}|Rest], FilteredStats) ->
filter_stats(Rest, FilteredStats ++ [{Name, filter_stat_set(Stats)}]).

filter_stat_set(Stats) ->
filter_stat_set(Stats, []).

filter_stat_set([], FilteredStatSet) ->
FilteredStatSet;
filter_stat_set([{percentile, Percentiles}|Rest], FilteredStatSet) ->
filter_stat_set(Rest, FilteredStatSet ++ [{percentile, keys_to_strings(Percentiles)}]);
filter_stat_set([{histogram, _}|Rest], FilteredStatSet) ->
filter_stat_set(Rest, FilteredStatSet);
filter_stat_set([Pair|Rest], FilteredStatSet) ->
filter_stat_set(Rest, FilteredStatSet ++ [Pair]).

keys_to_strings(Pairs) ->
lists:map(
fun({K, V}) ->
{list_to_binary(lists:flatten(io_lib:format("~p", [K]))), V}
end, Pairs).
1 change: 1 addition & 0 deletions src/erldns_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ init(_Args) ->
?CHILD(erldns_packet_cache, worker, []),
?CHILD(erldns_query_throttle, worker, []),
?CHILD(erldns_handler, worker, []),
?CHILD(erldns_metrics, worker, []),

?CHILD(sample_custom_handler, worker, [])
],
Expand Down

0 comments on commit 2614ad9

Please sign in to comment.