Current section
Files
Jump to
Current section
Files
src/ot_tracer_server.erl
%%%------------------------------------------------------------------------
%% Copyright 2019, 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(ot_tracer_server).
-behaviour(ot_tracer_provider).
-export([init/1,
register_tracer/4,
register_tracer/3,
resource/1,
code_change/1]).
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("ot_tracer.hrl").
-include("ot_span.hrl").
-type telemetry_library() :: #telemetry_library{}.
-type instrumentation_library() :: #instrumentation_library{}.
-export_type([telemetry_library/0,
instrumentation_library/0]).
-record(state,
{
%% the tracer configuration shared between all named
%% tracers created by this provider
shared_tracer :: tracer(),
processors :: [module()],
sampler :: ot_sampler:t(),
resource :: ot_resource:t(),
%% list of tracer names to return noop tracers for
deny_list :: [atom() | {atom(), string()}],
%% data about this SDK implementation itself
%% the name, language (erlang) and version
telemetry_library :: telemetry_library()
}).
init(Opts) ->
{Sampler, SamplerOpts} = proplists:get_value(sampler, Opts, {always_on, #{}}),
SamplerFun = ot_sampler:setup(Sampler, SamplerOpts),
Processors = proplists:get_value(processors, Opts, []),
DenyList = proplists:get_value(deny_list, Opts, []),
OSVarResource = ot_resource_env_var:get_resource(),
AppEnvResource = ot_resource_app_env:get_resource(),
%% merge the resource attributes with the OS env taking precedence
Resource = ot_resource:merge(OSVarResource, AppEnvResource),
{ok, LibraryVsn} = application:get_key(opentelemetry, vsn),
LibraryName = <<"opentelemetry">>,
LibraryLanguage = <<"erlang">>,
TelemetryLibrary = #telemetry_library{name=LibraryName,
language=LibraryLanguage,
version=list_to_binary(LibraryVsn)},
Tracer = #tracer{module=ot_tracer_default,
sampler=SamplerFun,
on_start_processors=on_start(Processors),
on_end_processors=on_end(Processors),
resource=Resource,
telemetry_library=TelemetryLibrary,
span_module=ot_span_ets,
ctx_module=ot_ctx_pdict},
opentelemetry:set_default_tracer({ot_tracer_default, Tracer}),
{ok, #state{shared_tracer=Tracer,
resource=Resource,
sampler=SamplerFun,
telemetry_library=TelemetryLibrary,
deny_list=DenyList,
processors=Processors}}.
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, {ot_tracer_noop, []});
false ->
InstrumentationLibrary = ot_utils:instrumentation_library(Name, Vsn),
TracerTuple = {Tracer#tracer.module,
Tracer#tracer{instrumentation_library=InstrumentationLibrary}},
[opentelemetry:set_tracer(M, TracerTuple) || M <- Modules]
end.
register_tracer(Name, Vsn, #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, {ot_tracer_noop, []});
false ->
InstrumentationLibrary = ot_utils:instrumentation_library(Name, Vsn),
TracerTuple = {Tracer#tracer.module,
Tracer#tracer{instrumentation_library=InstrumentationLibrary}},
opentelemetry:set_tracer(Name, TracerTuple)
end.
%% the application vsn has likely changed during a code change
%% so update the shared tracer data here
code_change(State=#state{shared_tracer=Tracer=#tracer{telemetry_library=TelemetryLibrary}}) ->
{ok, LibraryVsn} = application:get_key(opentelemetry, vsn),
NewTelemetryLibrary = TelemetryLibrary#telemetry_library{version=list_to_binary(LibraryVsn)},
NewTracer = Tracer#tracer{telemetry_library=NewTelemetryLibrary},
{ok, State#state{shared_tracer=NewTracer}}.
%%
on_start(Processors) ->
fun(Span) -> [P:on_start(Span, Config) || {P, Config} <- Processors] end.
on_end(Processors) ->
fun(Span) -> [P:on_end(Span, Config) || {P, Config} <- Processors] end.