opentelemetry_api_experimental

Signals still in experimental status in the Erlang/Elixir API.

Metrics

For configuration of the Experimental SDK for Metrics see the experimental SDK opentelemtry_experimental. Without the SDK all operations for instruments and recording to them will be no-ops and nothing will be created or exported.

Quickstart

The metrics API is used for instrumenting application code through the creation of instruments and calls to record data points with them.

Instrument Creation

Supported Instruments

There are 3 synchronous instrument types and 3 observable instruments that are tied to a callback function. The list below gives each instrument type supported and details on the default aggregation used for the measurements recorded for that instrument:

Macros

The header otel_meter.hrl contains macros for working with Instruments. This includes creation in the form create_<instrument type> and recording measurements like counter_add and histogram_record.

Below is example creation found in the dice_roll_elli example:

-include_lib("opentelemetry_api_experimental/include/otel_meter.hrl").
?create_counter(?ROLL_COUNTER, #{description => <<"The number of rolls by roll value.">>,
unit => '1'}).

Instrument Recording

Measurements are taken on an instrument through recordings. Each type of instrument has functions and macros specific to its type for recording measurements. Counters can be added to so have the counter_add macro, UpDown counters can also be added to (but with the addition of accepting negative numbers) so have updown_counter_add and Histograms are passed recordings so have the macro histogram_record.

An example from dice_roll_elli example of recording an addition to a counter with an attribute:

?counter_add(?ROLL_COUNTER, 1, #{'roll.value' => Roll}),

See the Experimental SDK's README.md for how to setup Views for aggregation and then the exporting of metrics.

Details

Meter Provider

The Meter Provider (here the default implementation is in the module otel_meter_server in the SDK) is responsible for creating Meters and stores their shared configuration along with the shared Resource of the telemetry created for those Meters. Including the SDK application ensures a default Provider is created and used during Meter creation.

Meter

Meters (default implementation found in otel_meter_default in the SDK) are used to create Instruments. Direct interaction with a Meter is not required except for special cases where the provided macros aren't enough to get the job done. The majority of use is done behind the macros.

Measurement

Measurements are individual data points and their associated attributes.

Instrument

An instrument is used to capture measurements.

Supported instrument kinds:

The first 3 are synchronous instruments while the latter 3 must be associated with a callback function.

To record measurements an instrument must first be created. Each instrument kind has a ?create_<kind> macro in Erlang for creation:

_RequestCounter = ?create_counter(app_request_counter, #{description => ~"Count of number of requests"})

Now the instrument can be used to record measurements either by passing the atom name app_request_counter:

?counter_add(app_request_counter, 5, #{<<"a">> => <<"b">>}),

For synchronous instruments the available macros are:

The asynchronous (observable) instruments can be created with their callback or be later registered with a callback that supports multiple instruments.

When created with a callback for the instrument the callback returns a list of values and attributes to record for that instrument:

?create_observable_counter(my_observable_counter,
fun(_Args) ->
[{4, #{a => <<"b">>}},
{12, #{c => <<"d">>}]
end,
[],
#{description => <<"Describe your instrument">>,
unit => kb})

When the measurements are taken from the same source it is more efficient to create a single callback for multiple instruments:

ProcessCountName = 'beam_processes',
AtomCountName = 'beam_atoms',
ProcessGauge = ?create_observable_gauge(ProcessCountName, #{description => <<"Number of currently running processes">>, unit => '1'}),
AtomGauge = ?create_observable_gauge(AtomCountName, #{description => <<"Number of created atoms">>, unit => '1'}),
?register_callback([ProcessGauge, AtomGauge],
fun(_) ->
ProcessCount = erlang:system_info(process_count),
AtomCount = erlang:system_info(atom_count),
[{ProcessCountName, [{ProcessCount, #{}}]},
{AtomCountName, [{AtomCount, #{}}]}]
end, [])

The callbacks are run when the Metric Reader collects metrics for export. See the Experimental SDK's README.md for more details on Metric Readers and their configuration.