%% ------------------------------------------------------------------- %% %% 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_duration). -behaviour(exometer_probe). %% exometer_entry callbacks -export([new/3, delete/3, get_value/3, get_value/4, get_datapoints/3, setopts/3, update/4, reset/3, sample/3]). %% exometer_probe callbacks -export([behaviour/0, probe_init/3, probe_terminate/1, probe_get_value/2, probe_update/2, probe_reset/1, probe_sample/1, probe_setopts/3, probe_get_datapoints/1, probe_handle_msg/2, probe_code_change/3]). -include("exometer.hrl"). -import(netlink_stat, [get_value/1]). -record(st, {name, t_start, count = 0, last = 0, histogram, opts = []}). -define(DATAPOINTS, [count, last]). behaviour() -> entry. %% exometer_entry callbacks new(Name, Type, Options) -> exometer_probe:new(Name, Type, [{arg, ?MODULE}|Options]). delete(Name, Type, Ref) -> exometer_probe:delete(Name, Type, Ref). get_value(Name, Type, Ref) -> exometer_probe:get_value(Name, Type, Ref). get_value(Name, Type, Ref, DataPoints) -> exometer_probe:get_value(Name, Type, Ref, DataPoints). get_datapoints(Name, Type, Ref) -> exometer_probe:get_datapoints(Name, Type, Ref). setopts(Entry, Opts, Status) -> exometer_probe:setopts(Entry, Opts, Status). update(Name, timer_start, Type, Ref) -> exometer_probe:update(Name, {timer_start, os:timestamp()}, Type, Ref); update(Name, timer_end, Type, Ref) -> exometer_probe:update(Name, {timer_end, os:timestamp()}, Type, Ref); update(_, _, _, _) -> {error, badarg}. reset(Name, Type, Ref) -> exometer_probe:reset(Name, Type, Ref). sample(_, _, _) -> {error, unsupported}. %% exometer_probe callbacks probe_init(Name, Type, Options) -> {ok, H} = exometer_histogram:probe_init(Name, Type, Options), {ok, #st{histogram = H, opts = Options}}. probe_terminate(_ModSt) -> ok. %% Not used probe_get_datapoints(#st{histogram = H}) -> {ok, HDPs} = exometer_histogram:probe_get_datapoints(H), {ok, ?DATAPOINTS ++ HDPs}. probe_get_value(DataPoints, #st{histogram = H} = St) -> case DataPoints -- ?DATAPOINTS of [] -> {ok, fill_datapoints(DataPoints, [], St)}; HDPs -> {ok, HVals} = exometer_histogram:probe_get_value(HDPs, H), {ok, fill_datapoints(DataPoints, HVals, St)} end. probe_setopts(_Entry, _Opts, _St) -> ok. probe_update({timer_start, T}, St) -> {ok, St#st{t_start = T}}; probe_update({timer_end, T}, #st{histogram = H, count = C} = St) -> try Duration = timer:now_diff(T, St#st.t_start), {ok, H1} = exometer_histogram:probe_update(Duration, H), {ok, St#st{histogram = H1, count = C+1, last = Duration}} catch error:_ -> {ok, St} end. probe_reset(#st{histogram = H} = St) -> {ok, H1} = exometer_histogram:probe_reset(H), {ok, St#st{histogram = H1, count = 0, t_start = undefined, last = 0}}. probe_sample(St) -> {ok, St}. probe_code_change(_From, ModSt, _Extra) -> {ok, ModSt}. probe_handle_msg(_, S) -> {ok, S}. fill_datapoints([D|DPs], [{D,_} = V|Vals], St) -> [V|fill_datapoints(DPs, Vals, St)]; fill_datapoints([count|DPs], Vals, #st{count = C} = St) -> [{count, C}|fill_datapoints(DPs, Vals, St)]; fill_datapoints([last|DPs], Vals, #st{last = Last} = St) -> [{last, Last}|fill_datapoints(DPs, Vals, St)]; fill_datapoints([], [], _) -> [].