サンプリング

サンプリングは、システムによって生成されるトレースの量を制限するプロセスです。 Erlang SDK はいくつかのヘッドサンプラーを提供しています。

デフォルトの動作

デフォルトでは、すべてのスパンがサンプリングされ、トレースの 100% がサンプリングされます。 データ量を管理する必要がない場合は、サンプラーを設定する必要はありません。

ParentBasedSampler

サンプリングにおいて、ParentBasedSamplerヘッドサンプリングで最もよく使用されます。 スパンの親のサンプリング決定、または親が存在しないという事実を使用して、どの二次サンプラーを使用するかを判断します。

サンプラーは環境変数 OTEL_TRACES_SAMPLEROTEL_TRACES_SAMPLER_ARG で設定できます。 また、アプリケーション設定を使用すると、スパンの親の5つの潜在的な状態それぞれを設定できます。

  • root - 親なし
  • remote_parent_sampled - 親はサンプリングされたリモートスパン
  • remote_parent_not_sampled - 親はサンプリングされていないリモートスパン
  • local_parent_sampled - 親はサンプリングされたローカルスパン
  • local_parent_not_sampled - 親はサンプリングされていないローカルスパン

TraceIdRatioBasedSampler

ParentBasedSampler 内で最もよく使われるのは TraceIdRatioBasedSampler です。 パラメーターとして渡したパーセンテージのトレースを決定論的にサンプリングします。

環境変数

環境変数で TraceIdRatioBasedSampler を設定できます。

export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"

これにより、トレースの 10% のみが作成されるようにスパンをサンプリングするよう SDK に指示します。

アプリケーション設定

アプリケーション設定の例です。 ルートサンプラーでトレースの 10% をサンプリングし、その他のケースでは親の決定を使用します。

%% config/sys.config.src
{opentelemetry, {sampler, {parent_based, #{root => {trace_id_ratio_based, 0.10},
                                          remote_parent_sampled => always_on,
                                          remote_parent_not_sampled => always_off,
                                          local_parent_sampled => always_on,
                                          local_parent_not_sampled => always_off}}}}
# config/runtime.exs
config :opentelemetry, sampler: {:parent_based, %{root: {:trace_id_ratio_based, 0.10},
                                                  remote_parent_sampled: :always_on,
                                                  remote_parent_not_sampled: :always_off,
                                                  local_parent_sampled: :always_on,
                                                  local_parent_not_sampled: :always_off}}

AlwaysOn と AlwaysOff サンプラー

その他の2つの組み込みサンプラーは AlwaysOnSamplerAlwaysOffSampler です。

環境変数

環境変数 OTEL_TRACES_SAMPLER を使って、ParentBasedSamplerAlwaysOnSampler または AlwaysOffSampler を使用するように設定できます。

export OTEL_TRACES_SAMPLER="parentbased_always_on"

AlwaysOffSampler の場合は以下のとおりです。

export OTEL_TRACES_SAMPLER="parentbased_always_off"

アプリケーション設定

アプリケーション設定の例です。 ルートサンプラーで常にサンプリングし、その他のケースでは親の決定を使用します。

%% config/sys.config.src
{opentelemetry, {sampler, {parent_based, #{root => always_on,
                                          remote_parent_sampled => always_on,
                                          remote_parent_not_sampled => always_off,
                                          local_parent_sampled => always_on,
                                          local_parent_not_sampled => always_off}}}}
# config/runtime.exs
config :opentelemetry, sampler: {:parent_based, %{root: :always_on,
                                                  remote_parent_sampled: :always_on,
                                                  remote_parent_not_sampled: :always_off,
                                                  local_parent_sampled: :always_on,
                                                  local_parent_not_sampled: :always_off}}

カスタムサンプラー

カスタムサンプラーは otel_sampler ビヘイビアを実装することで作成できます。 このサンプラーの例を示します。

-module(attribute_sampler).

-behavior(otel_sampler).

-export([description/1,
         setup/1,
         should_sample/7]).

-include("otel_sampler.hrl").

setup(Attributes) when is_map(Attributes) ->
    Attributes;
setup(_) ->
    #{}.

description(_) ->
    <<"AttributeSampler">>.

should_sample(_Ctx, _TraceId, _Links, _SpanName, _SpanKind, Attributes, ConfigAttributes) ->
    AttributesSet = sets:from_list(maps:to_list(Attributes)),
    ConfigSet = sets:from_list(maps:to_list(ConfigAttributes)),
    case sets:is_disjoint(AttributesSet, ConfigSet) of
        true -> {?RECORD_AND_SAMPLE, [], []};
        _ -> {?DROP, [], []}
end.
defmodule AttributesSampler do
  def setup(attributes) when is_map(attributes) do
    attributes
  end

  def setup(_) do
    %{}
  end

  def description(_) do
    "ExampleSampler"
  end

  def should_sample(_ctx, _trace_id, _links, _span_name, _span_kind, attributes, config_attributes) do
    no_match =
      Enum.into(attributes, %MapSet{})
      |> MapSet.disjoint?(Enum.into(config_attributes, %MapSet{}))

    if no_match, do: {:record_and_sample, [], []}, else: {:drop, [], []}
  end
end

このサンプラーは、サンプラーの設定として渡された属性と一致する属性を持たないスパンをサンプリングします。

リクエストされた URL が /healthcheck であることを指定する属性を持つスパンをサンプリングしない設定の例です。

{opentelemetry, {sampler, {attributes_sampler, #{'http.target' => <<"/healthcheck">>}}}}
config :opentelemetry, sampler: {AttributesSampler, %{"http.target": "/healthcheck"}}