Skip to content

Latest commit

 

History

History
596 lines (306 loc) · 14.7 KB

exometer_function.md

File metadata and controls

596 lines (306 loc) · 14.7 KB

Module exometer_function

Behaviours: exometer_entry.

Data Types


arg() = $dp | {$call, atom(), atom(), arg_spec()} | any()

arg_spec() = [arg()]

binding() = {atom(), any()}

datapoints() = [atom()]

expr_atom() = atom() | {a, atom()} | {atom, atom()}

expr_binary_op() = {op, expr_operator(), expr(), expr()}

expr_call() = {call, atom(), [expr()]} | {call, {atom(), atom()}, [expr()]}

expr_case() = {case, [expr()], [expr_clause()]}

expr_clause() = {expr_pattern(), [expr_guard()], [expr()]}

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_list() = {cons, expr(), expr()} | nil | {l, [expr()]}

expr_match() = {match, expr_pattern(), expr()} | {m, expr_pattern(), expr()}

expr_operator() = + | - | * | / | div | rem | band | and | bor | bxor | bsl | bsr | or | xor | ++ | -- | == | /= | >= | =< | < | > | =:= | =/=

expr_pattern() = _ | expr_descr()

expr_string() = {string, string()} | {s, string()}

expr_tuple() = {tuple, [expr()]} | {t, [expr()]}

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()}

Function Index

behaviour/0
delete/3
empty/0
eval_exprs/2Evaluate a list of abstract expressions.
get_datapoints/3
get_value/4
new/3Callback for creating an exometer function entry.
preprocess_setopts/5
reset/3
sample/3
setopts/3
test_mem_info/1
update/4

Function Details

behaviour/0


behaviour() -> exometer:behaviour()

delete/3

delete(X1, X2, X3) -> any()

empty/0

empty() -> any()

eval_exprs/2


eval_exprs(Es::[expr()], Bs::[binding()]) -> {value, any(), [binding()]}

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/3

get_datapoints(Name, Type, T) -> any()

get_value/4

get_value(X1, X2, X3, DataPoints0) -> any()

new/3


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 calling apply(M, F, Args) where Args is the list of arguments after performing substitution on Args0.

  • {'$value', Term} uses Term 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 (see exometer_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}, and eval_exprs/2 will be used to evaluate Exprs. The return value from the function call will be bound to Value, and the list of data points will be bound to DPs. 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/5

preprocess_setopts(Name, Opts, Type, Ref, OldOpts) -> any()

reset/3

reset(X1, X2, X3) -> any()

sample/3

sample(X1, X2, X3) -> any()

setopts/3

setopts(X1, X2, X3) -> any()

test_mem_info/1

test_mem_info(DataPoints) -> any()

update/4

update(X1, X2, X3, X4) -> any()