Current section
Files
Jump to
Current section
Files
src/exometer_folsom.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_folsom).
-behaviour(exometer_entry).
-export([behaviour/0,
new/3,
delete/3,
get_datapoints/3,
get_value/4,
update/4,
reset/3,
sample/3,
setopts/3]).
-spec behaviour() -> exometer:behaviour().
behaviour() -> entry.
new(Name, counter, _Opts) ->
folsom_metrics:new_counter(Name);
new(Name, spiral, _Opts) ->
folsom_metrics:new_spiral(Name);
new(Name, histogram, Opts) ->
case lists:keysearch(arg, 1, Opts) of
{_, {histogram, SampleType, SampleArgs}} ->
{folsom_metrics:new_histogram(Name, SampleType, SampleArgs),
opt_ref(Opts)};
false ->
{folsom_metrics:new_histogram(Name, slide_uniform, {60, 1028}),
opt_ref(Opts)}
end;
new(Name, meter, Opts) ->
{folsom_metrics:new_meter(Name), opt_ref(Opts)};
new(Name, meter_reader, Opts) ->
{folsom_metrics:new_meter_reader(Name), opt_ref(Opts)};
new(Name, gauge, Opts) ->
{folsom_metrics:new_gauge(Name), opt_ref(Opts)};
new(Name, duration, Opts) ->
{folsom_metrics:new_duration(Name), opt_ref(Opts)};
new(Name, history, Opts) ->
case lists:keyfind(size, 1, Opts) of
{_, Sz} -> {folsom_metrics:new_history(Name, Sz), opt_ref(Opts)};
false -> {folsom_metrics:new_history(Name), opt_ref(Opts)}
end.
opt_ref(Opts) ->
case lists:keyfind(truncate, 1, Opts) of
false ->
[{truncate,true}];
{_, B} when is_boolean(B) ->
[{truncate,B}]
end.
delete(Name, _Type, _Ref) ->
folsom_metrics:delete_metric(Name).
update(Name, Value, counter, _Ref) ->
folsom_metrics:notify_existing_metric(Name, {inc, Value}, counter);
update(Name, tick, meter_reader, _Ref) ->
folsom_metrics_meter_reader:tick(Name);
update(Name, Value, meter_reader, _Ref) ->
folsom_metrics_meter_reader:mark(Name, Value);
update(Name, Value, Type, _Ref) ->
folsom_metrics:notify_existing_metric(Name, Value, Type).
reset(Name, counter, _Ref) ->
folsom_metrics_counter:clear(Name);
reset(Name, gauge, _Ref) ->
folsom_metrics_gauge:clear(Name);
reset(_, _, _) ->
{error, unsupported}.
get_value(Name, history, _Ref, DataPoints0) ->
try DataPoints = datapoints(history, DataPoints0),
lists:foldr(
fun(events, Acc) ->
[{events, just_events(
folsom_metrics_history:get_events(Name))}
| Acc];
(values, Acc) ->
[{values, folsom_metrics_history:get_events(Name)}
| Acc];
(timed_events, Acc) ->
[{timed_events,
timed_events(
folsom_metrics_history:get_events(Name))}
| Acc];
(Sz, Acc) when is_integer(Sz), Sz > 0 ->
[{Sz, just_events(
folsom_metrics_history:get_events(Name, Sz))}
| Acc];
(info, Acc) ->
[{info, folsom_metrics_history:get_value(Name)}
| Acc];
(_, Acc) -> Acc
end, [], DataPoints)
catch
error:_ -> unavailable
end;
get_value(Name, Type, Ref, DataPoints) ->
Trunc = get_trunc_opt(Ref),
Vals = get_value_(Name, Type, Ref),
try [filter_dp(D, Vals, Trunc) || D <- datapoints(Type, DataPoints)]
catch
error:_Error ->
unavailable
end.
get_trunc_opt(undefined) -> true;
get_trunc_opt(L) ->
proplists:get_value(truncate, L, true).
get_datapoints(_Name, Type, _Ref) ->
datapoints(Type, default).
datapoints(Type, default) -> datapoints(Type);
datapoints(_, L) when is_list(L) -> L.
datapoints(counter) ->
[value];
datapoints(gauge) ->
[value];
datapoints(histogram) ->
stats_datapoints();
datapoints(duration) ->
[count, last |stats_datapoints()];
datapoints(spiral) ->
[one, count];
datapoints(meter) ->
[count,one,five,fifteen,day,mean,acceleration];
datapoints(history) ->
[events, info].
filter_dp(Mean, DPs, Trunc) when Mean==mean; Mean==arithmetic_mean ->
case lists:keyfind(mean, 1, DPs) of
false ->
case lists:keyfind(arithmetic_mean, 1, DPs) of
false -> {mean, zero(Trunc)};
{_,V} -> {mean, opt_trunc(Trunc, V)}
end;
{_,V} -> {mean, opt_trunc(Trunc, V)}
end;
filter_dp(H, DPs, Trunc) when is_integer(H) ->
case lists:keyfind(H, 1, DPs) of
false ->
case lists:keyfind(percentile, 1, DPs) of
false -> {H, zero(Trunc)};
{_, Ps} ->
get_dp(H, Ps, Trunc)
end;
{_,V} -> {H, opt_trunc(Trunc, V)}
end;
filter_dp(H, DPs, Trunc) ->
get_dp(H, DPs, Trunc).
opt_trunc(true, V) when is_float(V) ->
trunc(V);
opt_trunc(round, V) when is_float(V) ->
round(V);
opt_trunc(_, V) ->
V.
get_dp(K, DPs, Trunc) ->
case lists:keyfind(K, 1, DPs) of
false -> {K, zero(Trunc)};
{_, V} -> {K, opt_trunc(Trunc, V)}
end.
zero(true) -> 0;
zero(round) -> 0;
zero(false) -> 0.0.
stats_datapoints() ->
[n,mean,min,max,median,50,75,90,95,99,999].
setopts(_Entry, _Options, _Status) ->
ok.
sample(_Name, _Type, _Ref) ->
{ error, unsupported }.
get_value_(Name, counter, _Ref) ->
[{value, folsom_metrics_counter:get_value(Name)}];
get_value_(Name, gauge, _Ref) ->
[{value, folsom_metrics_gauge:get_value(Name)}];
get_value_(Name, histogram, _Ref) ->
calc_stats(folsom_metrics_histogram:get_values(Name));
get_value_(Name, duration, _Ref) ->
{Name, Cnt, _Start, Last} = folsom_metrics_duration:get_value(Name),
Stats = calc_stats(folsom_metrics_histogram:get_values(Name)),
[{count, Cnt}, {last, Last} | Stats];
get_value_(Name, meter, _Ref) ->
folsom_metrics:get_metric_value(Name);
get_value_(Name, spiral, _Ref) ->
folsom_metrics_spiral:get_values(Name).
calc_stats(Values) ->
L = length(Values),
exometer_util:get_statistics(L,
lists:sum(Values),
lists:sort(Values)).
just_events([{I, Events}|T]) when is_integer(I) ->
just_events1(Events, T);
just_events([]) ->
[].
just_events1([{event, E}|Es], T) ->
[E|just_events1(Es, T)];
just_events1([], T) ->
just_events(T).
timed_events([{I, Events}|T]) when is_integer(I) ->
timed_events(Events, I, T);
timed_events([]) ->
[].
timed_events([{event, E}|Es], I, T) ->
[{I, E}|timed_events(Es, I, T)];
timed_events([], _, T) ->
timed_events(T).