Current section

Files

Jump to
opentelemetry src otel_sampler_parent_based.erl
Raw

src/otel_sampler_parent_based.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 An {@link otel_sampler} that makes the decision based on the parent.
%%
%% This sampler decides with the following possibilities:
%% <ol>
%% <li>a remote parent that is sampled (by default `always_on');</li>
%% <li>a remote parent that is not sampled (by default `always_off');</li>
%% <li>a local parent that is sampled (by default `always_on');</li>
%% <li>a local parent that is not sampled (by default `always_off');</li>
%% <li>no parent (by default `always_on').</li>
%% </ol>
%%
%% For each of these cases a different sampler can be configured.
%% For options, see {@link opts()}.
%%
%% This is one of the
%% <a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/#built-in-samplers">built-in
%% samplers</a> provided by the OpenTelemetry SDK.
%% @end
%%%-------------------------------------------------------------------------
-module(otel_sampler_parent_based).
-behavior(otel_sampler).
-export([description/1, setup/1, should_sample/7]).
-export_type([opts/0]).
-include_lib("kernel/include/logger.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-type opts() :: #{
remote_parent_sampled => otel_sampler:sampler_spec(),
remote_parent_not_sampled => otel_sampler:sampler_spec(),
local_parent_sampled => otel_sampler:sampler_spec(),
local_parent_not_sampled => otel_sampler:sampler_spec(),
root => otel_sampler:sampler_spec()
}.
%% Options to configure this sampler.
%% @private
setup(Opts = #{root := RootSpec}) ->
RemoteParentSampledSampler = sampler_for_spec(remote_parent_sampled, Opts, always_on),
RemoteParentNotSampledSampler = sampler_for_spec(remote_parent_not_sampled, Opts, always_off),
LocalParentSampledSampler = sampler_for_spec(local_parent_sampled, Opts, always_on),
LocalParentNotSampledSampler = sampler_for_spec(local_parent_not_sampled, Opts, always_off),
RootSampler = otel_sampler:new(RootSpec),
#{
root => RootSampler,
remote_parent_sampled => RemoteParentSampledSampler,
remote_parent_not_sampled => RemoteParentNotSampledSampler,
local_parent_sampled => LocalParentSampledSampler,
local_parent_not_sampled => LocalParentNotSampledSampler
};
setup(Opts) ->
?LOG_INFO("No sampler spec found for parent_based 'root' option. The 'always_on' sampler will be used for root spans."),
setup(Opts#{root => always_on}).
sampler_for_spec(Key, Opts, DefaultModule) ->
Spec = maps:get(Key, Opts, DefaultModule),
otel_sampler:new(Spec).
%% @private
description(#{
root := RootSampler,
remote_parent_sampled := RemoteParentSampler,
remote_parent_not_sampled := RemoteParentNotSampler,
local_parent_sampled := LocalParentSampler,
local_parent_not_sampled := LocalParentNotSampler
}) ->
<<"ParentBased{root:", (otel_sampler:description(RootSampler))/binary, ",remoteParentSampled:",
(otel_sampler:description(RemoteParentSampler))/binary, ",remoteParentNotSampled:",
(otel_sampler:description(RemoteParentNotSampler))/binary, ",localParentSampled:",
(otel_sampler:description(LocalParentSampler))/binary, ",localParentNotSampled:",
(otel_sampler:description(LocalParentNotSampler))/binary, "}">>.
%% @private
should_sample(Ctx, TraceId, Links, SpanName, SpanKind, Attributes, Config) ->
ParentSpanCtx = otel_tracer:current_span_ctx(Ctx),
SamplerKey = parent_based_sampler(ParentSpanCtx),
{Sampler, _Description, SamplerOpts} = maps:get(SamplerKey, Config),
Sampler:should_sample(Ctx, TraceId, Links, SpanName, SpanKind, Attributes, SamplerOpts).
%% remote parent sampled
parent_based_sampler(#span_ctx{trace_flags = TraceFlags, is_remote = true}) when
?IS_SAMPLED(TraceFlags)
->
remote_parent_sampled;
%% remote parent not sampled
parent_based_sampler(#span_ctx{is_remote = true}) ->
remote_parent_not_sampled;
%% local parent sampled
parent_based_sampler(#span_ctx{trace_flags = TraceFlags}) when
?IS_SAMPLED(TraceFlags)
->
local_parent_sampled;
%% local parent not sampled
parent_based_sampler(#span_ctx{}) ->
local_parent_not_sampled;
%% root
parent_based_sampler(_SpanCtx) ->
root.