The pitch
Before OTel, every APM vendor had its own SDK. Switching vendors meant rewriting instrumentation. OTel decouples: your code emits OTel spans, a Collector forwards them to whatever backend you want. Today that might be Tempo; tomorrow Honeycomb; ten years from now, something not yet invented. Your instrumentation doesn't change.
The three pillars
- Traces — request waterfalls across services. The most mature OTel pillar.
- Metrics — counters, gauges, histograms. Solid but newer than tracing.
- Logs — structured log records with trace correlation. Still stabilizing across the ecosystem.
Setting up OTel in Laravel
composer require \
open-telemetry/sdk \
open-telemetry/exporter-otlp \
open-telemetry/sem-convapp/Providers/TelemetryServiceProvider.php
use OpenTelemetry\API\Globals;
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor;
use OpenTelemetry\SDK\Trace\TracerProvider;
use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
use OpenTelemetry\SemConv\ResourceAttributes;
public function register(): void
{
$transport = (new PsrTransportFactory())->create(
'http://localhost:4318/v1/traces', 'application/x-protobuf'
);
$exporter = new SpanExporter($transport);
$resource = ResourceInfoFactory::defaultResource()->merge(
ResourceInfo::create(Attributes::create([
ResourceAttributes::SERVICE_NAME => config('app.name'),
ResourceAttributes::DEPLOYMENT_ENVIRONMENT => config('app.env'),
]))
);
$tracerProvider = TracerProvider::builder()
->addSpanProcessor(new BatchSpanProcessor($exporter))
->setResource($resource)
->build();
Globals::registerInitializer(fn () => $tracerProvider);
}Run an OTel Collector alongside your app. Forward spans to Tempo, Jaeger, SigNoz, or any SaaS vendor that speaks OTLP.
OTel vs Nightwatch (Laravel's first-party package)
- OTel: vendor-neutral, polyglot, generic. You portability at the cost of Laravel depth.
- Nightwatch: Laravel-specific, framework-aware, captures Eloquent patterns, queue job classes, scheduled tasks with minimal code. Not portable to non-Laravel services.
A common split: use the Nightwatch package (via NightOwl or Nightwatch Cloud) for Laravel-native monitoring; add OTel only at service boundaries where you need cross-service traces.