open-telemetry/api
OpenTelemetry API for PHP: vendor-neutral interfaces for tracing, metrics, and context propagation. Use it to instrument libraries/apps and connect to any OpenTelemetry SDK/exporter. Part of the OpenTelemetry PHP project (subtree split).
Install the package:
composer require open-telemetry/api
(Note: This is a pure API package—you'll need an SDK like open-telemetry/sdk for implementation.)
First use case: Instrumenting a route
use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\API\Trace\Span;
// Get the tracer (via SDK or DI container)
$tracer = \OpenTelemetry\API\GlobalTracer::getTracer('my-app');
// Start a span
$span = $tracer->spanBuilder('user.route')
->setAttribute('http.method', 'GET')
->startSpan();
try {
// Your route logic here
$span->addEvent('route.processed');
} finally {
$span->end();
}
Key entry points:
GlobalTracer::getTracer() – For trace instrumentation.GlobalMeter::getMeter() – For metrics.GlobalPropagation::getTextMapPropagator() – For context propagation.use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\API\Trace\Status;
$span = \OpenTelemetry\API\GlobalTracer::getTracer('my-app')->spanBuilder('http.request')
->setAttribute('http.url', $request->getUri())
->setAttribute('http.method', $request->getMethod())
->startSpan();
try {
$response = $client->send($request);
$span->setAttribute('http.status_code', $response->getStatusCode());
} catch (\Exception $e) {
$span->recordException($e);
$span->setStatus(new Status(Status::ERROR, $e->getMessage()));
} finally {
$span->end();
}
$parentSpan = \OpenTelemetry\API\GlobalTracer::getTracer('my-app')->getCurrentSpan();
$childSpan = $parentSpan->tracer()->spanBuilder('db.query')
->setParent($parentSpan)
->startSpan();
$meter = \OpenTelemetry\API\GlobalMeter::getMeter('my-app');
$counter = $meter->createCounter('request.count');
$counter->add(1, ['http.method' => 'GET']);
$histogram = $meter->createHistogram('request.latency.ms');
$histogram->record($executionTimeMs, ['route' => 'user.profile']);
use OpenTelemetry\API\Propagation\TextMapPropagator;
$propagator = \OpenTelemetry\API\GlobalPropagation::getTextMapPropagator();
$carrier = [];
$propagator->inject($carrier, \OpenTelemetry\API\GlobalContext::getCurrent());
// Send $carrier with HTTP headers
$client->send($request->withHeaders($carrier));
$propagator->extract($carrier, $request->getHeaders());
\OpenTelemetry\API\GlobalContext::storeInContext($carrier);
\OpenTelemetry\API\Instrumentation\Hook::register(
\OpenTelemetry\API\Instrumentation\Hook::HTTP_CLIENT,
function ($url, $options, $next) {
$span = \OpenTelemetry\API\GlobalTracer::getTracer('my-app')->spanBuilder('http.client')
->setAttribute('http.url', $url)
->startSpan();
try {
$response = $next($url, $options);
$span->setAttribute('http.status_code', $response->getStatusCode());
return $response;
} finally {
$span->end();
}
}
);
open-telemetry/sdk) for actual telemetry collection.composer require open-telemetry/sdk
try/finally when working with spans to avoid memory leaks:
$span->end(); // Critical!
InstrumentationInterface and ConfigurationResolver are deprecated (since v1.9.0). Use SDK-specific config instead.export OTEL_LOG_LEVEL=debug
GlobalContext::getCurrent() to verify active spans.| Issue | Solution |
|---|---|
| Spans not appearing in backend | Ensure SDK is properly configured. |
| Context not propagated | Verify inject()/extract() usage. |
| High memory usage | End spans promptly; avoid leaks. |
| Metrics not updating | Check meter enablement (Meter::isEnabled()). |
SpanAttribute for type-safe attributes.bootstrap/app.php).ObservableInstrument for custom metric collection.use OpenTelemetry\API\GlobalTracer;
public function register()
{
$this->app->singleton(TracerInterface::class, function () {
return GlobalTracer::getTracer('laravel-app');
});
}
public function handle($request, Closure $next)
{
$span = GlobalTracer::getTracer('laravel-app')->spanBuilder('middleware')
->setAttribute('http.method', $request->method())
->startSpan();
try {
return $next($request);
} finally {
$span->end();
}
}
How can I help you explore Laravel packages today?