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)whereArgsis the list of arguments after performing substitution onArgs0. -
{'$value', Term}usesTermwithout 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,DataPointsis 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,DataPointsis expected to be{Exprs, DPs}, andeval_exprs/2will 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()