# Exporters

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

---

Send telemetry to the [OpenTelemetry Collector](/docs/collector/) to make sure
it's exported correctly. Using the Collector in production environments is a
best practice. To visualize your telemetry, export it to a backend such as
[Jaeger](https://jaegertracing.io/), [Zipkin](https://zipkin.io/),
[Prometheus](https://prometheus.io/), or a
[vendor-specific](/ecosystem/vendors/) backend.



## Available exporters

The registry contains a [list of exporters for PHP][reg].





Among exporters, [OpenTelemetry Protocol (OTLP)][OTLP] exporters are designed
with the OpenTelemetry data model in mind, emitting OTel data without any loss
of information. Furthermore, many tools that operate on telemetry data support
OTLP (such as [Prometheus][], [Jaeger][], and most [vendors][]), providing you
with a high degree of flexibility when you need it. To learn more about OTLP,
see [OTLP Specification][OTLP].

[Jaeger]: /blog/2022/jaeger-native-otlp/
[OTLP]: /docs/specs/otlp/
[Prometheus]:
  https://prometheus.io/docs/prometheus/2.55/feature_flags/#otlp-receiver
[reg]: </ecosystem/registry/?component=exporter&language=php>
[vendors]: /ecosystem/vendors/



This page covers the main OpenTelemetry PHP exporters and how to set
them up.






{{__hugo_ctx/}}


> [!NOTE]
>
> If you use [zero-code instrumentation](/docs/zero-code/php/) you can set up
> exporters with
> [zero-code configuration to setup exporters](/docs/zero-code/php#configuration).

## OTLP

To send trace data to a OTLP endpoint (like the [collector](/docs/collector) or
Jaeger) you'll need to use the `open-telemetry/exporter-otlp` package and an
HTTP client that satisfied `psr/http-client-implementation`:

```shell
composer require \
  open-telemetry/exporter-otlp \
  php-http/guzzle7-adapter
```

To use the [gRPC](https://grpc.io/) exporter, you will also need to install the
`open-telemetry/transport-grpc` package, and the `grpc` extension:

```shell
pecl install grpc
composer require open-telemetry/transport-grpc
```

Next, configure an exporter with an OTLP endpoint. For example:

     <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="grpc" aria-controls="tabs-01-00" aria-selected="true">
        gRPC
      </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="protobuf" aria-controls="tabs-01-01" aria-selected="false">
        protobuf
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-01-02-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-02" role="tab"
          data-td-tp-persist="json" aria-controls="tabs-01-02" aria-selected="false">
        JSON
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-01-03-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-03" role="tab"
          data-td-tp-persist="ndjson" aria-controls="tabs-01-03" aria-selected="false">
        NDJSON
      </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-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">require</span> <span class="no">__DIR__</span> <span class="o">.</span> <span class="s1">&#39;/vendor/autoload.php&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\API\Signals</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Grpc\GrpcTransportFactory</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\OtlpUtil</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\SpanExporter</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\TracerProvider</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$transport</span> <span class="o">=</span> <span class="p">(</span><span class="k">new</span> <span class="nx">GrpcTransportFactory</span><span class="p">())</span><span class="o">-&gt;</span><span class="na">create</span><span class="p">(</span><span class="s1">&#39;http://jaeger:4317&#39;</span> <span class="o">.</span> <span class="nx">OtlpUtil</span><span class="o">::</span><span class="na">method</span><span class="p">(</span><span class="nx">Signals</span><span class="o">::</span><span class="na">TRACE</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="nv">$exporter</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SpanExporter</span><span class="p">(</span><span class="nv">$transport</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$tracerProvider</span> <span class="o">=</span>  <span class="k">new</span> <span class="nx">TracerProvider</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="nv">$exporter</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-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">require</span> <span class="no">__DIR__</span> <span class="o">.</span> <span class="s1">&#39;/vendor/autoload.php&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\SpanExporter</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\TracerProvider</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$transport</span> <span class="o">=</span> <span class="p">(</span><span class="k">new</span> <span class="nx">OtlpHttpTransportFactory</span><span class="p">())</span><span class="o">-&gt;</span><span class="na">create</span><span class="p">(</span><span class="s1">&#39;http://jaeger:4318/v1/traces&#39;</span><span class="p">,</span> <span class="s1">&#39;application/x-protobuf&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$exporter</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SpanExporter</span><span class="p">(</span><span class="nv">$transport</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$tracerProvider</span> <span class="o">=</span>  <span class="k">new</span> <span class="nx">TracerProvider</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="nv">$exporter</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-02" role="tabpanel" aria-labelled-by="tabs-01-02-tab" tabindex="1">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">require</span> <span class="no">__DIR__</span> <span class="o">.</span> <span class="s1">&#39;/vendor/autoload.php&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\SpanExporter</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\TracerProvider</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$transport</span> <span class="o">=</span> <span class="p">(</span><span class="k">new</span> <span class="nx">OtlpHttpTransportFactory</span><span class="p">())</span><span class="o">-&gt;</span><span class="na">create</span><span class="p">(</span><span class="s1">&#39;http://jaeger:4318/v1/traces&#39;</span><span class="p">,</span> <span class="s1">&#39;application/json&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$exporter</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SpanExporter</span><span class="p">(</span><span class="nv">$transport</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$tracerProvider</span> <span class="o">=</span>  <span class="k">new</span> <span class="nx">TracerProvider</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="nv">$exporter</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$tracer</span> <span class="o">=</span> <span class="nv">$tracerProvider</span><span class="o">-&gt;</span><span class="na">getTracer</span><span class="p">(</span><span class="s1">&#39;io.opentelemetry.contrib.php&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$tracer</span><span class="o">-&gt;</span><span class="na">spanBuilder</span><span class="p">(</span><span class="s1">&#39;example&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">startSpan</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">end</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-01-03" role="tabpanel" aria-labelled-by="tabs-01-03-tab" tabindex="1">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">require</span> <span class="no">__DIR__</span> <span class="o">.</span> <span class="s1">&#39;/vendor/autoload.php&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\Contrib\Otlp\SpanExporter</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">use</span> <span class="nx">OpenTelemetry\SDK\Trace\TracerProvider</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$transport</span> <span class="o">=</span> <span class="p">(</span><span class="k">new</span> <span class="nx">OtlpHttpTransportFactory</span><span class="p">())</span><span class="o">-&gt;</span><span class="na">create</span><span class="p">(</span><span class="s1">&#39;http://jaeger:4318/v1/traces&#39;</span><span class="p">,</span> <span class="s1">&#39;application/x-ndjson&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$exporter</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SpanExporter</span><span class="p">(</span><span class="nv">$transport</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">$tracerProvider</span> <span class="o">=</span>  <span class="k">new</span> <span class="nx">TracerProvider</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="nv">$exporter</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$tracer</span> <span class="o">=</span> <span class="nv">$tracerProvider</span><span class="o">-&gt;</span><span class="na">getTracer</span><span class="p">(</span><span class="s1">&#39;io.opentelemetry.contrib.php&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nv">$tracer</span><span class="o">-&gt;</span><span class="na">spanBuilder</span><span class="p">(</span><span class="s1">&#39;example&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">startSpan</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">end</span><span class="p">();</span>
</span></span></code></pre></div>
    </div>
</div>


Then, append the following code to generate a span:

```php
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
$tracer
  ->spanBuilder('example')
  ->startSpan()
  ->end();
```

To try out the example above, you can run
[Jaeger](https://www.jaegertracing.io/) in a docker container:

```shell
docker run -d --name jaeger \
  -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 14250:14250 \
  -p 14268:14268 \
  -p 14269:14269 \
  -p 9411:9411 \
  jaegertracing/all-in-one:latest
```

## Zipkin

If you're using [Zipkin](https://zipkin.io/) to visualize traces, you'll need to
set it up first. Here's how to run it locally in a docker container.

```shell
docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin
```

Install the exporter package as a dependency for your application:

```shell
composer require open-telemetry/exporter-zipkin
```

Update the example to use the Zipkin exporter and to send data to your Zipkin
backend:

```php
$transport = \OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory::discover()
    ->create('http://zipkin:9411/api/v2/spans', 'application/json');
$zipkinExporter = new ZipkinExporter($transport);
$tracerProvider =  new TracerProvider(
    new SimpleSpanProcessor($zipkinExporter)
);
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
```

## Minimizing export delays

Most PHP runtimes are synchronous and blocking. Sending telemetry data
[can delay](/docs/specs/otel/performance/#shutdown-and-explicit-flushing-could-block)
HTTP responses being received by your users.

If you are using `fastcgi`, you could issue a call to `fastcgi_finish_request()`
after sending a user response, which means that delays in sending telemetry data
will not hold up request processing.

To minimize the impact of slow transport of telemetry data, particularly for
external or cloud-based backends, you should consider using the
[OpenTelemetry Collector](/docs/collector/) as an
[agent](/docs/collector/deploy/agent/). The agent can quickly accept, then batch
send telemetry data to the backend.
