Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace parent sampler with parent_or_else #81

Merged
merged 3 commits into from
Jul 19, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/ot_sampler.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@

-define(NOT_RECORD, not_record).
-define(RECORD, record).
-define(RECORD_AND_PROPAGATE, record_and_propagate).
-define(RECORD_AND_SAMPLED, record_and_sampled).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the mix of present and past tense is intended there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, yes. In the spec, I don't know :).

33 changes: 20 additions & 13 deletions src/ot_sampler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@
-export([setup/2,
always_on/7,
always_off/7,
always_parent/7,
parent_or_else/7,
probability/7]).

-include_lib("kernel/include/logger.hrl").
-include_lib("opentelemetry_api/include/opentelemetry.hrl").
-include("ot_sampler.hrl").
-include("ot_span.hrl").

-type sampling_decision() :: ?NOT_RECORD | ?RECORD | ?RECORD_AND_PROPAGATE.
-type sampling_decision() :: ?NOT_RECORD | ?RECORD | ?RECORD_AND_SAMPLED.
-type sampling_result() :: {sampling_decision(), opentelemetry:attributes()}.
-type sampler() :: {fun((opentelemetry:trace_id(),
opentelemetry:span_ctx() | undefined,
Expand All @@ -51,8 +52,12 @@ setup(always_on, _Opts) ->
{fun ?MODULE:always_on/7, []};
setup(always_off, _Opts) ->
{fun ?MODULE:always_off/7, []};
setup(always_parent, _Opts) ->
{fun ?MODULE:always_parent/7, []};
setup(parent_or_else, #{delegate_sampler := {DelegateSampler, DelegateOpts}})
when is_atom(DelegateSampler) ->
{fun ?MODULE:parent_or_else/7, setup(DelegateSampler, DelegateOpts)};
setup(parent_or_else, _Opts) ->
?LOG_INFO("no delegate_sampler opt found for sampler parent_or_else. always_on will be used for root spans"),
{fun ?MODULE:parent_or_else/7, setup(always_on, #{})};
setup(probability, Opts) ->
IdUpperBound =
case maps:get(probability, Opts, ?DEFAULT_PROBABILITY) of
Expand All @@ -72,15 +77,17 @@ setup(Sampler, Opts) ->
Sampler:setup(Opts).

always_on(_TraceId, _SpanCtx, _Links, _SpanName, _Kind, _Attributes, _Opts) ->
{?RECORD_AND_PROPAGATE, []}.
{?RECORD_AND_SAMPLED, []}.

always_off(_TraceId, _SpanCtx, _Links, _SpanName, _Kind, _Attributes, _Opts) ->
{?NOT_RECORD, []}.

always_parent(_, #span_ctx{trace_flags=TraceFlags}, _, _, _, _, _) when ?IS_SPAN_ENABLED(TraceFlags) ->
{?RECORD_AND_PROPAGATE, []};
always_parent(_, _, _, _, _, _, _) ->
{?NOT_RECORD, []}.
parent_or_else(_, #span_ctx{trace_flags=TraceFlags}, _, _, _, _, _) when ?IS_SPAN_ENABLED(TraceFlags) ->
{?RECORD_AND_SAMPLED, []};
parent_or_else(_, #span_ctx{trace_flags=_TraceFlags}, _, _, _, _, _) ->
{?NOT_RECORD, []};
parent_or_else(TraceId, SpanCtx, Links, SpanName, Kind, Attributes, {DelegateSampler, DelegateOpts}) ->
DelegateSampler(TraceId, SpanCtx, Links, SpanName, Kind, Attributes, DelegateOpts).

probability(TraceId, Parent, _, _, _, _, {IdUpperBound,
IgnoreParentFlag,
Expand All @@ -91,14 +98,14 @@ probability(_, #span_ctx{trace_flags=TraceFlags}, _, _, _, _, {_IdUpperBound,
_IgnoreParentFlag,
_OnlyRoot})
when ?IS_SPAN_ENABLED(TraceFlags) ->
{?RECORD_AND_PROPAGATE, []};
{?RECORD_AND_SAMPLED, []};
probability(TraceId, #span_ctx{is_remote=IsRemote}, _, _, _, _, {IdUpperBound,
_IgnoreParentFlag,
OnlyRoot}) ->
case OnlyRoot =:= false andalso IsRemote =:= true
andalso do_probability_sample(TraceId, IdUpperBound) of
?RECORD_AND_PROPAGATE ->
{?RECORD_AND_PROPAGATE, []};
?RECORD_AND_SAMPLED ->
{?RECORD_AND_SAMPLED, []};
_ ->
{?NOT_RECORD, []}
end.
Expand All @@ -107,7 +114,7 @@ do_probability_sample(TraceId, IdUpperBound) ->
Lower64Bits = TraceId band ?MAX_VALUE,
case erlang:abs(Lower64Bits) < IdUpperBound of
true ->
?RECORD_AND_PROPAGATE;
?RECORD_AND_SAMPLED;
false ->
?NOT_RECORD
end.
Expand Down
2 changes: 1 addition & 1 deletion src/ot_span_utils.erl
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,6 @@ sample({Sampler, Opts}, TraceId, Parent, Links, SpanName, Kind, Attributes) ->
{0, false, NewAttributes};
?RECORD ->
{0, true, NewAttributes};
?RECORD_AND_PROPAGATE ->
?RECORD_AND_SAMPLED ->
{1, true, NewAttributes}
end.
57 changes: 49 additions & 8 deletions test/ot_samplers_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
-include("ot_sampler.hrl").

all() ->
[probability_sampler].
[probability_sampler, parent_or_else].

init_per_suite(Config) ->
application:load(opentelemetry),
Expand Down Expand Up @@ -37,36 +37,36 @@ probability_sampler(_Config) ->
only_root_spans => false}),

%% checks the trace id is is under the upper bound
?assertMatch({?RECORD_AND_PROPAGATE, []},
?assertMatch({?RECORD_AND_SAMPLED, []},
Sampler(DoSample, undefined, [], SpanName, undefined, [], Opts)),

%% checks the trace id is is over the upper bound
?assertMatch({?NOT_RECORD, []},
Sampler(DoNotSample, undefined, [], SpanName, undefined, [], Opts)),

%% uses the value from the parent span context
?assertMatch({?RECORD_AND_PROPAGATE, []},
?assertMatch({?RECORD_AND_SAMPLED, []},
Sampler(DoNotSample, #span_ctx{trace_flags=1,
is_remote=true},
is_remote=true},
[], SpanName, undefined, [], Opts)),

%% since parent is not remote it uses the value from the parent span context
?assertMatch({?NOT_RECORD, []},
Sampler(DoSample, #span_ctx{trace_flags=0,
is_remote=false},
is_remote=false},
[], SpanName, undefined, [], Opts)),

%% since parent is remote it checks the trace id and it is under the upper bound
?assertMatch({?RECORD_AND_PROPAGATE, []},
?assertMatch({?RECORD_AND_SAMPLED, []},
Sampler(DoSample, #span_ctx{trace_flags=0,
is_remote=true},
is_remote=true},
[], SpanName, undefined, [], Opts)),

{Sampler1, Opts1} = ot_sampler:setup(probability, #{probability => Probability,
only_root_spans => false,
ignore_parent_flag => false}),

?assertMatch({?RECORD_AND_PROPAGATE, []},
?assertMatch({?RECORD_AND_SAMPLED, []},
Sampler1(DoSample, #span_ctx{trace_flags=0, is_remote=true},
[], SpanName, undefined, [], Opts1)),

Expand All @@ -79,3 +79,44 @@ probability_sampler(_Config) ->
[], SpanName, undefined, [], Opts3)),

ok.

parent_or_else(_Config) ->
SpanName = <<"span-prob-sampled">>,
Probability = 0.5,
DoSample = 120647249294066572380176333851662846319,
DoNotSample = 53020601517903903921384168845238205400,

{Sampler, Opts} = ot_sampler:setup(parent_or_else,
#{delegate_sampler => {probability, #{probability => Probability,
only_root_spans => false}}}),

%% with no parent it will run the probability sampler
?assertMatch({?RECORD_AND_SAMPLED, []},
Sampler(DoSample, undefined, [], SpanName, undefined, [], Opts)),
?assertMatch({?NOT_RECORD, []},
Sampler(DoNotSample, undefined, [], SpanName, undefined, [], Opts)),

%% with parent it will use the parents value
?assertMatch({?RECORD_AND_SAMPLED, []},
Sampler(DoNotSample, #span_ctx{trace_flags=1},
[], SpanName, undefined, [], Opts)),
?assertMatch({?NOT_RECORD, []},
Sampler(DoNotSample, #span_ctx{trace_flags=0},
[], SpanName, undefined, [], Opts)),

%% with no delegate_sampler in setup opts the default sampler always_on is used
{DefaultParentOrElse, Opts1} = ot_sampler:setup(parent_or_else, #{}),

?assertMatch({?RECORD_AND_SAMPLED, []},
DefaultParentOrElse(DoSample, undefined, [], SpanName, undefined, [], Opts1)),
?assertMatch({?RECORD_AND_SAMPLED, []},
DefaultParentOrElse(DoNotSample, undefined, [], SpanName, undefined, [], Opts1)),

?assertMatch({?RECORD_AND_SAMPLED, []},
DefaultParentOrElse(DoNotSample, #span_ctx{trace_flags=1},
[], SpanName, undefined, [], Opts1)),
?assertMatch({?NOT_RECORD, []},
DefaultParentOrElse(DoNotSample, #span_ctx{trace_flags=0},
[], SpanName, undefined, [], Opts1)),

ok.