# Sampling

LLMS index: [llms.txt](/llms.txt)

---

<!-- markdownlint-disable no-duplicate-heading -->

[Sampling](/docs/concepts/sampling/) is a process that restricts the amount of
traces that are generated by a system. The Erlang SDK offers several
[head samplers](/docs/concepts/sampling#head-sampling).

## Default behavior

By default, all spans are sampled, and thus, 100% of traces are sampled. If you
do not need to manage data volume, you do not need to configure a sampler.

## ParentBasedSampler

When sampling, the `ParentBasedSampler` is most often used for
[head sampling](/docs/concepts/sampling/#head-sampling). It uses the sampling
decision of the Span's parent, or the fact that there is no parent, to know
which secondary sampler to use.

The sampler can be configured with the environment variables
`OTEL_TRACES_SAMPLER` and `OTEL_TRACES_SAMPLER_ARG` or using the Application
configuration allows you to configure each of the 5 potential states of a Span's
parent:

- `root` - No parent
- `remote_parent_sampled` - Parent is from a remote Span that is sampled
- `remote_parent_not_sampled` - Parent is from a remote Span that is not sampled
- `local_parent_sampled` - Parent is from a local Span that is sampled
- `local_parent_not_sampled` - Parent is from a local Span that is not sampled

### TraceIdRatioBasedSampler

Within the `ParentBasedSampler` the most common is the
`TraceIdRatioBasedSampler`. It deterministically samples a percentage of traces
that you pass in as a parameter.

#### Environment Variables

You can configure the `TraceIdRatioBasedSampler` with environment variables:

```shell
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"
```

This tells the SDK to sample spans such that only 10% of Traces get created.

#### Application configuration

Example in the Application configuration with a root sampler for sampling 10% of
Traces and using the parent decision in the other cases:

   <ul class="nav nav-tabs" id="tabs-0" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-00-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-00" role="tab"
          data-td-tp-persist="erlang" aria-controls="tabs-00-00" aria-selected="true">
        Erlang
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-01" role="tab"
          data-td-tp-persist="elixir" aria-controls="tabs-00-01" aria-selected="false">
        Elixir
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-0-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-00-00" role="tabpanel" aria-labelled-by="tabs-00-00-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-erlang" data-lang="erlang"><span class="line"><span class="cl"><span class="c">%% config/sys.config.src
</span></span></span><span class="line"><span class="cl"><span class="p">{</span><span class="n">opentelemetry</span><span class="p">,</span> <span class="p">{</span><span class="n">sampler</span><span class="p">,</span> <span class="p">{</span><span class="n">parent_based</span><span class="p">,</span> <span class="p">#{</span><span class="n">root</span> <span class="o">=&gt;</span> <span class="p">{</span><span class="n">trace_id_ratio_based</span><span class="p">,</span> <span class="mi">0</span><span class="p">.</span><span class="mi">10</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">remote_parent_sampled</span> <span class="o">=&gt;</span> <span class="n">always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">remote_parent_not_sampled</span> <span class="o">=&gt;</span> <span class="n">always_off</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">local_parent_sampled</span> <span class="o">=&gt;</span> <span class="n">always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">local_parent_not_sampled</span> <span class="o">=&gt;</span> <span class="n">always_off</span><span class="p">}}}}</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-00-01" role="tabpanel" aria-labelled-by="tabs-00-01-tab" tabindex="0">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elixir" data-lang="elixir"><span class="line"><span class="cl"><span class="c1"># config/runtime.exs</span>
</span></span><span class="line"><span class="cl"><span class="n">config</span> <span class="ss">:opentelemetry</span><span class="p">,</span> <span class="ss">sampler</span><span class="p">:</span> <span class="p">{</span><span class="ss">:parent_based</span><span class="p">,</span> <span class="p">%{</span><span class="ss">root</span><span class="p">:</span> <span class="p">{</span><span class="ss">:trace_id_ratio_based</span><span class="p">,</span> <span class="mf">0.10</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">remote_parent_sampled</span><span class="p">:</span> <span class="ss">:always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">remote_parent_not_sampled</span><span class="p">:</span> <span class="ss">:always_off</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">local_parent_sampled</span><span class="p">:</span> <span class="ss">:always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">local_parent_not_sampled</span><span class="p">:</span> <span class="ss">:always_off</span><span class="p">}}</span>
</span></span></code></pre></div>
    </div>
</div>


### AlwaysOn and AlwaysOff Sampler

The other two built-in samplers are the `AlwaysOnSampler` and the
`AlwaysOffSampler`.

#### Environment Variables

You can configure the `ParentBasedSampler` to use either the `AlwaysOnSampler`
or `AlwaysOffSampler` with the environment variable `OTEL_TRACES_SAMPLER`:

```shell
export OTEL_TRACES_SAMPLER="parentbased_always_on"
```

And for the `AlwaysOffSampler`:

```shell
export OTEL_TRACES_SAMPLER="parentbased_always_off"
```

#### Application configuration

Here's an example in the Application configuration with a root sampler that
always samples and using the parent decision in the other cases:

   <ul class="nav nav-tabs" id="tabs-1" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-01-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-00" role="tab"
          data-td-tp-persist="erlang" aria-controls="tabs-01-00" aria-selected="true">
        Erlang
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-01-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-01" role="tab"
          data-td-tp-persist="elixir" aria-controls="tabs-01-01" aria-selected="false">
        Elixir
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-1-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-01-00" role="tabpanel" aria-labelled-by="tabs-01-00-tab" tabindex="1">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-erlang" data-lang="erlang"><span class="line"><span class="cl"><span class="c">%% config/sys.config.src
</span></span></span><span class="line"><span class="cl"><span class="p">{</span><span class="n">opentelemetry</span><span class="p">,</span> <span class="p">{</span><span class="n">sampler</span><span class="p">,</span> <span class="p">{</span><span class="n">parent_based</span><span class="p">,</span> <span class="p">#{</span><span class="n">root</span> <span class="o">=&gt;</span> <span class="n">always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">remote_parent_sampled</span> <span class="o">=&gt;</span> <span class="n">always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">remote_parent_not_sampled</span> <span class="o">=&gt;</span> <span class="n">always_off</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">local_parent_sampled</span> <span class="o">=&gt;</span> <span class="n">always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                          <span class="n">local_parent_not_sampled</span> <span class="o">=&gt;</span> <span class="n">always_off</span><span class="p">}}}}</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-01-01" role="tabpanel" aria-labelled-by="tabs-01-01-tab" tabindex="1">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elixir" data-lang="elixir"><span class="line"><span class="cl"><span class="c1"># config/runtime.exs</span>
</span></span><span class="line"><span class="cl"><span class="n">config</span> <span class="ss">:opentelemetry</span><span class="p">,</span> <span class="ss">sampler</span><span class="p">:</span> <span class="p">{</span><span class="ss">:parent_based</span><span class="p">,</span> <span class="p">%{</span><span class="ss">root</span><span class="p">:</span> <span class="ss">:always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">remote_parent_sampled</span><span class="p">:</span> <span class="ss">:always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">remote_parent_not_sampled</span><span class="p">:</span> <span class="ss">:always_off</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">local_parent_sampled</span><span class="p">:</span> <span class="ss">:always_on</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                                                  <span class="ss">local_parent_not_sampled</span><span class="p">:</span> <span class="ss">:always_off</span><span class="p">}}</span>
</span></span></code></pre></div>
    </div>
</div>


## Custom Sampler

Custom samplers can be created by implementing the
[`otel_sampler` behaviour](https://hexdocs.pm/opentelemetry/1.3.0/otel_sampler.html#callbacks).
This example sampler:

   <ul class="nav nav-tabs" id="tabs-2" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-02-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-00" role="tab"
          data-td-tp-persist="erlang" aria-controls="tabs-02-00" aria-selected="true">
        Erlang
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-02-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-01" role="tab"
          data-td-tp-persist="elixir" aria-controls="tabs-02-01" aria-selected="false">
        Elixir
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-2-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-02-00" role="tabpanel" aria-labelled-by="tabs-02-00-tab" tabindex="2">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-erlang" data-lang="erlang"><span class="line"><span class="cl"><span class="p">-</span><span class="ni">module</span><span class="p">(</span><span class="n">attribute_sampler</span><span class="p">).</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">-</span><span class="ni">behavior</span><span class="p">(</span><span class="n">otel_sampler</span><span class="p">).</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">-</span><span class="ni">export</span><span class="p">([</span><span class="n">description</span><span class="o">/</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">         <span class="n">setup</span><span class="o">/</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">         <span class="n">should_sample</span><span class="o">/</span><span class="mi">7</span><span class="p">]).</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">-</span><span class="ni">include</span><span class="p">(</span><span class="s">&#34;otel_sampler.hrl&#34;</span><span class="p">).</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">setup</span><span class="p">(</span><span class="nv">Attributes</span><span class="p">)</span> <span class="k">when</span> <span class="n">is_map</span><span class="p">(</span><span class="nv">Attributes</span><span class="p">)</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">Attributes</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">setup</span><span class="p">(_)</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">#{}.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">description</span><span class="p">(_)</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;&lt;</span><span class="s">&#34;AttributeSampler&#34;</span><span class="o">&gt;&gt;</span><span class="p">.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">should_sample</span><span class="p">(_</span><span class="nv">Ctx</span><span class="p">,</span> <span class="p">_</span><span class="nv">TraceId</span><span class="p">,</span> <span class="p">_</span><span class="nv">Links</span><span class="p">,</span> <span class="p">_</span><span class="nv">SpanName</span><span class="p">,</span> <span class="p">_</span><span class="nv">SpanKind</span><span class="p">,</span> <span class="nv">Attributes</span><span class="p">,</span> <span class="nv">ConfigAttributes</span><span class="p">)</span> <span class="o">-&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nv">AttributesSet</span> <span class="o">=</span> <span class="nn">sets</span><span class="p">:</span><span class="nf">from_list</span><span class="p">(</span><span class="nn">maps</span><span class="p">:</span><span class="nf">to_list</span><span class="p">(</span><span class="nv">Attributes</span><span class="p">)),</span>
</span></span><span class="line"><span class="cl">    <span class="nv">ConfigSet</span> <span class="o">=</span> <span class="nn">sets</span><span class="p">:</span><span class="nf">from_list</span><span class="p">(</span><span class="nn">maps</span><span class="p">:</span><span class="nf">to_list</span><span class="p">(</span><span class="nv">ConfigAttributes</span><span class="p">)),</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nn">sets</span><span class="p">:</span><span class="nf">is_disjoint</span><span class="p">(</span><span class="nv">AttributesSet</span><span class="p">,</span> <span class="nv">ConfigSet</span><span class="p">)</span> <span class="k">of</span>
</span></span><span class="line"><span class="cl">        <span class="n">true</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="o">?</span><span class="nv">RECORD_AND_SAMPLE</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[]};</span>
</span></span><span class="line"><span class="cl">        <span class="p">_</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="o">?</span><span class="nv">DROP</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[]}</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span><span class="p">.</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-02-01" role="tabpanel" aria-labelled-by="tabs-02-01-tab" tabindex="2">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elixir" data-lang="elixir"><span class="line"><span class="cl"><span class="kd">defmodule</span> <span class="nc">AttributesSampler</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">  <span class="kd">def</span> <span class="n">setup</span><span class="p">(</span><span class="n">attributes</span><span class="p">)</span> <span class="ow">when</span> <span class="n">is_map</span><span class="p">(</span><span class="n">attributes</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="n">attributes</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">def</span> <span class="n">setup</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="p">%{}</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">def</span> <span class="n">description</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;ExampleSampler&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">def</span> <span class="n">should_sample</span><span class="p">(</span><span class="n">_ctx</span><span class="p">,</span> <span class="n">_trace_id</span><span class="p">,</span> <span class="n">_links</span><span class="p">,</span> <span class="n">_span_name</span><span class="p">,</span> <span class="n">_span_kind</span><span class="p">,</span> <span class="n">attributes</span><span class="p">,</span> <span class="n">config_attributes</span><span class="p">)</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">    <span class="n">no_match</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">      <span class="nc">Enum</span><span class="o">.</span><span class="n">into</span><span class="p">(</span><span class="n">attributes</span><span class="p">,</span> <span class="p">%</span><span class="nc">MapSet</span><span class="p">{})</span>
</span></span><span class="line"><span class="cl">      <span class="o">|&gt;</span> <span class="nc">MapSet</span><span class="o">.</span><span class="n">disjoint?</span><span class="p">(</span><span class="nc">Enum</span><span class="o">.</span><span class="n">into</span><span class="p">(</span><span class="n">config_attributes</span><span class="p">,</span> <span class="p">%</span><span class="nc">MapSet</span><span class="p">{}))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">no_match</span><span class="p">,</span> <span class="ss">do</span><span class="p">:</span> <span class="p">{</span><span class="ss">:record_and_sample</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[]},</span> <span class="ss">else</span><span class="p">:</span> <span class="p">{</span><span class="ss">:drop</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[]}</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span>
</span></span></code></pre></div>
    </div>
</div>


Will sample Spans that do not have any attributes that match the attributes
passed as the sampler's configuration.

Example configuration to not sample any Span with an attribute specifying the
URL requested is `/healthcheck`:

   <ul class="nav nav-tabs" id="tabs-3" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-03-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-00" role="tab"
          data-td-tp-persist="erlang" aria-controls="tabs-03-00" aria-selected="true">
        Erlang
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-03-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-01" role="tab"
          data-td-tp-persist="elixir" aria-controls="tabs-03-01" aria-selected="false">
        Elixir
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-3-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-03-00" role="tabpanel" aria-labelled-by="tabs-03-00-tab" tabindex="3">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-erlang" data-lang="erlang"><span class="line"><span class="cl"><span class="p">{</span><span class="n">opentelemetry</span><span class="p">,</span> <span class="p">{</span><span class="n">sampler</span><span class="p">,</span> <span class="p">{</span><span class="n">attributes_sampler</span><span class="p">,</span> <span class="p">#{</span><span class="n">&#39;http.target&#39;</span> <span class="o">=&gt;</span> <span class="o">&lt;&lt;</span><span class="s">&#34;/healthcheck&#34;</span><span class="o">&gt;&gt;</span><span class="p">}}}}</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-03-01" role="tabpanel" aria-labelled-by="tabs-03-01-tab" tabindex="3">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-elixir" data-lang="elixir"><span class="line"><span class="cl"><span class="n">config</span> <span class="ss">:opentelemetry</span><span class="p">,</span> <span class="ss">sampler</span><span class="p">:</span> <span class="p">{</span><span class="nc">AttributesSampler</span><span class="p">,</span> <span class="p">%{</span><span class="s2">&#34;http.target&#34;</span><span class="p">:</span> <span class="s2">&#34;/healthcheck&#34;</span><span class="p">}}</span>
</span></span></code></pre></div>
    </div>
</div>
