diff --git a/apps/opentelemetry/include/otel_span.hrl b/apps/opentelemetry/include/otel_span.hrl index 40a2d4eef..b190d159e 100644 --- a/apps/opentelemetry/include/otel_span.hrl +++ b/apps/opentelemetry/include/otel_span.hrl @@ -16,11 +16,6 @@ %% @end %%%------------------------------------------------------------------------- -%% Holds information about the instrumentation library specified when -%% getting a Tracer from the TracerProvider. --record(instrumentation_library, {name :: unicode:unicode_binary() | undefined, - version :: unicode:unicode_binary() | undefined}). - %% The name, version and language of this OpenTelemetry library -record(telemetry_library, {name :: unicode:unicode_binary() | undefined, language :: unicode:unicode_binary() | undefined, @@ -70,5 +65,5 @@ %% trace flags lowest bit is 1 but simply not propagated. is_recording :: boolean() | undefined, - instrumentation_library :: #instrumentation_library{} | undefined + instrumentation_library :: opentelemetry:instrumentation_library() | undefined }). diff --git a/apps/opentelemetry/src/opentelemetry_app.erl b/apps/opentelemetry/src/opentelemetry_app.erl index e50c4dc69..ab2d5e224 100644 --- a/apps/opentelemetry/src/opentelemetry_app.erl +++ b/apps/opentelemetry/src/opentelemetry_app.erl @@ -62,8 +62,9 @@ register_loaded_application_tracers(Opts) -> register_loaded_applications_(RegisterLoadedApplications). register_loaded_applications_(true) -> + %% TODO: filter out OTP apps that will not have any instrumentation LoadedApplications = application:loaded_applications(), - [opentelemetry:register_application_tracer(Name) || {Name, _, _} <- LoadedApplications], + opentelemetry:register_application_tracers(LoadedApplications), ok; register_loaded_applications_(_) -> ok. diff --git a/apps/opentelemetry/src/otel_tracer_server.erl b/apps/opentelemetry/src/otel_tracer_server.erl index e1b36674d..b35b1a02d 100644 --- a/apps/opentelemetry/src/otel_tracer_server.erl +++ b/apps/opentelemetry/src/otel_tracer_server.erl @@ -20,8 +20,8 @@ -behaviour(otel_tracer_provider). -export([init/1, - register_tracer/4, register_tracer/3, + get_tracer/2, resource/1, code_change/1]). @@ -86,18 +86,11 @@ init(Opts) -> resource(#state{resource=Resource}) -> Resource. -register_tracer(Name, Vsn, Modules, #state{shared_tracer=Tracer, - deny_list=DenyList}) -> - %% TODO: support semver constraints in denylist - case proplists:is_defined(Name, DenyList) of - true -> - opentelemetry:set_tracer(Name, {otel_tracer_noop, []}); - false -> - InstrumentationLibrary = otel_utils:instrumentation_library(Name, Vsn), - TracerTuple = {Tracer#tracer.module, - Tracer#tracer{instrumentation_library=InstrumentationLibrary}}, - [opentelemetry:set_tracer(M, TracerTuple) || M <- Modules] - end. +get_tracer(InstrumentationLibrary, #state{shared_tracer=Tracer, + deny_list=_DenyList}) -> + + {Tracer#tracer.module, + Tracer#tracer{instrumentation_library=InstrumentationLibrary}}. register_tracer(Name, Vsn, #state{shared_tracer=Tracer, deny_list=DenyList}) -> @@ -106,7 +99,7 @@ register_tracer(Name, Vsn, #state{shared_tracer=Tracer, true -> opentelemetry:set_tracer(Name, {otel_tracer_noop, []}); false -> - InstrumentationLibrary = otel_utils:instrumentation_library(Name, Vsn), + InstrumentationLibrary = opentelemetry:instrumentation_library(Name, Vsn), TracerTuple = {Tracer#tracer.module, Tracer#tracer{instrumentation_library=InstrumentationLibrary}}, opentelemetry:set_tracer(Name, TracerTuple) diff --git a/apps/opentelemetry/src/otel_utils.erl b/apps/opentelemetry/src/otel_utils.erl deleted file mode 100644 index 29f7b93a4..000000000 --- a/apps/opentelemetry/src/otel_utils.erl +++ /dev/null @@ -1,29 +0,0 @@ --module(otel_utils). - --export([instrumentation_library/2]). - --include("otel_span.hrl"). - -instrumentation_library(Name, Vsn) -> - #instrumentation_library{name=name_to_binary(Name), - version=vsn_to_binary(Vsn)}. - -%% Vsn can't be an atom or anything but a list or binary -%% so return `undefined' if it isn't a list or binary. -vsn_to_binary(Vsn) when is_list(Vsn) -> - list_to_binary(Vsn); -vsn_to_binary(Vsn) when is_binary(Vsn) -> - Vsn; -vsn_to_binary(_) -> - undefined. - -%% name can be atom, list or binary. But atom `undefined' -%% must stay as `undefined' atom. -name_to_binary(undefined)-> - undefined; -name_to_binary(T) when is_atom(T) -> - atom_to_binary(T, utf8); -name_to_binary(T) when is_list(T) -> - list_to_binary(T); -name_to_binary(T) when is_binary(T) -> - T. diff --git a/apps/opentelemetry/test/opentelemetry_SUITE.erl b/apps/opentelemetry/test/opentelemetry_SUITE.erl index e54b3e503..19b420681 100644 --- a/apps/opentelemetry/test/opentelemetry_SUITE.erl +++ b/apps/opentelemetry/test/opentelemetry_SUITE.erl @@ -65,12 +65,12 @@ end_per_testcase(_, _Config) -> ok. disable_auto_registration(_Config) -> - {_, #tracer{instrumentation_library=Library}} = opentelemetry:get_tracer(kernel), + {_, #tracer{instrumentation_library=Library}} = opentelemetry:get_application_tracer(kernel), ?assertEqual(undefined, Library), ok. registered_tracers(_Config) -> - {_, #tracer{instrumentation_library=Library}} = opentelemetry:get_tracer(kernel), + {_, #tracer{instrumentation_library=Library}} = opentelemetry:get_application_tracer(kernel), ?assertEqual(<<"kernel">>, Library#instrumentation_library.name), %% register a new tracer with the same name but different version @@ -78,6 +78,12 @@ registered_tracers(_Config) -> {_, #tracer{instrumentation_library=NewLibrary}} = opentelemetry:get_tracer(kernel), ?assertEqual(<<"kernel">>, NewLibrary#instrumentation_library.name), ?assertEqual(<<"fake-version">>, NewLibrary#instrumentation_library.version), + + %% tracer registered on startup for a particular application is the same + {_, #tracer{instrumentation_library=Library1}} = opentelemetry:get_application_tracer(kernel), + ?assertEqual(<<"kernel">>, Library1#instrumentation_library.name), + ?assertNotEqual(<<"fake-version">>, Library1#instrumentation_library.version), + ok. propagator_configuration(_Config) -> diff --git a/apps/opentelemetry_api/README.md b/apps/opentelemetry_api/README.md index 9f65329d2..310735639 100644 --- a/apps/opentelemetry_api/README.md +++ b/apps/opentelemetry_api/README.md @@ -30,64 +30,12 @@ def deps do end ``` -### Registering and Using Tracers Directly - -If it is a runnable application then this registration should happen in `start/2`, example below is adding `Tracer` registration to the Postgres library [pgo](https://github.com/erleans/pgo): - -``` erlang -start(_StartType, _StartArgs) -> - _ = opentelemetry:register_application_tracer(pgo), -... -``` - -Or for an Elixir Application named `MyApp`: - -``` elixir -defmodule MyApp do - use Application - - def start(_type, _args) do - _ = OpenTelemetry.register_application_tracer(:my_app) - ... - end -end -``` - -Then when the spans are started and finished in the application's code the `Tracer` is fetched with `get_tracer/1` and passed to `with_span/3` or `start_span/3`: - -``` erlang -Tracer = opentelemetry:get_tracer(pgo), -otel_tracer:with_span(Tracer, <<"pgo:query/3">>, fun() -> ... end). -``` - -A `Tracer` variable can be passed through your Application's calls so `get_tracer` only has to be called once, it is safe to store it in the state of a `gen_server` and to pass across process boundaries. - -If the application does not have a `start/2` there may be another function that is always called before the library would create any spans. For example, the [Elli](https://github.com/elli-lib/elli) middleware for OpenTelemetry instrumentation registers the `Tracer` during Elli startup: - -``` erlang -handle_event(elli_startup, _Args, _Config) -> - _ = opentelemetry:register_application_tracer(opentelemetry_elli), - ok; -``` - -When there is no startup of any kind to hook into in the library itself it should export a function `register_application_tracer/0` to be used by any application that depends on it to do the registration: - -``` erlang --module(mylib). - --export([register_tracer/0]). - -register_tracer() -> - _ = opentelemetry:register_application_tracer(mylib), - ok. -``` - -Not registering does not cause any issues or crashes, OpenTelemetry simply will fallback to the default `Tracer` if `get_tracer/1` is called with a name that is not registered. - - ### Helper Macros for Application Tracers -When `register_application_tracer/1` is used to register a Tracer there are both Erlang and Elixir macros that make use of the current module's name to lookup the Tracer for you and can be used for Trace and Span operations: +There are both Erlang and Elixir macros that make use of the current module's +name to lookup a Named Tracer -- a Named Tracer is created for each Application +loaded in the system at start time -- for you and can be used for Trace and Span +operations: ``` erlang -include_lib("opentelemetry_api/include/otel_tracer.hrl"). diff --git a/apps/opentelemetry_api/include/opentelemetry.hrl b/apps/opentelemetry_api/include/opentelemetry.hrl index cd51a2ade..37132808a 100644 --- a/apps/opentelemetry_api/include/opentelemetry.hrl +++ b/apps/opentelemetry_api/include/opentelemetry.hrl @@ -34,6 +34,11 @@ -define(OTEL_STATUS_OK, ok). -define(OTEL_STATUS_ERROR, error). +%% Holds information about the instrumentation library specified when +%% getting a Tracer from the TracerProvider. +-record(instrumentation_library, {name :: unicode:unicode_binary() | undefined, + version :: unicode:unicode_binary() | undefined}). + -record(span_ctx, { %% 128 bit int trace id trace_id :: opentelemetry:trace_id(), diff --git a/apps/opentelemetry_api/include/otel_tracer.hrl b/apps/opentelemetry_api/include/otel_tracer.hrl index 8a4241fc6..09a11de1c 100644 --- a/apps/opentelemetry_api/include/otel_tracer.hrl +++ b/apps/opentelemetry_api/include/otel_tracer.hrl @@ -1,7 +1,7 @@ %% macros for tracing %% register a tracer for an application with opentelemetry:register_application_tracer(AppName) --define(current_tracer, opentelemetry:get_tracer(?MODULE)). +-define(current_tracer, opentelemetry:get_application_tracer(?MODULE)). -define(current_span_ctx, otel_tracer:current_span_ctx()). -define(start_span(SpanName), diff --git a/apps/opentelemetry_api/lib/open_telemetry.ex b/apps/opentelemetry_api/lib/open_telemetry.ex index b11b74ad1..93b804ee5 100644 --- a/apps/opentelemetry_api/lib/open_telemetry.ex +++ b/apps/opentelemetry_api/lib/open_telemetry.ex @@ -13,8 +13,6 @@ defmodule OpenTelemetry do require OpenTelemetry.Tracer require OpenTelemetry.Span - OpenTelemetry.register_application_tracer(:this_otp_app) - Tracer.start_span("some-span") ... event = "ecto.query" diff --git a/apps/opentelemetry_api/lib/open_telemetry/tracer.ex b/apps/opentelemetry_api/lib/open_telemetry/tracer.ex index b70a4cbd0..5ab61438a 100644 --- a/apps/opentelemetry_api/lib/open_telemetry/tracer.ex +++ b/apps/opentelemetry_api/lib/open_telemetry/tracer.ex @@ -6,9 +6,8 @@ defmodule OpenTelemetry.Tracer do a different Span to be the current Span by passing the Span's context, end a Span or run a code block within the context of a newly started span that is ended when the code block completes. - The macros use the Tracer registered to the Application the module using the macro is included in, - assuming `OpenTelemetry.register_application_tracer/1` has been called for the Application. If - not then the default Tracer is used. + The macros `start_span` and `with_span` use the Tracer registered to the Application the module + is included in. These Tracers are created at boot time for each loaded Application. require OpenTelemetry.Tracer diff --git a/apps/opentelemetry_api/src/opentelemetry.erl b/apps/opentelemetry_api/src/opentelemetry.erl index ebf5fdc43..47363b9ab 100644 --- a/apps/opentelemetry_api/src/opentelemetry.erl +++ b/apps/opentelemetry_api/src/opentelemetry.erl @@ -29,16 +29,18 @@ -module(opentelemetry). -export([set_default_tracer/1, - set_tracer/2, register_tracer/2, - register_application_tracer/1, + register_application_tracers/1, get_tracer/0, get_tracer/1, + set_tracer/2, + get_application_tracer/1, set_text_map_propagator/1, set_text_map_extractor/1, get_text_map_extractor/0, set_text_map_injector/1, get_text_map_injector/0, + instrumentation_library/2, timestamp/0, timestamp_to_nano/1, convert_timestamp/2, @@ -51,7 +53,6 @@ events/1, status/2, verify_and_set_term/3, - verify_and_set_term/4, generate_trace_id/0, generate_span_id/0]). @@ -84,6 +85,9 @@ text_map/0]). -type tracer() :: {module(), term()}. +%% -type named_tracer_map() :: #{atom() => tracer()}. + +-type instrumentation_library() :: #instrumentation_library{}. -type trace_id() :: non_neg_integer(). -type span_id() :: non_neg_integer(). @@ -129,13 +133,19 @@ -type text_map() :: [{unicode:unicode_binary(), unicode:unicode_binary()}]. +-define(TRACER_KEY(Name), {?MODULE, tracer, Name}). +-define(DEFAULT_TRACER_KEY, ?TRACER_KEY('$__default_tracer')). +-define(APPLICATION_TRACER_KEY, {?MODULE, otel_application_tracer_key}). +-define(TEXT_MAP_EXTRACTOR_KEY, {?MODULE, text_map_extractor}). +-define(TEXT_MAP_INJECTOR_KEY, {?MODULE, text_map_injector}). + -spec set_default_tracer(tracer()) -> boolean(). set_default_tracer(Tracer) -> - verify_and_set_term(Tracer, default_tracer, otel_tracer). + verify_and_set_term(Tracer, ?DEFAULT_TRACER_KEY, otel_tracer). -spec set_tracer(atom(), tracer()) -> boolean(). set_tracer(Name, Tracer) -> - verify_and_set_term(Tracer, Name, otel_tracer). + verify_and_set_term(Tracer, ?TRACER_KEY(Name), otel_tracer). -spec register_tracer(atom(), string() | binary()) -> boolean(). register_tracer(Name, Vsn) when is_atom(Name) and is_binary(Vsn) -> @@ -143,17 +153,40 @@ register_tracer(Name, Vsn) when is_atom(Name) and is_binary(Vsn) -> register_tracer(Name, Vsn) when is_atom(Name) and is_list(Vsn) -> otel_tracer_provider:register_tracer(Name, list_to_binary(Vsn)). --spec register_application_tracer(atom()) -> boolean(). -register_application_tracer(Name) -> - otel_tracer_provider:register_application_tracer(Name). +-spec register_application_tracers([atom()]) -> ok. +register_application_tracers(Applications) -> + TracerMap = lists:foldl(fun(Application, Acc) -> + maps:merge(Acc, application_tracer(Application)) + end, #{}, Applications), + persistent_term:put(?APPLICATION_TRACER_KEY, TracerMap). + +%% creates a map of modules to tracers for a particular application +application_tracer({Name, _Description, Version}) -> + try + {ok, Modules} = application:get_key(Name, modules), + InstrumentationLibrary = instrumentation_library(Name, Version), + TracerTuple = otel_tracer_provider:get_tracer(InstrumentationLibrary), + lists:foldl(fun(M, Acc) -> + Acc#{M => TracerTuple} + end, #{}, Modules) + catch exit:{noproc, _} -> + %% ignore because noproc here means no provider + %% likely since the SDK has been included and started + #{} + end. -spec get_tracer() -> tracer(). get_tracer() -> - persistent_term:get({?MODULE, default_tracer}, {otel_tracer_noop, []}). + persistent_term:get(?DEFAULT_TRACER_KEY, {otel_tracer_noop, []}). -spec get_tracer(atom()) -> tracer(). get_tracer(Name) -> - persistent_term:get({?MODULE, Name}, get_tracer()). + persistent_term:get(?TRACER_KEY(Name), get_tracer()). + +-spec get_application_tracer(atom()) -> tracer(). +get_application_tracer(ModuleName) -> + Map = persistent_term:get(?APPLICATION_TRACER_KEY, #{}), + maps:get(ModuleName, Map, get_tracer()). %% setting the propagator is the same as setting the same injector and extractor set_text_map_propagator(Propagator) -> @@ -161,16 +194,16 @@ set_text_map_propagator(Propagator) -> set_text_map_extractor(Propagator). set_text_map_extractor(Propagator) -> - persistent_term:put({?MODULE, text_map_extractor}, Propagator). + persistent_term:put(?TEXT_MAP_EXTRACTOR_KEY, Propagator). set_text_map_injector(Propagator) -> - persistent_term:put({?MODULE, text_map_injector}, Propagator). + persistent_term:put(?TEXT_MAP_INJECTOR_KEY, Propagator). get_text_map_extractor() -> - persistent_term:get({?MODULE, text_map_extractor}, otel_propagator_text_map_noop). + persistent_term:get(?TEXT_MAP_EXTRACTOR_KEY, otel_propagator_text_map_noop). get_text_map_injector() -> - persistent_term:get({?MODULE, text_map_injector}, otel_propagator_text_map_noop). + persistent_term:get(?TEXT_MAP_INJECTOR_KEY, otel_propagator_text_map_noop). %% @doc A monotonically increasing time provided by the Erlang runtime system in the native time unit. %% This value is the most accurate and precise timestamp available from the Erlang runtime and @@ -341,12 +374,9 @@ uniform(X) -> -spec verify_and_set_term(module() | {module(), term()}, term(), atom()) -> boolean(). verify_and_set_term(Module, TermKey, Behaviour) -> - verify_and_set_term(?MODULE, Module, TermKey, Behaviour). - -verify_and_set_term(AppKey, Module, TermKey, Behaviour) -> case verify_module_exists(Module) of true -> - persistent_term:put({AppKey, TermKey}, Module), + persistent_term:put(TermKey, Module), true; false -> ?LOG_WARNING("Module ~p does not exist. " @@ -376,3 +406,27 @@ link_or_false(TraceId, SpanId, Attributes, TraceState) -> _ -> false end. + +instrumentation_library(Name, Vsn) -> + #instrumentation_library{name=name_to_binary(Name), + version=vsn_to_binary(Vsn)}. + +%% Vsn can't be an atom or anything but a list or binary +%% so return `undefined' if it isn't a list or binary. +vsn_to_binary(Vsn) when is_list(Vsn) -> + list_to_binary(Vsn); +vsn_to_binary(Vsn) when is_binary(Vsn) -> + Vsn; +vsn_to_binary(_) -> + undefined. + +%% name can be atom, list or binary. But atom `undefined' +%% must stay as `undefined' atom. +name_to_binary(undefined)-> + undefined; +name_to_binary(T) when is_atom(T) -> + atom_to_binary(T, utf8); +name_to_binary(T) when is_list(T) -> + list_to_binary(T); +name_to_binary(T) when is_binary(T) -> + T. diff --git a/apps/opentelemetry_api/src/otel_tracer_provider.erl b/apps/opentelemetry_api/src/otel_tracer_provider.erl index 110380943..b362b34d6 100644 --- a/apps/opentelemetry_api/src/otel_tracer_provider.erl +++ b/apps/opentelemetry_api/src/otel_tracer_provider.erl @@ -21,7 +21,7 @@ -export([start_link/2, resource/0, - register_application_tracer/1, + get_tracer/1, register_tracer/2]). -export([init/1, @@ -33,6 +33,7 @@ -callback init(term()) -> {ok, cb_state()}. -callback register_tracer(atom(), binary(), cb_state()) -> boolean(). +-callback get_tracer(opentelemetry:instrumentation_library(), cb_state()) -> opentelemetry:tracer() | undefined. -callback resource(cb_state()) -> term() | undefined. -record(state, {callback :: module(), @@ -59,15 +60,13 @@ register_tracer(Name, Vsn) -> false end. --spec register_application_tracer(atom()) -> boolean(). -register_application_tracer(Name) -> +-spec get_tracer(opentelemetry:instrumentation_library()) -> opentelemetry:tracer() | undefined. +get_tracer(InstrumentationLibrary) -> try - {ok, Vsn} = application:get_key(Name, vsn), - {ok, Modules} = application:get_key(Name, modules), - gen_server:call(?MODULE, {register_tracer, Name, Vsn, Modules}) + gen_server:call(?MODULE, {get_tracer, InstrumentationLibrary}) catch exit:{noproc, _} -> - %% ignore register_tracer because no SDK has been included and started - false + %% ignore because likely no SDK has been included and started + {otel_tracer_noop, []} end. init([ProviderModule, Opts]) -> @@ -79,10 +78,10 @@ init([ProviderModule, Opts]) -> Other end. -handle_call({register_tracer, Name, Vsn, Modules}, _From, State=#state{callback=Cb, - cb_state=CbState}) -> - _ = Cb:register_tracer(Name, Vsn, Modules, CbState), - {reply, true, State}; +handle_call({get_tracer, InstrumentationLibrary}, _From, State=#state{callback=Cb, + cb_state=CbState}) -> + Tracer = Cb:get_tracer(InstrumentationLibrary, CbState), + {reply, Tracer, State}; handle_call({register_tracer, Name, Vsn}, _From, State=#state{callback=Cb, cb_state=CbState}) -> _ = Cb:register_tracer(Name, Vsn, CbState), diff --git a/apps/opentelemetry_api_experimental/lib/opentelemetry_api_experimental/meter.ex b/apps/opentelemetry_api_experimental/lib/opentelemetry_api_experimental/meter.ex index 28a663438..a8d52ca2f 100644 --- a/apps/opentelemetry_api_experimental/lib/opentelemetry_api_experimental/meter.ex +++ b/apps/opentelemetry_api_experimental/lib/opentelemetry_api_experimental/meter.ex @@ -5,8 +5,6 @@ defmodule OpenTelemetry.Meter do require OpenTelemetry.Counter require OpenTelemetry.Meter - OpenTelemetry.register_application_meter(Your.Application) - OpenTelemetry.Meter.new_instruments([OpenTelemetry.ValueRecorder.instrument("some.latency"), OpenTelemetry.Counter.instrument("some.counter")]) diff --git a/apps/opentelemetry_api_experimental/src/opentelemetry_experimental.erl b/apps/opentelemetry_api_experimental/src/opentelemetry_experimental.erl index 9e7afd0d4..5f9c7063d 100644 --- a/apps/opentelemetry_api_experimental/src/opentelemetry_experimental.erl +++ b/apps/opentelemetry_api_experimental/src/opentelemetry_experimental.erl @@ -30,13 +30,15 @@ -type meter() :: {module(), term()}. +-define(METER_KEY(Name), {?MODULE, meter, Name}). + -spec set_default_meter(meter()) -> boolean(). set_default_meter(Meter) -> - opentelemetry:verify_and_set_term(?MODULE, Meter, default_meter, otel_meter). + opentelemetry:verify_and_set_term(Meter, ?METER_KEY(default_meter), otel_meter). -spec set_meter(atom(), meter()) -> boolean(). set_meter(Name, Meter) -> - opentelemetry:verify_and_set_term(?MODULE, Meter, Name, otel_meter). + opentelemetry:verify_and_set_term(Meter, ?METER_KEY(Name), otel_meter). -spec register_meter(atom(), string()) -> boolean(). register_meter(Name, Vsn) -> @@ -48,8 +50,8 @@ register_application_meter(Name) -> -spec get_meter() -> meter(). get_meter() -> - persistent_term:get({?MODULE, default_meter}, {otel_meter_noop, []}). + persistent_term:get(?METER_KEY(default_meter), {otel_meter_noop, []}). -spec get_meter(atom()) -> meter(). get_meter(Name) -> - persistent_term:get({?MODULE, Name}, get_meter()). + persistent_term:get(?METER_KEY(Name), get_meter()). diff --git a/apps/opentelemetry_experimental/src/otel_meter_server.erl b/apps/opentelemetry_experimental/src/otel_meter_server.erl index fc60209eb..4628a6334 100644 --- a/apps/opentelemetry_experimental/src/otel_meter_server.erl +++ b/apps/opentelemetry_experimental/src/otel_meter_server.erl @@ -45,7 +45,7 @@ register_meter(Name, Vsn, #state{meter=Meter, true -> opentelemetry_experimental:set_meter(Name, {otel_meter_noop, []}); false -> - InstrumentationLibrary = otel_utils:instrumentation_library(Name, Vsn), + InstrumentationLibrary = opentelemetry:instrumentation_library(Name, Vsn), opentelemetry_experimental:set_meter(Name, {Meter#meter.module, Meter#meter{instrumentation_library=InstrumentationLibrary}}) end.