%%%------------------------------------------------------------------------ %% Copyright 2022, OpenTelemetry Authors %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% @doc %% @end %%%------------------------------------------------------------------------- -module(otel_view). -export([new/2, new/3, match_instrument_to_views/2]). -include_lib("opentelemetry_api_experimental/include/otel_metrics.hrl"). -include("otel_view.hrl"). -type name() :: atom(). -type criteria() :: #{instrument_name => otel_instrument:name(), instrument_kind => otel_instrument:kind(), meter_name => unicode:unicode_binary() | undefined, meter_version => unicode:unicode_binary() | undefined, meter_schema_url => unicode:unicode_binary() | undefined}. -type config() :: #{description => unicode:unicode_binary(), attribute_keys => [atom()], aggregation => module() | default %% exemplar_reservoir }. -type t() :: #view{}. -type selection() :: #selection{}. -export_type([t/0, name/0, selection/0, criteria/0, config/0]). -include_lib("opentelemetry_api/include/gradualizer.hrl"). %% no name means Instrument name is used %% must reject wildcard Criteria in this case -spec new(criteria(), config()) -> t(). new(Criteria, Config) -> Selection = criteria_to_selection(Criteria), %% no name given so use the name of the instrument in the selection %% if no instrument name is given then it'll stay `undefined' #view{name=?assert_type(case Selection#selection.instrument_name of '_' -> undefined; N -> N end, undefined | unicode:latin1_binary() | unicode:latin1_charlist()), selection=Selection, description=maps:get(description, Config, undefined), attribute_keys=maps:get(attribute_keys, Config, undefined), aggregation_module=maps:get(aggregation, Config, undefined), aggregation_options=#{}}. -spec new(name(), criteria(), config()) -> t(). new(Name, Criteria, Config) -> View = new(Criteria, Config), View#view{name=Name}. -spec match_instrument_to_views(otel_instrument:t(), [otel_view:t()]) -> [{otel_view:t(), #view_aggregation{}}]. match_instrument_to_views(Instrument=#instrument{name=Name, meter=Meter, description=Description}, Views) -> IsMonotonic = otel_instrument:is_monotonic(Instrument), Temporality = otel_aggregation:instrument_temporality(Instrument), Scope = otel_meter:scope(Meter), case lists:filtermap(fun(View=#view{name=ViewName, description=ViewDescription, aggregation_options=AggregationOptions, selection=#selection{instrument_name=InstrumentName}}) when Name =:= InstrumentName -> {true, {View, #view_aggregation{name=value_or(ViewName, InstrumentName), scope=Scope, instrument=Instrument, temporality=Temporality, is_monotonic=IsMonotonic, aggregation_options=AggregationOptions, description=value_or(ViewDescription, Description) }}}; (_) -> false end, Views) of [] -> [{#view{}, #view_aggregation{name=Name, scope=Scope, instrument=Instrument, temporality=Temporality, is_monotonic=IsMonotonic, aggregation_options=[], description=Description}}]; Aggs -> Aggs end. %% value_or(undefined, Other) -> Other; value_or(Value, _Other) -> Value. criteria_to_selection(Criteria) -> maps:fold(fun(instrument_name, InstrumentName, SelectionAcc) -> SelectionAcc#selection{instrument_name=InstrumentName}; (instrument_kind, Kind, SelectionAcc) -> SelectionAcc#selection{instrument_kind=Kind}; (meter_name, MeterName, SelectionAcc) -> SelectionAcc#selection{meter_name=MeterName}; (meter_version, MeterVersion, SelectionAcc) -> SelectionAcc#selection{meter_version=MeterVersion}; (meter_schema_url, SchemaUrl, SelectionAcc) -> SelectionAcc#selection{schema_url=SchemaUrl} end, #selection{}, Criteria).