# Propagation


With context propagation, [Signals](/docs/concepts/signals/) can be correlated
with each other, regardless of where they are generated. Although not limited to
tracing, context propagation allows [traces](/docs/concepts/signals/traces/) to
build causal information about a system across services that are arbitrarily
distributed across process and network boundaries.

For the vast majority of use cases, libraries that natively support
OpenTelemetry or [instrumentation libraries](../libraries/) will automatically
propagate trace context across services for you. It is only in rare cases that
you will need to propagate context manually.



To learn more, see [Context propagation](/docs/concepts/context-propagation).




{{__hugo_ctx/}}



## Automatic context propagation

Distributed traces extend beyond a single service, meaning some context must be
propagated across services to create the parent-child relationship between
Spans. This requires cross service
[_context propagation_](/docs/specs/otel/overview/#context-propagation), a
mechanism where identifiers for a Trace are sent to remote processes.

Instrumentation libraries for HTTP frameworks and servers like
[Phoenix](https://github.com/open-telemetry/opentelemetry-erlang-contrib/tree/main/instrumentation/opentelemetry_phoenix),
[Cowboy](https://github.com/open-telemetry/opentelemetry-erlang-contrib/tree/main/instrumentation/opentelemetry_cowboy),
[Elli](https://github.com/open-telemetry/opentelemetry-erlang-contrib/tree/main/instrumentation/opentelemetry_elli)
and clients like
[Tesla](https://github.com/open-telemetry/opentelemetry-erlang-contrib/tree/main/instrumentation/opentelemetry_tesla)
automatically inject or extract context using the globally registered
propagators. By default the global propagators used are the W3C
[Trace Context](https://w3c.github.io/trace-context/) and
[Baggage](https://www.w3.org/TR/baggage/) formats.

You can configure global propagators using the OTP application environment
variable `text_map_propagators`:

   <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">%% sys.config
</span></span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span><span class="n">text_map_propagators</span><span class="p">,</span> <span class="p">[</span><span class="n">baggage</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                        <span class="n">trace_context</span><span class="p">]},</span>
</span></span><span class="line"><span class="cl"><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">## runtime.exs</span>
</span></span><span class="line"><span class="cl"><span class="n">...</span>
</span></span><span class="line"><span class="cl"><span class="ss">text_map_propagators</span><span class="p">:</span> <span class="p">[</span><span class="ss">:baggage</span><span class="p">,</span> <span class="ss">:trace_context</span><span class="p">],</span>
</span></span><span class="line"><span class="cl"><span class="n">...</span>
</span></span></code></pre></div>
    </div>
</div>


You can also pass a comma separated list using the environment variable
`OTEL_PROPAGATORS`. Both forms of configuration accept the values
`trace_context`, `baggage`, [`b3`](https://github.com/openzipkin/b3-propagation)
and `b3multi`.

## Manual context propagation

To manually inject or extract context, you can use the
`otel_propagator_text_map` module:

   <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="c">%% uses the context from the process dictionary to add to an empty list of headers
</span></span></span><span class="line"><span class="cl"><span class="nv">Headers</span> <span class="o">=</span> <span class="nn">otel_propagator_text_map</span><span class="p">:</span><span class="nf">inject</span><span class="p">([]),</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">%% creates a context in the process dictionary from Headers
</span></span></span><span class="line"><span class="cl"><span class="nn">otel_propagator_text_map</span><span class="p">:</span><span class="nf">extract</span><span class="p">(</span><span class="nv">Headers</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="c1"># uses the context from the process dictionary to add to an empty list of headers</span>
</span></span><span class="line"><span class="cl"><span class="n">headers</span> <span class="o">=</span> <span class="ss">:otel_propagator_text_map</span><span class="o">.</span><span class="n">inject</span><span class="p">([])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># creates a context in the process dictionary from headers</span>
</span></span><span class="line"><span class="cl"><span class="ss">:otel_propagator_text_map</span><span class="o">.</span><span class="n">extract</span><span class="p">(</span><span class="n">headers</span><span class="p">)</span>
</span></span></code></pre></div>
    </div>
</div>


`otel_propagator_text_map:inject/1` and `otel_propagator_text_map:extract/1` use
globally registered propagators. To use a specific propagator
`otel_propagator_text_map:inject/2` and `otel_propagator_text_map:extract/2` can
be used with the first argument being the name of the propagator module to call.

## Next steps

To learn more about propagation, read the
[Propagators API specification](/docs/specs/otel/context/api-propagators/).
