Behaviours: exometer_entry
.
arg() = $dp | {$call, atom(), atom(), arg_spec()} | any()
arg_spec() = [arg()]
binding() = {atom(), any()}
datapoints() = [atom()]
expr() = expr_descr() | expr_action() | expr_match() | expr_erl()
expr_action() = expr_op() | expr_call() | expr_fold() | expr_case()
expr_atom() = atom() | {a, atom()} | {atom, atom()}
expr_binary_op() = {op, expr_operator(), expr(), expr()}
expr_case() = {case, [expr()], [expr_clause()]}
expr_clause() = {expr_pattern(), [expr_guard()], [expr()]}
expr_descr() = expr_int() | expr_atom() | expr_list() | expr_tuple() | expr_string()
expr_erl() = {erl, [erl_parse:abstract_expr()]}
expr_fold() = {fold, _IterVal::atom(), _AccVar::atom(), _IterExpr::[expr()], _Acc0Expr::expr(), _ListExpr::expr()}
expr_guard() = [expr()]
Must all return 'true'.
expr_int() = integer() | {i, integer()} | {integer, integer()}
expr_match() = {match, expr_pattern(), expr()} | {m, expr_pattern(), expr()}
expr_op() = expr_unary_op() | expr_binary_op()
expr_operator() = + | - | * | / | div | rem | band | and | bor | bxor | bsl | bsr | or | xor | ++ | -- | == | /= | >= | =< | < | > | =:= | =/=
expr_pattern() = _ | expr_descr()
expr_string() = {string, string()} | {s, string()}
expr_unary_op() = {op, - | not, expr()}
extended_fun() = {function, mod_name(), fun_name(), arg_spec(), res_type(), datapoints()}
fun_name() = atom()
fun_rep() = {mod_name(), fun_name()} | {mod_name(), fun_name(), each | once, arg_spec(), res_type(), datapoints()} | {mod_name(), fun_name(), each | once, arg_spec(), match, any()} | {eval, [expr()], datapoints()}
fun_spec() = simple_fun() | extended_fun()
mod_name() = atom()
res_type() = value | proplist | tagged
simple_fun() = {function, mod_name(), fun_name()}
behaviour/0 | |
delete/3 | |
empty/0 | |
eval_exprs/2 | Evaluate a list of abstract expressions. |
get_datapoints/3 | |
get_value/4 | |
new/3 | Callback for creating an exometer function entry. |
preprocess_setopts/5 | |
reset/3 | |
sample/3 | |
setopts/3 | |
test_mem_info/1 | |
update/4 |
behaviour() -> exometer:behaviour()
delete(X1, X2, X3) -> any()
empty() -> any()
Evaluate a list of abstract expressions.
This function is reminiscent of erl_eval:exprs/2
, but with a slightly
different expression grammar. Most prominently, forms have no line numbers,
and a few aliases for more compact representation. Otherwise, the forms can
be seen as mostly a subset of the Erlang abstract forms.
The list of bindings correspods exactly to the bindings in erl_eval
.
- Integers:
{integer, I}
,{i, I}
, or simply just the integer - Atoms:
{atom, A}
,{a, A}
, or simply just the atom (note that some atoms are special). - Lists:
{cons, H, T}
,nil
, or{l, [...]}
- Tuples:
{tuple, [Elem]}
, or{t, [Elem]}
- Variables:
{var, V}
, or{v, V}
- Matches:
{match, Pattern, Expr}
, or{m, Pattern, Expr}
- Function calls:
{call, {M, F}, Args}
, or{call, F, Args}
- Folds:
{fold, IterVar, AccVar, [IterExpr], Acc0Expr, ListExpr}
- Operators:
{op, Op, ExprA, ExprB}
- Unary operators:
{op, '-' | 'not', Expr}
- Case exprs:
{'case', [Expr], [{Pat, Gs, Body}]}
- Generic Erlang:
{erl, [ErlAbstractExpr]}
The currently supported "built-in functions" are length/1
, size/1
,
byte_size/1
and bit_size/1
.
The operators supported are all the Erlang binary operators (as in: '+', '-', '==', '=/=', etc.)
When evaluating guards in a case clause, any expression is legal. The guard must return true to succeed. Note that the abstract form of a guard sequence is [ [G11,...], [G21,...], ...], where each sublist represents an 'and' sequence, i.e. all guards in the sublist must succeed. The relationship between sublists is 'or'. This is the same as in Erlang.
get_datapoints(Name, Type, T) -> any()
get_value(X1, X2, X3, DataPoints0) -> any()
new(Name::exometer:name(), X2::function, Opts::exometer:options()) -> {ok, fun_rep()}
Callback for creating an exometer function
entry.
Function entries are created as
exometer:new(Name,{function,...},Opts)
which is syntactic sugar for
exometer:new(Name,function,[{arg,{function,...}}|Opts])
{function,...}
can be {function, Mod, Fun}
, in which case
where get_value(Name, DataPoints)
will result in a call to
Mod:Fun(DataPoints)
.
Invoking get_value(Name) (with no datapoints), will call
`Mod:Fun(default), which must return a default list of data point
values.
{function,...}
can also be setup as {function, Mod,Fun,ArgSpec,Type,DataPoints}
in order to invoke a limited
interpreter. The ArgSpec
is evaluated as follows:
-
[]
means to call with no arguments, i.e.M:F()
-
A list of patterns will be used as arguments, substituting the following patterns:
-
'$dp'
is replaced by the current data point -
'$datapoints'
is replaced by the requested list of data points. Note that'$dp'
and'$datapoints'
are mutually exclusive -
{'$call', M, F, Args0}
will be replaced by the result of callingapply(M, F, Args)
whereArgs
is the list of arguments after performing substitution onArgs0
. -
{'$value', Term}
usesTerm
without substitution.
The return value of the above call will be processed according to Type
:
-
If
Type==value
, the return value is returned as-is -
If
Type==histogram
, the return value is a list of integers, which will be compiled into a histogram (seeexometer_histogram
). -
If
Type==proplist
, the current data point or list of data points will be picked out of the returned proplist. -
If
Type==tagged
, the return value is assumed to be either{ok, Value}
or{DataPointName, Value}
. -
If
Type==match
,DataPoints
is used as a pattern to match against, where the names of data points are used where the values are expected to be, and'_'
is used for values to ignore. The pattern can be any combination of tuples and lists of datapoints or'_'
. -
If
Type==eval
,DataPoints
is expected to be{Exprs, DPs}
, andeval_exprs/2
will be used to evaluateExprs
. The return value from the function call will be bound toValue
, and the list of data points will be bound toDPs
. The evaluation must return a list of{DataPointName, Value}
tuples.
An alternative version of arg
is {arg, {eval, Exprs, Datapoints}}
, which
doesn't in fact call a function, but simply evaluates Exprs
using
eval_exprs/2
, with the pre-bound variables Value = undefined
and DPs = Datapoints
.
Examples:
An entry that returns a subset of erlang:memory()
:
exometer:new([mem], {function,erlang,memory,[],proplist,[total,processes]}).
An entry that reports the heap size and message queue length of the code server:
exometer:new(
[code_server, pinfo],
{function,erlang,process_info,[{'$call',erlang,whereis,[code_server]}],
proplist, [heap_size, message_queue_len]}).
An entry that reports the heap size of the code server.
exometer:new(
[code_server, heap_size],
{function,erlang,process_info,
[{'$call',erlang,whereis,[code_server]}, '$dp'], tagged, [heap_size]}).
An entry that does pattern-matching on the return value
(erlang:statistics(garbage_collection)
returns {GCs, Reclaimed, 0}
).
exometer:new(
[gc],
{ function,erlang,statistics,[garbage_collection],
match, {gcs,reclaimed,'_'} }, []).
An entry that calls erlang:processes()
and evaluates a list of expressions
that calculate the length of the returned list.
exometer:new(
[ps],
{function,erlang,processes,[],
eval, {[{l,[{t,[value,{call,length,[{v,'Value'}]}]}]}],[value]}}, []).
An entry that simply builds a list of datapoints, using the abstract syntax.
exometer:new([stub],
{function,{eval,[{l,[{t,[{a,1}]},{t,[{b,2}]}]}], [a,b]}}, []).
preprocess_setopts(Name, Opts, Type, Ref, OldOpts) -> any()
reset(X1, X2, X3) -> any()
sample(X1, X2, X3) -> any()
setopts(X1, X2, X3) -> any()
test_mem_info(DataPoints) -> any()
update(X1, X2, X3, X4) -> any()