Skip to content

Commit 840b120

Browse files
committed
Use explicit_histogram_buckets if not configured in view
1 parent 3b406dc commit 840b120

File tree

3 files changed

+98
-6
lines changed

3 files changed

+98
-6
lines changed

apps/opentelemetry_experimental/src/otel_meter_server.erl

-2
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,6 @@ view_aggregation_for_reader(Instrument=#instrument{kind=Kind}, ViewAggregation,
392392
reader=Id,
393393
attribute_keys=AttributeKeys,
394394
aggregation_module=AggregationModule,
395-
aggregation_options=#{},
396395
temporality=Temporality};
397396
view_aggregation_for_reader(Instrument=#instrument{kind=Kind}, ViewAggregation, View,
398397
Reader=#reader{id=Id,
@@ -404,7 +403,6 @@ view_aggregation_for_reader(Instrument=#instrument{kind=Kind}, ViewAggregation,
404403
reader=Id,
405404
attribute_keys=undefined,
406405
aggregation_module=AggregationModule,
407-
aggregation_options=#{},
408406
temporality=Temporality}.
409407

410408

apps/opentelemetry_experimental/src/otel_view.erl

+13-3
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ new(Name, Criteria, Config) ->
7878
-spec match_instrument_to_views(otel_instrument:t(), [t()]) -> [{t() | undefined, #view_aggregation{}}].
7979
match_instrument_to_views(Instrument=#instrument{name=InstrumentName,
8080
meter=Meter,
81-
description=Description}, Views) ->
81+
description=Description,
82+
advisory_params=AdvisoryParams}, Views) ->
8283
IsMonotonic = otel_instrument:is_monotonic(Instrument),
8384
Temporality = otel_instrument:temporality(Instrument),
8485
Scope = otel_meter:scope(Meter),
@@ -91,6 +92,7 @@ match_instrument_to_views(Instrument=#instrument{name=InstrumentName,
9192
[] ->
9293
false;
9394
_ ->
95+
AggregationOptions1 = aggragation_options(AggregationOptions, AdvisoryParams),
9496
%% `reader' needs to be undefined and is set
9597
%% for each in `otel_meter_server'
9698
%% eqwalizer:ignore see above
@@ -101,27 +103,35 @@ match_instrument_to_views(Instrument=#instrument{name=InstrumentName,
101103
temporality=Temporality,
102104
is_monotonic=IsMonotonic,
103105
attribute_keys=AttributeKeys,
104-
aggregation_options=AggregationOptions,
106+
aggregation_options=AggregationOptions1,
105107
description=value_or(ViewDescription,
106108
Description)
107109
}}}
108110
end
109111
end, Views) of
110112
[] ->
113+
AggregationOptions1 = aggragation_options(#{}, AdvisoryParams),
111114
[{undefined, #view_aggregation{name=InstrumentName,
112115
scope=Scope,
113116
instrument=Instrument,
114117
temporality=Temporality,
115118
is_monotonic=IsMonotonic,
116119
attribute_keys=undefined,
117-
aggregation_options=#{},
120+
aggregation_options=AggregationOptions1,
118121
description=Description}}];
119122
Aggs ->
120123
Aggs
121124
end.
122125

123126
%%
124127

128+
aggragation_options(#{boundaries := _} = AggregationOptions, _AdvisoryParams) ->
129+
AggregationOptions;
130+
aggragation_options(AggregationOptions, #{explicit_bucket_boundaries := Boundaries}) ->
131+
maps:put(boundaries, Boundaries, AggregationOptions);
132+
aggragation_options(AggregationOptions, _AdvisoryParams) ->
133+
AggregationOptions.
134+
125135
value_or(undefined, Other) ->
126136
Other;
127137
value_or(Value, _Other) ->

apps/opentelemetry_experimental/test/otel_metrics_SUITE.erl

+85-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ all() ->
8383
kill_reader, kill_server, observable_counter, observable_updown_counter, observable_gauge,
8484
multi_instrument_callback, using_macros, float_counter, float_updown_counter, float_histogram,
8585
sync_filtered_attributes, async_filtered_attributes, delta_observable_counter,
86-
bad_observable_return, default_resource
86+
bad_observable_return, default_resource, advisory_params
8787
].
8888

8989
init_per_suite(Config) ->
@@ -1130,3 +1130,87 @@ bad_observable_return(_Config) ->
11301130
?assertSumReceive(CounterName2, <<"observable counter 2 description">>, kb, [{8, #{}}]),
11311131

11321132
ok.
1133+
1134+
advisory_params(_Config) ->
1135+
DefaultMeter = otel_meter_default,
1136+
1137+
Meter = opentelemetry_experimental:get_meter(),
1138+
?assertMatch({DefaultMeter, _}, Meter),
1139+
1140+
% explicit_bucket_boundaries allowed only for histograms
1141+
Counter = otel_counter:create(Meter, invalid_1,
1142+
#{advisory_params => #{explicit_bucket_boundaries => [1, 2, 3]}}),
1143+
?assertEqual(Counter#instrument.advisory_params, #{}),
1144+
1145+
% advisory parameters different from explicit_bucket_boundaries are not allowed
1146+
Counter1 = otel_counter:create(Meter, invalid_2, #{advisory_params => #{invalid => invalid}}),
1147+
?assertEqual(Counter1#instrument.advisory_params, #{}),
1148+
1149+
% explicit_bucket_boundaries should be an ordered list of numbers
1150+
Histo1 = otel_histogram:create(Meter, invalid_3,
1151+
#{advisory_params => #{explicit_bucket_boundaries => invalid}}),
1152+
?assertEqual(Histo1#instrument.advisory_params, #{}),
1153+
1154+
Histo2 = otel_histogram:create(Meter, invalid_4,
1155+
#{advisory_params => #{explicit_bucket_boundaries => [2,1,4]}}),
1156+
?assertEqual(Histo2#instrument.advisory_params, #{}),
1157+
1158+
% when valid use the explicit_bucket_boundaries from advisory_params if not set in a view
1159+
Histogram = otel_histogram:create(Meter, a_histogram,
1160+
#{advisory_params => #{explicit_bucket_boundaries => [10, 20, 30]}}),
1161+
?assertEqual(Histogram#instrument.advisory_params, #{explicit_bucket_boundaries => [10, 20, 30]}),
1162+
1163+
?assertEqual(ok, otel_histogram:record(Histogram, 15, #{<<"a">> => <<"1">>})),
1164+
?assertEqual(ok, otel_histogram:record(Histogram, 50, #{<<"a">> => <<"1">>})),
1165+
?assertEqual(ok, otel_histogram:record(Histogram, 26, #{<<"a">> => <<"2">>})),
1166+
1167+
otel_meter_server:force_flush(),
1168+
1169+
receive
1170+
{otel_metric, #metric{name=a_histogram,
1171+
data=#histogram{datapoints=Datapoints}}} ->
1172+
AttributeBuckets =
1173+
lists:sort([{Attributes, Buckets, Min, Max, Sum} || #histogram_datapoint{bucket_counts=Buckets,
1174+
attributes=Attributes,
1175+
min=Min,
1176+
max=Max,
1177+
sum=Sum} <- Datapoints]),
1178+
?assertEqual([], [{#{<<"a">> => <<"1">>}, [0,1,0,1], 15, 50, 65},
1179+
{#{<<"a">> => <<"2">>}, [0,0,1,0], 26, 26, 26}]
1180+
-- AttributeBuckets, AttributeBuckets)
1181+
after
1182+
5000 ->
1183+
ct:fail(histogram_receive_timeout)
1184+
end,
1185+
1186+
% boundaries from view have precedence
1187+
?assert(otel_meter_server:add_view(view, #{instrument_name => b_histogram}, #{
1188+
aggregation_module => otel_aggregation_histogram_explicit,
1189+
aggregation_options => #{boundaries => [10, 100]}})),
1190+
1191+
HistogramB = otel_histogram:create(Meter, b_histogram,
1192+
#{advisory_params => #{explicit_bucket_boundaries => [10, 20, 30]}}),
1193+
?assertEqual(HistogramB#instrument.advisory_params, #{explicit_bucket_boundaries => [10, 20, 30]}),
1194+
1195+
?assertEqual(ok, otel_histogram:record(HistogramB, 15, #{<<"a">> => <<"1">>})),
1196+
?assertEqual(ok, otel_histogram:record(HistogramB, 50, #{<<"a">> => <<"1">>})),
1197+
?assertEqual(ok, otel_histogram:record(HistogramB, 26, #{<<"a">> => <<"2">>})),
1198+
1199+
otel_meter_server:force_flush(),
1200+
1201+
receive
1202+
{otel_metric, #metric{name=view,
1203+
data=#histogram{datapoints=DatapointsB}}} ->
1204+
AttributeBucketsB =
1205+
lists:sort([{Attributes, Buckets, Min, Max, Sum} || #histogram_datapoint{bucket_counts=Buckets,
1206+
attributes=Attributes,
1207+
min=Min,
1208+
max=Max,
1209+
sum=Sum} <- DatapointsB]),
1210+
?assertEqual([], [{#{<<"a">> => <<"1">>}, [0,2,0], 15, 50, 65},
1211+
{#{<<"a">> => <<"2">>}, [0,1,0], 26, 26, 26}]
1212+
-- AttributeBucketsB, AttributeBucketsB)
1213+
after
1214+
1000 ->
1215+
ct:fail(histogram_receive_timeout)
1216+
end.

0 commit comments

Comments
 (0)