Current section
Files
Jump to
Current section
Files
src/exometer_entry.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/.
%%
%% -------------------------------------------------------------------
%% @doc
%% == Creating custom exometer entries ==
%%
%% An exometer_entry behavior implementation can be created when custom
%% processing of various metrics is needed.
%%
%% A custom exometer entry is invoked by mapping a type to the module
%% name of the custom exometer entry module. All metrics created with the
%% given type will trigger the invocation of the new entry module. See
%% {@section Configuring type - entry maps} for details on how to setup
%% such maps.
%%
%% The life cycle of a an exometer entry consists of the following steps.
%%
%% + Metrics Creation
%% <br/>`new/3' is invoked by exometer to signal that a new metrics
%% should be created. The name of the new metric will be provided as
%% a list of atoms.
%%
%% + Update Data
%% <br/>Values will be sent to the entry through the `update/4'
%% function. The custom entry should store this value for the given
%% metric and break it down into data points that can be reported for
%% the metric.
%%
%% + Retrieve Value
%% <br/>`get_value/4' will be invoked by exometer to retrieve specific
%% data points from a given metric.
%%
%% See individual functions for details on the
%% in the exometer_entry behavior.
%%
%% === behaviour/0 ===
%%
%% The `behaviour()' function for an entry implementation should return
%% the atom `entry'. This function will be involved by the
%% exometer system in order to determine if a callback is
%% an entry or a probe.
%%
%% === new/3 ===
%%
%% The `new()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% new(Name, Type, Options)</pre>
%%
%% The custom entry should create the necessary state for the new metric and store
%% it for furure access through `update()' and `get_value()' calls.
%%
%% + `Name'
%% <br/>Specifies the name of the metric to be created as a list of atoms.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map). It can be used if several
%% different types are mapped to the same entry module.
%%
%% + `Options'
%% <br/>Specifies an option list that contains additional setup directives to
%% the entry. The actual options to support are implementation dependent.
%%
%% The `new()' function should return `{ok, Ref}' where Ref is a
%% tuple that will be provided as a reference argument to other calls
%% made into the module. Any other return formats will cancel the
%% creation of the new metric.
%%
%% === delete/3 ===
%%
%% The `delete()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% delete(Name, Type, Ref)</pre>
%%
%% The custom entry should free all resources associated with the given name.
%%
%% + `Name'
%% <br/>Specifies the name of the metric to be deleted as a list of atoms.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map).
%%
%% + `Ref'
%% <br/>Will contain the same tuple returned as `Ref' by the module's `new()' function.
%%
%% The `delete()' function shall return `ok'.
%%
%%
%% === get_value/4 ===
%%
%% The `get_value()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% get_value(Name, Type, Ref, DataPoints)</pre>
%%
%% The custom entry should retrieve the metric with the given name and
%% return the values of the specified data points. Data points can be
%% expected to be one or more of those returned by the entry's
%% `get_datapoints()' function.
%%
%% + `Name'
%% <br/>Specifies the name of the metric to update with a value.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map).
%%
%% + `Ref'
%% <br/>Will contain the same tuple returned as `Ref' by the module's `new()' function.
%%
%% + `DataPoints'
%% <br/>Will contain a list of data points, each picked from the list returned by
%% the module's `get_datapoints()' function.
%%
%% The `get_value()' function should calculate the values of the given
%% data points based on previous calls to `update()' and return them to the caller.
%%
%% The return format shall be:
%%
%% <pre lang="erlang">
%% {ok, [ { DataPoint, Value }, ...]}</pre>
%%
%% Each `{ DataPoint, Value }' tuple shall contain the name and value of
%% one of the data points provided as arguments to `get_value()'.
%%
%% If a data point is not valid (i.e. not in the list returned by
%% `get_datapoints()'), the returned tuple should be `{ DataPoint,
%% undefined }'.
%%
%%
%% === update/4 ===
%%
%% The `update()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% update(Name, Value, Type, Ref)</pre>
%%
%% + `Name'
%% <br/>Specifies the name of the metric to update.
%%
%% + `Value'
%% <br/>Specifies the new value to integrate into the given metric.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map).
%%
%% + `Ref'
%% <br/>Will contain the same tuple returned as `Ref' by the module's `new()' function.
%%
%% The `update()' function should update the data points for the metric with the
%% given name in preparation for future calls to `get_value()'.
%%
%% The return format shall be `ok'.
%%
%%
%% === reset/3 ===
%%
%% The `reset()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% reset(Name, Type, Ref)</pre>
%%
%% + `Name'
%% <br/>Specifies the name of the metric to reset.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map).
%%
%% + `Ref'
%% <br/>Will contain the same tuple returned as `Ref' by the module's `new()' function.
%%
%% The `reset()' function should revert the metric with the given name to
%% its original state. A counter, for example, should be reset to 0 while
%% histograms should be emptied.
%%
%% The return format shall be `ok'.
%%
%% === sample/3 ===
%%
%% The `sample()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% sample(Name, Type, Ref)</pre>
%%
%% + `Name'
%% <br/>Specifies the name of the metric to run the sample.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map).
%%
%% + `Ref'
%% <br/>Will contain the same tuple returned as `Ref' by the module's
%% `new()' function.
%%
%% This function is only used by probes, where it is periodically called
%% to sample a local sub system such as /proc or netlink in order to
%% update its data points.
%%
%% Any exometer entry-based implementation should do nothing and return
%% `ok'.
%%
%% === get_datapoints/3 ===
%%
%% The `get_datapoints()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% get_datapoints(Name, Type, Ref)</pre>
%%
%% + `Name'
%% <br/>Specifies the name of the metric to return available datapoints for.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map).
%%
%% + `Ref'
%% <br/>Will contain the same tuple returned as `Ref' by the module's
%% `new()' function.
%%
%% This function should return a list of all data points supported by
%% the exometer entry implementation. The returned data points shall
%% be supported by the module's `get_value()' function.
%%
%%
%% === setopts/3 ===
%%
%% The `setopts()' function is invoked as follows:
%%
%% <pre lang="erlang">
%% setopts(Entry, Options, Type, Ref)</pre>
%%
%% + `Entry'
%% The (opaque) exometer entry record. See {@link exometer_info} for
%% information on how to inspect the data structure.
%%
%% + `Options'
%% <br/>Specifies an option list that contains additional setup directives to
%% the entry. The actual options to support are implementation dependent.
%%
%% + `Type'
%% <br/>Specifies the type provided to the `exometer:new()' call (before it
%% was translated by the type - exometer entry map).
%%
%% + `Ref'
%% <br/>Will contain the same tuple returned as `Ref' by the module's
%% `new()' function.
%%
%% This function should modify the behavior of the given metric by the
%% options provided in the `Options' property list.
%%
%% The function should return either `ok' or `{error, Reason}', where
%% `Reason' contins a descriptive reason for a failure to set one or more
%% options.
%%
%% @end
-module(exometer_entry).
-include("exometer.hrl").
-export_type([name/0, type/0, options/0, datapoint/0, datapoints/0, value/0, ref/0, error/0]).
-type name() :: list().
-type type() :: atom().
-type options() :: [{atom(), any()}].
-type datapoints() :: [datapoint()].
-type datapoint() :: exometer:datapoint().
-type value() :: any().
-type ref() :: any().
-type error() :: {error, any()}.
-callback behaviour() -> exometer:behaviour().
-callback new(name(), type(), options()) ->
ok | {ok, ref()} | error().
-callback delete(name(), type(), ref()) ->
ok | error().
-callback get_value(name(), type(), ref(), datapoints()) ->
[{datapoint(), value()}].
-callback update(name(), value(), type(), ref()) ->
ok | {ok, value()} | error().
-callback reset(name(), type(), ref()) ->
ok | {ok, value()} | error().
-callback sample(name(), type(), ref()) ->
ok | error().
-callback get_datapoints(name(), type(), ref()) ->
datapoints().
-callback setopts(exometer:entry(), options(), exometer:status()) ->
ok | error().