Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Opentelemetry Laravel Package

open-telemetry/opentelemetry

OpenTelemetry PHP metapackage bundling the API and SDK plus common HTTP exporters (OTLP, Zipkin), a PSR-7 factory (nyholm/psr7), and Symfony HTTP client. Great for trying OpenTelemetry; for production, require needed packages directly.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the metapackage to your Laravel project via Composer:

    composer require open-telemetry/opentelemetry
    

    For production, replace with explicit package versions (e.g., open-telemetry/sdk, open-telemetry/exporter-otlp).

  2. First Use Case: Basic Tracing Initialize a tracer in bootstrap/app.php or a service provider:

    use OpenTelemetry\API\Trace\TracerInterface;
    use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
    use OpenTelemetry\SDK\Trace\TracerProvider;
    
    $tracerProvider = new TracerProvider();
    $tracerProvider->addSpanProcessor(new SimpleSpanProcessor());
    $tracer = $tracerProvider->getTracer('laravel-app');
    

    Start a root span in a controller or middleware:

    $span = $tracer->spanBuilder('user-request')->startSpan();
    try {
        // Your logic here
    } finally {
        $span->end();
    }
    
  3. Exporter Configuration Configure an OTLP exporter (e.g., for Jaeger or Honeycomb) in a config file (config/opentelemetry.php):

    return [
        'exporter' => [
            'otlp' => [
                'endpoint' => env('OPENTELEMETRY_ENDPOINT', 'http://localhost:4318'),
                'headers' => [
                    'Authorization' => 'Bearer ' . env('OPENTELEMETRY_API_KEY'),
                ],
            ],
        ],
    ];
    

    Attach it to the provider:

    $exporter = new \OpenTelemetry\Exporter\OTlp\OtlpHttpExporter(
        new \Nyholm\Psr7\Factory\Psr17Factory(),
        new \Symfony\Contracts\HttpClient\HttpClientInterface(),
        $config['exporter']['otlp']
    );
    $tracerProvider->addSpanProcessor(new \OpenTelemetry\SDK\Trace\SpanProcessor\BatchingSpanProcessor($exporter));
    

Implementation Patterns

Core Workflows

  1. Middleware-Based Tracing Create a middleware to auto-instrument HTTP requests:

    namespace App\Http\Middleware;
    
    use Closure;
    use OpenTelemetry\API\Trace\TracerInterface;
    
    class TelemetryMiddleware
    {
        public function __construct(protected TracerInterface $tracer) {}
    
        public function handle($request, Closure $next)
        {
            $span = $this->tracer->spanBuilder('http-request')
                ->setAttribute('http.method', $request->method())
                ->setAttribute('http.url', $request->url())
                ->startSpan();
    
            try {
                return $next($request)->withSpan($span);
            } finally {
                $span->end();
            }
        }
    }
    

    Register it in app/Http/Kernel.php:

    protected $middleware = [
        \App\Http\Middleware\TelemetryMiddleware::class,
    ];
    
  2. Database Query Tracing Use a query listener to trace Eloquent queries:

    use OpenTelemetry\API\Trace\TracerInterface;
    use Illuminate\Database\Events\QueryExecuted;
    
    public function boot()
    {
        \DB::listen(function (QueryExecuted $query) {
            $span = app(TracerInterface::class)->spanBuilder('db-query')
                ->setAttribute('db.system', 'mysql')
                ->setAttribute('db.statement', $query->sql)
                ->startSpan();
    
            try {
                // Simulate query execution time
            } finally {
                $span->end();
            }
        });
    }
    
  3. Context Propagation Propagate spans across service boundaries (e.g., HTTP clients):

    use OpenTelemetry\Context\Context;
    use OpenTelemetry\Context\Propagation\TextMapPropagator;
    
    $propagator = new TextMapPropagator();
    $context = Context::withPropagator($propagator);
    
    $httpClient = \Symfony\Contracts\HttpClient\HttpClient::create();
    $response = $httpClient->request('GET', 'https://api.example.com', [
        'headers' => $propagator->inject(
            ['traceparent' => ''],
            Context::current()
        ),
    ]);
    

Integration Tips

  • Laravel Service Container: Bind the TracerInterface and MeterInterface to the container in a service provider:
    $this->app->singleton(TracerInterface::class, function ($app) {
        $provider = new TracerProvider();
        $provider->addSpanProcessor(new BatchingSpanProcessor(
            new OtlpHttpExporter(/* ... */)
        ));
        return $provider->getTracer('laravel-app');
    });
    
  • Queue Workers: Instrument queue jobs by wrapping handle():
    public function handle()
    {
        $span = app(TracerInterface::class)->spanBuilder('job-' . $this->job->id)->startSpan();
        try {
            // Job logic
        } finally {
            $span->end();
        }
    }
    
  • HTTP Client: Use the built-in HttpClient for automatic context propagation:
    $client = \OpenTelemetry\Contrib\Http\Client::create();
    $response = $client->request('GET', 'https://api.example.com');
    

Gotchas and Tips

Pitfalls

  1. Span Leaks

    • Issue: Unclosed spans (e.g., exceptions in try-finally blocks) can leak memory.
    • Fix: Use try-finally or a SpanProcessor with auto-flushing (e.g., BatchingSpanProcessor).
    • Debug: Check for warnings in logs or use tracerProvider->forceFlush().
  2. Context Propagation Failures

    • Issue: Missing headers or incorrect propagator usage can break distributed tracing.
    • Fix: Verify headers (e.g., traceparent) are injected/carried:
      $propagator = new TextMapPropagator();
      $carrier = [];
      $propagator->inject($carrier, Context::current());
      assert(isset($carrier['traceparent']));
      
  3. Exporter Timeouts

    • Issue: OTLP exporters may hang if the endpoint is unreachable.
    • Fix: Configure timeouts and retries:
      $exporter = new OtlpHttpExporter(/* ... */, [
          'timeout' => 2.0,
          'retry' => [
              'max_attempts' => 3,
              'delay' => 100,
          ],
      ]);
      
  4. Attribute Limits

    • Issue: Exporters may drop spans with too many attributes (e.g., >128).
    • Fix: Limit attributes or use resource attributes for static metadata.

Debugging

  • Log Spans: Use a SimpleSpanProcessor with a custom logger:
    $processor = new SimpleSpanProcessor(function ($span) {
        \Log::debug('Span', [
            'name' => $span->getName(),
            'attributes' => $span->getAttributes(),
        ]);
    });
    
  • Validate Traces: Use tools like Jaeger or Honeycomb to visualize traces.
  • Check Context: Log the current context to verify propagation:
    \Log::debug('Current Context', [
        'trace_id' => Context::current()->getValue('trace_id'),
    ]);
    

Extension Points

  1. Custom Span Processors Extend SpanProcessorInterface to filter or modify spans:

    class FilterSpanProcessor implements SpanProcessorInterface
    {
        public function onStart(Span $span, ?Span $parentSpan = null) {}
        public function onEnd(Span $span) {
            if ($span->getName() === 'ignored-span') {
                $span->setStatus(new Status(StatusCode::ERROR_UNKNOWN, 'Filtered'));
            }
        }
    }
    
  2. Resource Attributes Add static metadata (e.g., service version) via Resource:

    $resource = new Resource([
        'service.name' => 'laravel-app',
        'service.version' => '1.0.0',
    ]);
    $tracerProvider = new TracerProvider([], [$resource]);
    
  3. Instrumentation Libraries Use community packages like:

Configuration Quirks

  • Environment Variables: Prefer .env for exporter endpoints:
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
amashukov/lnd-client-php
althinect/enum-permission
andydefer/laravel-actions
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor