Packages
Graphite reporter for Exometer compatible with exometer_core
Current section
Files
Jump to
Current section
Files
src/exometer_report_graphite.erl
%% -------------------------------------------------------------------
%%
%% Copyright (c) 2014 Basho Technologies, Inc. All Rights Reserved.
%%
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at http://mozilla.org/MPL/2.0/.
%%
%% -------------------------------------------------------------------
-module(exometer_report_graphite).
-behaviour(exometer_report).
%% gen_server callbacks
-export(
[
exometer_init/1,
exometer_info/2,
exometer_cast/2,
exometer_call/3,
exometer_report/5,
exometer_subscribe/5,
exometer_unsubscribe/4,
exometer_newentry/2,
exometer_setopts/4,
exometer_terminate/2
]).
-include_lib("exometer_core/include/exometer.hrl").
-define(DEFAULT_HOST, "carbon.hostedgraphite.com").
-define(DEFAULT_PORT, 2003).
-define(DEFAULT_CONNECT_TIMEOUT, 5000).
-record(st, {
host = ?DEFAULT_HOST,
port = ?DEFAULT_PORT,
connect_timeout = ?DEFAULT_CONNECT_TIMEOUT,
name,
namespace = [],
prefix = [],
api_key = "",
socket = undefined}).
%% calendar:datetime_to_gregorian_seconds({{1970,1,1},{0,0,0}}).
-define(UNIX_EPOCH, 62167219200).
-include("log.hrl").
%% Probe callbacks
exometer_init(Opts) ->
?info("Exometer Graphite Reporter; Opts: ~p~n", [Opts]),
API_key = get_opt(api_key, Opts),
Prefix = get_opt(prefix, Opts, []),
Host = get_opt(host, Opts, ?DEFAULT_HOST),
Port = get_opt(port, Opts, ?DEFAULT_PORT),
ConnectTimeout = get_opt(connect_timeout, Opts, ?DEFAULT_CONNECT_TIMEOUT),
case gen_tcp:connect(Host, Port, [{mode, list}], ConnectTimeout) of
{ok, Sock} ->
{ok, #st{prefix = Prefix,
api_key = API_key,
socket = Sock,
host = Host,
port = Port,
connect_timeout = ConnectTimeout }};
{error, _} = Error ->
Error
end.
exometer_report(Probe, DataPoint, _Extra, Value, #st{socket = Sock,
api_key = APIKey,
prefix = Prefix} = St) ->
Line = [key(APIKey, Prefix, Probe, DataPoint), " ",
value(Value), " ", timestamp(), $\n],
case gen_tcp:send(Sock, Line) of
ok ->
{ok, St};
_ ->
reconnect(St)
end.
exometer_subscribe(_Metric, _DataPoint, _Extra, _Interval, St) ->
{ok, St }.
exometer_unsubscribe(_Metric, _DataPoint, _Extra, St) ->
{ok, St }.
exometer_call(Unknown, From, St) ->
?info("Unknown call ~p from ~p", [Unknown, From]),
{ok, St}.
exometer_cast(Unknown, St) ->
?info("Unknown cast: ~p", [Unknown]),
{ok, St}.
exometer_info(Unknown, St) ->
?info("Unknown info: ~p", [Unknown]),
{ok, St}.
exometer_newentry(_Entry, St) ->
{ok, St}.
exometer_setopts(_Metric, _Options, _Status, St) ->
{ok, St}.
exometer_terminate(_, _) ->
ignore.
%% Format a graphite key from API key, prefix, prob and datapoint
key([], [], Prob, DataPoint) ->
name(Prob, DataPoint);
key([], Prefix, Prob, DataPoint) ->
[Prefix, $., name(Prob, DataPoint)];
key(APIKey, [], Prob, DataPoint) ->
[APIKey, $., name(Prob, DataPoint)];
key(APIKey, Prefix, Prob, DataPoint) ->
[APIKey, $., Prefix, $., name(Prob, DataPoint)].
%% Add probe and datapoint within probe
name(Probe, DataPoint) ->
[[[metric_elem_to_list(I), $.] || I <- Probe], datapoint(DataPoint)].
metric_elem_to_list(V) when is_atom(V) -> atom_to_list(V);
metric_elem_to_list(V) when is_binary(V) -> binary_to_list(V);
metric_elem_to_list(V) when is_integer(V) -> integer_to_list(V);
metric_elem_to_list(V) when is_list(V) -> V.
datapoint(V) when is_integer(V) -> integer_to_list(V);
datapoint(V) when is_atom(V) -> atom_to_list(V).
%% Add value, int or float, converted to list
value(V) when is_integer(V) -> integer_to_list(V);
value(V) when is_float(V) -> float_to_list(V);
value(_) -> 0.
timestamp() ->
integer_to_list(unix_time()).
reconnect(St) ->
case gen_tcp:connect(St#st.host, St#st.port, [{mode, list}], St#st.connect_timeout) of
{ok, Sock} ->
{ok, St#st{socket = Sock}};
{error, _} = Error ->
Error
end.
unix_time() ->
datetime_to_unix_time(erlang:universaltime()).
datetime_to_unix_time({{_,_,_},{_,_,_}} = DateTime) ->
calendar:datetime_to_gregorian_seconds(DateTime) - ?UNIX_EPOCH.
get_opt(K, Opts) ->
case lists:keyfind(K, 1, Opts) of
{_, V} -> V;
false -> error({required, K})
end.
get_opt(K, Opts, Default) ->
exometer_util:get_opt(K, Opts, Default).