%%%------------------------------------------------------------------------ %% 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 Behaviour for defining samplers. %% %% A sampler should provide a function run on each started span that returns whether to %% record and propagate, only record, or not record the span. %% %% For more information on the concept of Sampling, see %% Sampling in the OpenTelemetry %% documentation or the %% Sampling spec. %% For examples of configuring samplers or implementing your own sampler, %% see the OpenTelemetry %% Erlang documentation. %% %%

Configuration

%% %% To configure sampling for the `opentelemetry' application, see %% the documentation. %% @end %%%------------------------------------------------------------------------- -module(otel_sampler). -export([description/1, new/1, should_sample/7]). -export_type([description/0, sampler_spec/0, sampler_config/0, sampler_opts/0, sampling_decision/0, sampling_result/0, t/0]). -callback setup(sampler_opts()) -> sampler_config(). %% Called when a sampler is created to set up the sampler. %% Should return the sampler configuration that is then passed to other callbacks. -callback description(sampler_config()) -> description(). %% Should return the description of the sampler. -callback should_sample( otel_ctx:t(), opentelemetry:trace_id(), otel_links:t(), opentelemetry:span_name(), opentelemetry:span_kind(), opentelemetry:attributes_map(), sampler_config() ) -> sampling_result(). %% Main callback that determines whether a span should be sampled.\ -include("otel_sampler.hrl"). -type description() :: unicode:unicode_binary(). %% The description of the sampler. -type sampler_config() :: term(). %% Any term used to configured a given sampler. -type sampler_opts() :: term(). %% Any options passed to a sampler. -type builtin_sampler() :: always_on | always_off | {trace_id_ratio_based, float()} | {parent_based, #{ remote_parent_sampled => sampler_spec(), remote_parent_not_sampled => sampler_spec(), local_parent_sampled => sampler_spec(), local_parent_not_sampled => sampler_spec(), root => sampler_spec() }}. %% A built-in sampler. -type sampler_spec() :: builtin_sampler() | {module(), sampler_opts()}. %% Specification to create a sampler. -type sampling_decision() :: ?DROP | ?RECORD_ONLY | ?RECORD_AND_SAMPLE. %% The decision that a sampler can make on a given span. -type sampling_result() :: { sampling_decision(), opentelemetry:attributes_map(), opentelemetry:tracestate() | otel_tracestate:members() }. %% The result of a sampling decision. -opaque t() :: {module(), description(), sampler_opts()}. %% A sampler. %% @doc Returns a sampler based on the given specification. -spec new(SamplerSpec :: sampler_spec()) -> t(). new(always_on) -> new({otel_sampler_always_on, #{}}); new(always_off) -> new({otel_sampler_always_off, #{}}); new({trace_id_ratio_based, Opts}) -> new({otel_sampler_trace_id_ratio_based, Opts}); new({parent_based, Opts}) -> new({otel_sampler_parent_based, Opts}); new({Sampler, Opts}) -> Config = Sampler:setup(Opts), {Sampler, Sampler:description(Config), Config}. %% @private -spec should_sample( t(), otel_ctx:t(), opentelemetry:trace_id(), otel_links:t(), opentelemetry:span_name(), opentelemetry:span_kind(), opentelemetry:attributes_map() ) -> sampling_result(). should_sample({Sampler, _, Config}, Ctx, TraceId, Links, SpanName, Kind, Attributes) -> case Sampler:should_sample(Ctx, TraceId, Links, SpanName, Kind, Attributes, Config) of %% to support backwards compatibility with when `tracestate' was just a list, not %% a record, we accept a list and create a new `tracestate' {Decision, Attributes, Tracestate} when is_list(Tracestate) -> {Decision, Attributes, otel_tracestate:new(Tracestate)}; Result -> Result end. %% @doc Returns the description of the given sampler. -spec description(t()) -> description(). description(_Sampler = {_, Description, _}) -> Description.