Exporters
Send telemetry to the OpenTelemetry 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, Zipkin, Prometheus, or a vendor-specific backend.
Available exporters
The registry contains a list of exporters for PHP.
Among exporters, OpenTelemetry Protocol (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.
This page covers the main OpenTelemetry PHP exporters and how to set them up.
Note
If you use automatic instrumentation you can setup exporters with zero-code configuration to setup exporters.OTLP
To send trace data to a OTLP endpoint (like the collector or
Jaeger) you’ll need to use the open-telemetry/exporter-otlp
package and an
HTTP client that satisfied psr/http-client-implementation
:
composer require \
open-telemetry/exporter-otlp \
php-http/guzzle7-adapter
To use the gRPC exporter, you will also need to install the
open-telemetry/transport-grpc
package, and the grpc
extension:
pecl install grpc
composer require open-telemetry/transport-grpc
Next, configure an exporter with an OTLP endpoint. For example:
<?php
require __DIR__ . '/vendor/autoload.php';
use OpenTelemetry\API\Signals;
use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory;
use OpenTelemetry\Contrib\Otlp\OtlpUtil;
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
$transport = (new GrpcTransportFactory())->create('http://jaeger:4317' . OtlpUtil::method(Signals::TRACE));
$exporter = new SpanExporter($transport);
$tracerProvider = new TracerProvider(
new SimpleSpanProcessor($exporter)
);
<?php
require __DIR__ . '/vendor/autoload.php';
use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory;
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
$transport = (new OtlpHttpTransportFactory())->create('http://jaeger:4318/v1/traces', 'application/x-protobuf');
$exporter = new SpanExporter($transport);
$tracerProvider = new TracerProvider(
new SimpleSpanProcessor($exporter)
);
<?php
require __DIR__ . '/vendor/autoload.php';
use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory;
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
$transport = (new OtlpHttpTransportFactory())->create('http://jaeger:4318/v1/traces', 'application/json');
$exporter = new SpanExporter($transport);
$tracerProvider = new TracerProvider(
new SimpleSpanProcessor($exporter)
);
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
$tracer->spanBuilder('example')->startSpan()->end();
<?php
require __DIR__ . '/vendor/autoload.php';
use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory;
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
$transport = (new OtlpHttpTransportFactory())->create('http://jaeger:4318/v1/traces', 'application/x-ndjson');
$exporter = new SpanExporter($transport);
$tracerProvider = new TracerProvider(
new SimpleSpanProcessor($exporter)
);
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
$tracer->spanBuilder('example')->startSpan()->end();
Then, append the following code to generate a span:
$tracer = $tracerProvider->getTracer('io.opentelemetry.contrib.php');
$tracer
->spanBuilder('example')
->startSpan()
->end();
To try out the example above, you can run Jaeger in a docker container:
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 to visualize traces, you’ll need to set it up first. Here’s how to run it locally in a docker container.
docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin
Install the exporter package as a dependency for your application:
composer require open-telemetry/exporter-zipkin
Update the example to use the Zipkin exporter and to send data to your Zipkin backend:
$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 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 as an agent. The agent can quickly accept, then batch send telemetry data to the backend.