Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support explicit_bucket_boundaries advisory parameters #628

Merged
merged 7 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions apps/opentelemetry_api_experimental/include/otel_metrics.hrl
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
-record(instrument, {module :: module(),
meter :: otel_meter:t(),
name :: otel_instrument:name(),
description :: otel_instrument:description() | undefined,
kind :: otel_instrument:kind(),
unit :: otel_instrument:unit() | undefined,
temporality :: otel_instrument:temporality(),
callback :: otel_instrument:callback() | undefined,
callback_args :: otel_instrument:callback_args() | undefined}).
-record(instrument, {module :: module(),
meter :: otel_meter:t(),
name :: otel_instrument:name(),
description :: otel_instrument:description() | undefined,
kind :: otel_instrument:kind(),
unit :: otel_instrument:unit() | undefined,
temporality :: otel_instrument:temporality(),
callback :: otel_instrument:callback() | undefined,
callback_args :: otel_instrument:callback_args() | undefined,
advisory_params :: otel_instrument:advisory_params() | undefined}).

-define(TEMPORALITY_DELTA, temporality_delta).
-define(TEMPORALITY_CUMULATIVE, temporality_cumulative).
Expand Down
2 changes: 1 addition & 1 deletion apps/opentelemetry_api_experimental/src/otel_counter.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
-spec create(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: otel_meter:t(),
Name :: otel_instrument:name(),
Opts :: otel_meter:opts().
Opts :: otel_instrument:opts().
create(Meter, Name, Opts) ->
otel_meter:create_counter(Meter, Name, Opts).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
-spec create(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: otel_meter:t(),
Name :: otel_instrument:name(),
Opts :: otel_meter:opts().
Opts :: otel_instrument:opts().
create(Meter, Name, Opts) ->
otel_meter:create_histogram(Meter, Name, Opts).

Expand Down
62 changes: 39 additions & 23 deletions apps/opentelemetry_api_experimental/src/otel_instrument.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
%%%-------------------------------------------------------------------------
-module(otel_instrument).

-export([new/6,
new/8,
-export([new/5,
new/7,
is_monotonic/1,
temporality/1]).

Expand All @@ -38,6 +38,12 @@

-type temporality() :: ?TEMPORALITY_DELTA | ?TEMPORALITY_CUMULATIVE.

-type advisory_params() :: #{explicit_bucket_boundaries => [number(), ...]}.

-type opts() :: #{description => description(),
unit => unit(),
advisory_params => advisory_params()}.

-type t() :: #instrument{}.

-export_type([t/0,
Expand All @@ -48,29 +54,39 @@
temporality/0,
callback/0,
callback_args/0,
callback_result/0]).
callback_result/0,
advisory_params/0,
opts/0]).

-spec new(module(), otel_meter:t(), kind(), name(), description() | undefined, unit() | undefined) -> t().
new(Module, Meter, Kind, Name, Description, Unit) ->
#instrument{module = Module,
meter = Meter,
name = Name,
description = Description,
temporality = ?TEMPORALITY_DELTA,
kind = Kind,
unit = Unit}.
-spec new(module(), otel_meter:t(), kind(), name(), opts()) -> t().
new(Module, Meter, Kind, Name, Opts) ->
Description = maps:get(description, Opts, undefined),
Unit = maps:get(unit, Opts, undefined),
AdvisoryParams = maps:get(advisory_params, Opts, undefined),
#instrument{module = Module,
meter = Meter,
name = Name,
description = Description,
temporality = ?TEMPORALITY_DELTA,
kind = Kind,
unit = Unit,
advisory_params = AdvisoryParams}.

-spec new(module(), otel_meter:t(), kind(), name(), description() | undefined, unit() | undefined, callback(), callback_args()) -> t().
new(Module, Meter, Kind, Name, Description, Unit, Callback, CallbackArgs) ->
#instrument{module = Module,
meter = Meter,
name = Name,
description = Description,
kind = Kind,
unit = Unit,
temporality = ?TEMPORALITY_CUMULATIVE,
callback = Callback,
callback_args = CallbackArgs}.
-spec new(module(), otel_meter:t(), kind(), name(), callback(), callback_args(), opts()) -> t().
new(Module, Meter, Kind, Name, Callback, CallbackArgs, Opts) ->
Description = maps:get(description, Opts, undefined),
Unit = maps:get(unit, Opts, undefined),
AdvisoryParams = maps:get(advisory_params, Opts, undefined),
#instrument{module = Module,
meter = Meter,
name = Name,
description = Description,
kind = Kind,
unit = Unit,
temporality = ?TEMPORALITY_CUMULATIVE,
callback = Callback,
callback_args = CallbackArgs,
advisory_params = AdvisoryParams}.

is_monotonic(#instrument{kind=?KIND_COUNTER}) ->
true;
Expand Down
32 changes: 14 additions & 18 deletions apps/opentelemetry_api_experimental/src/otel_meter.erl
Original file line number Diff line number Diff line change
Expand Up @@ -42,55 +42,51 @@
Meter :: t(),
Name :: otel_instrument:name(),
Kind :: otel_instrument:kind(),
Opts :: opts().
Opts :: otel_instrument:opts().

-callback create_instrument(Meter, Name, Kind, Callback, CallbackArgs, Opts) -> otel_instrument:t() when
Meter :: t(),
Name :: otel_instrument:name(),
Kind :: otel_instrument:kind(),
Callback :: otel_instrument:callback(),
CallbackArgs :: otel_instrument:callback_args(),
Opts :: opts().
Opts :: otel_instrument:opts().

-callback register_callback(Meter, Instruments, Callback, CallbackArgs) -> ok when
Meter :: t(),
Instruments :: otel_instrument:t(),
Callback :: otel_instrument:callback(),
CallbackArgs :: otel_instrument:callback_args().

-type opts() :: #{description => otel_instrument:description(),
unit => otel_instrument:unit()}.

-type t() :: {module(), term()}.

-export_type([t/0,
opts/0]).
-export_type([t/0]).

-spec create_counter(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: t(),
Name :: otel_instrument:name(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_counter(Meter, Name, Opts) ->
create_instrument(Meter, Name, ?KIND_COUNTER, Opts).

-spec create_updown_counter(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: t(),
Name :: otel_instrument:name(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_updown_counter(Meter, Name, Opts) ->
create_instrument(Meter, Name, ?KIND_UPDOWN_COUNTER, Opts).

-spec create_histogram(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: t(),
Name :: otel_instrument:name(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_histogram(Meter, Name, Opts) ->
create_instrument(Meter, Name, ?KIND_HISTOGRAM, Opts).

-spec create_observable_counter(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: t(),
Name :: otel_instrument:name(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_observable_counter(Meter, Name, Opts) ->
create_instrument(Meter, Name, ?KIND_OBSERVABLE_COUNTER, Opts).

Expand All @@ -99,14 +95,14 @@ create_observable_counter(Meter, Name, Opts) ->
Name :: otel_instrument:name(),
Callback :: otel_instrument:callback(),
CallbackArgs :: otel_instrument:callback_args(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_observable_counter(Meter, Name, Callback, CallbackArgs, Opts) ->
create_instrument(Meter, Name, ?KIND_OBSERVABLE_COUNTER, Callback, CallbackArgs, Opts).

-spec create_observable_gauge(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: t(),
Name :: otel_instrument:name(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_observable_gauge(Meter, Name, Opts) ->
create_instrument(Meter, Name, ?KIND_OBSERVABLE_GAUGE, Opts).

Expand All @@ -115,14 +111,14 @@ create_observable_gauge(Meter, Name, Opts) ->
Name :: otel_instrument:name(),
Callback :: otel_instrument:callback(),
CallbackArgs :: otel_instrument:callback_args(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_observable_gauge(Meter, Name, Callback, CallbackArgs, Opts) ->
create_instrument(Meter, Name, ?KIND_OBSERVABLE_GAUGE, Callback, CallbackArgs, Opts).

-spec create_observable_updowncounter(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: t(),
Name :: otel_instrument:name(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_observable_updowncounter(Meter, Name, Opts) ->
create_instrument(Meter, Name, ?KIND_OBSERVABLE_UPDOWNCOUNTER, Opts).

Expand All @@ -131,7 +127,7 @@ create_observable_updowncounter(Meter, Name, Opts) ->
Name :: otel_instrument:name(),
Callback :: otel_instrument:callback(),
CallbackArgs :: otel_instrument:callback_args(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_observable_updowncounter(Meter, Name, Callback, CallbackArgs, Opts) ->
create_instrument(Meter, Name, ?KIND_OBSERVABLE_UPDOWNCOUNTER, Callback, CallbackArgs, Opts).

Expand All @@ -145,7 +141,7 @@ scope(Meter={Module, _}) ->
Meter :: t(),
Name :: otel_instrument:name(),
Kind :: otel_instrument:kind(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_instrument(Meter={Module, _}, Name, Kind, Opts) ->
Module:create_instrument(Meter, Name, Kind, Opts).

Expand All @@ -155,7 +151,7 @@ create_instrument(Meter={Module, _}, Name, Kind, Opts) ->
Kind :: otel_instrument:kind(),
Callback :: otel_instrument:callback(),
CallbackArgs :: otel_instrument:callback_args(),
Opts :: opts().
Opts :: otel_instrument:opts().
create_instrument(Meter={Module, _}, Name, Kind, Callback, CallbackArgs, Opts) ->
Module:create_instrument(Meter, Name, Kind, Callback, CallbackArgs, Opts).

Expand Down
6 changes: 2 additions & 4 deletions apps/opentelemetry_api_experimental/src/otel_meter_noop.erl
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ register_callback(_Meter, _Instruments, _Callback, _CallbackArgs) ->
ok.

create_instrument(Meter, Name, Kind, Opts) ->
otel_instrument:new(?MODULE, Meter, Kind, Name, maps:get(description, Opts, undefined),
maps:get(unit, Opts, undefined)).
otel_instrument:new(?MODULE, Meter, Kind, Name, Opts).

create_instrument(Meter, Name, Kind, Callback, CallbackArgs, Opts) ->
otel_instrument:new(?MODULE, Meter, Kind, Name, maps:get(description, Opts, undefined),
maps:get(unit, Opts, undefined), Callback, CallbackArgs).
otel_instrument:new(?MODULE, Meter, Kind, Name, Callback, CallbackArgs, Opts).
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
-spec create(Meter, Name, Opts) -> otel_instrument:t() when
Meter :: otel_meter:t(),
Name :: otel_instrument:name(),
Opts :: otel_meter:opts().
Opts :: otel_instrument:opts().
create(Meter, Name, Opts) ->
otel_meter:create_updown_counter(Meter, Name, Opts).

Expand Down
40 changes: 34 additions & 6 deletions apps/opentelemetry_experimental/src/otel_meter_default.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@

-define(INSTRUMENT_NAME_REGEX, "^[A-Za-z]+[A-Za-z0-9/_.\-]{0,254}$").

-spec create_instrument(otel_meter:t(), otel_instrument:name(), otel_instrument:kind(), otel_meter:opts()) -> otel_instrument:t().
-spec create_instrument(otel_meter:t(), otel_instrument:name(), otel_instrument:kind(), otel_instrument:opts()) -> otel_instrument:t().
create_instrument(Meter, Name, Kind, Opts) ->
validate_name(Name),
ValidatedOpts = validate_opts(Name, Kind, Opts),
Instrument=#instrument{meter={_, #meter{provider=Provider}}} =
otel_instrument:new(?MODULE, Meter, Kind, Name, maps:get(description, Opts, undefined),
maps:get(unit, Opts, undefined)),
otel_instrument:new(?MODULE, Meter, Kind, Name, ValidatedOpts),
_ = otel_meter_server:add_instrument(Provider, Instrument),
Instrument.

Expand All @@ -52,12 +52,12 @@ lookup_instrument(Meter={_, #meter{instruments_tab=Tab}}, Name) ->
undefined
end.

-spec create_instrument(otel_meter:t(), otel_instrument:name(), otel_instrument:kind(), otel_instrument:callback(), otel_instrument:callback_args(), otel_meter:opts()) -> otel_instrument:t().
-spec create_instrument(otel_meter:t(), otel_instrument:name(), otel_instrument:kind(), otel_instrument:callback(), otel_instrument:callback_args(), otel_instrument:opts()) -> otel_instrument:t().
create_instrument(Meter, Name, Kind, Callback, CallbackArgs, Opts) ->
validate_name(Name),
ValidatedOpts = validate_opts(Name, Kind, Opts),
Instrument=#instrument{meter={_, #meter{provider=Provider}}} =
otel_instrument:new(?MODULE, Meter, Kind, Name, maps:get(description, Opts, undefined),
maps:get(unit, Opts, undefined), Callback, CallbackArgs),
otel_instrument:new(?MODULE, Meter, Kind, Name, Callback, CallbackArgs, ValidatedOpts),
_ = otel_meter_server:add_instrument(Provider, Instrument),
Instrument.

Expand All @@ -81,6 +81,34 @@ validate_name(Name) when is_atom(Name) ->
validate_name(Name) ->
?LOG_ERROR("Invalid instrument name, should be an atom matching '~s', but got ~p", [?INSTRUMENT_NAME_REGEX, Name]),
ok.

validate_opts(Name, Kind, #{advisory_params := AdvisoryParams} = Opts) ->
% switch to maps:filtermap when we support only 24 onwards
ValidatedAdvisoryParams = maps:from_list(lists:filtermap(fun({Key, Value}) -> validate_advisory_param(Name, Kind, Key, Value) end, maps:to_list(AdvisoryParams))),
maps:put(advisory_params, ValidatedAdvisoryParams, Opts);
validate_opts(_Name, _Kind, Opts) ->
Opts.

validate_advisory_param(Name, ?KIND_HISTOGRAM, explicit_bucket_boundaries, Value) ->
validate_explicit_bucket_boundaries(Name, Value);
validate_advisory_param(Name, _Kind, explicit_bucket_boundaries, _Value) ->
?LOG_WARNING("[instrument '~s'] 'explicit_bucket_boundaries' advisory parameter is allowed only for histograms, ignoring", [Name]),
false;
validate_advisory_param(Name, _Kind, Opt, _Value) ->
?LOG_WARNING("[instrument '~s'] '~s' advisory parameter is not supported, ignoring", [Name, Opt]),
false.

validate_explicit_bucket_boundaries(Name, [_ | _] = Value) ->
case lists:all(fun is_number/1, Value) and (lists:sort(Value) == Value) of
true ->
{true, {explicit_bucket_boundaries, Value}};
false ->
?LOG_WARNING("[instrument '~s'] 'explicit_bucket_boundaries' advisory parameter should be a not empty ordered list of numbers, got ~p", [Name, Value]),
false
end;
validate_explicit_bucket_boundaries(Name, Value) ->
?LOG_WARNING("[instrument '~s'] 'explicit_bucket_boundaries' advisory parameter should be a not empty ordered list of numbers, got ~p", [Name, Value]),
false.
%%

record(Instrument=#instrument{meter={_, #meter{view_aggregations_tab=ViewAggregationTab,
Expand Down
2 changes: 0 additions & 2 deletions apps/opentelemetry_experimental/src/otel_meter_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,6 @@ view_aggregation_for_reader(Instrument=#instrument{kind=Kind}, ViewAggregation,
reader=Id,
attribute_keys=AttributeKeys,
aggregation_module=AggregationModule,
aggregation_options=#{},
temporality=Temporality};
view_aggregation_for_reader(Instrument=#instrument{kind=Kind}, ViewAggregation, View,
Reader=#reader{id=Id,
Expand All @@ -404,7 +403,6 @@ view_aggregation_for_reader(Instrument=#instrument{kind=Kind}, ViewAggregation,
reader=Id,
attribute_keys=undefined,
aggregation_module=AggregationModule,
aggregation_options=#{},
temporality=Temporality}.


Expand Down
Loading
Loading