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

Laravel Open Telemetry Laravel Package

spatie/laravel-open-telemetry

Add OpenTelemetry tracing to Laravel to measure performance and follow requests across dispatched jobs and services. Export traces to tools like Jaeger or Aspecto for end-to-end visibility and debugging. (Package still in development.)

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-open-telemetry
    php artisan vendor:publish --provider="Spatie\OpenTelemetry\OpenTelemetryServiceProvider"
    

    Publish the config file to adjust exporters (e.g., OTLP, Jaeger, Zipkin).

  2. First Use Case: Enable OpenTelemetry in config/open-telemetry.php:

    'enabled' => env('OPEN_TELEMETRY_ENABLED', false),
    

    Set OPEN_TELEMETRY_ENABLED=true in your .env.

  3. Verify Integration: Run a request or job. Check your configured exporter (e.g., Jaeger UI at http://localhost:16686) for traces.


Where to Look First

  • Config File: config/open-telemetry.php – Define exporters, sampling rate, and service name.
  • Middleware: app/Http/Middleware/TraceRequests.php – Auto-instrument HTTP requests.
  • Service Provider: Spatie\OpenTelemetry\OpenTelemetryServiceProvider – Bootstraps the tracer.
  • Documentation: Spatie’s OpenTelemetry Guide (if available post-archive).

Implementation Patterns

Core Workflows

1. Auto-Instrumentation

  • HTTP Requests: The TraceRequests middleware automatically instruments incoming requests. No manual setup required beyond enabling the package.
    // app/Http/Kernel.php
    protected $middleware = [
        // ...
        \Spatie\OpenTelemetry\Middleware\TraceRequests::class,
    ];
    
  • Jobs: Use the traceJob helper or withTrace() method to instrument queue jobs:
    use Spatie\OpenTelemetry\Facades\OpenTelemetry;
    
    OpenTelemetry::traceJob('my-job', function () {
        // Job logic
    });
    
    // OR via facade:
    \Spatie\OpenTelemetry\Facades\OpenTelemetry::traceJob('my-job', fn() => $this->handle());
    

2. Manual Instrumentation

  • Spans: Create custom spans for critical sections of code:
    $span = OpenTelemetry::tracer()->startSpan('database-query');
    try {
        DB::table('users')->get();
    } finally {
        $span->end();
    }
    
  • Context Propagation: Pass context between services or layers:
    $context = OpenTelemetry::tracer()->getCurrentSpan()->getContext();
    OpenTelemetry::tracer()->withContext($context, fn() => $this->callExternalService());
    

3. Exporter Configuration

  • Configure exporters in config/open-telemetry.php:
    'exporters' => [
        'otlp' => [
            'endpoint' => env('OTLP_ENDPOINT', 'http://localhost:4318'),
            'headers' => [],
        ],
        'jaeger' => [
            'endpoint' => env('JAEGER_ENDPOINT', 'http://localhost:14268/api/traces'),
        ],
    ],
    
  • Enable an exporter:
    'enabled_exporters' => ['otlp'], // or 'jaeger', 'zipkin'
    

4. Sampling

  • Adjust sampling rate to balance overhead and data volume:
    'sampling' => [
        'rate' => env('OPEN_TELEMETRY_SAMPLING_RATE', 0.1), // 10% of traces
        'parentBased' => env('OPEN_TELEMETRY_PARENT_BASED_SAMPLING', false),
    ],
    

Integration Tips

  • Queue Workers: Ensure your queue workers (e.g., Laravel Horizon, Supervisor) have access to the same OpenTelemetry configuration. Use environment variables to sync settings.
  • Microservices: Propagate traces across service boundaries using HTTP headers (traceparent). The package auto-injects these headers for outgoing requests.
  • Database Queries: For fine-grained SQL tracing, combine with spatie/laravel-query-logger or instrument queries manually:
    $span = OpenTelemetry::tracer()->startSpan('query-users');
    DB::enableQueryLog();
    $users = User::all();
    $span->setAttribute('db.query', $users->getQueryLog()[0]['query']);
    $span->end();
    
  • Testing: Disable OpenTelemetry in tests to avoid noise:
    config(['open-telemetry.enabled' => false]);
    

Gotchas and Tips

Pitfalls

  1. Performance Overhead:

    • Issue: Excessive sampling or deep instrumentation can degrade performance.
    • Fix: Start with a low sampling rate (e.g., 0.1) and monitor. Use parentBased sampling for critical paths.
    • Debug: Check config/open-telemetry.php for sampling settings.
  2. Exporter Configuration:

    • Issue: Misconfigured exporters (e.g., wrong OTLP endpoint) may silently fail.
    • Fix: Validate exporter endpoints and credentials. Use config:clear after changes.
    • Debug: Check Laravel logs for exporter errors or enable debug mode:
      'debug' => env('OPEN_TELEMETRY_DEBUG', false),
      
  3. Context Leaks:

    • Issue: Context not properly propagated between services or layers.
    • Fix: Always use withContext() for cross-service calls:
      OpenTelemetry::tracer()->withContext($context, fn() => $this->externalCall());
      
    • Debug: Verify traceparent headers in outgoing requests (use browser dev tools or tcpdump).
  4. Job Instrumentation:

    • Issue: Jobs not appearing in traces due to missing context.
    • Fix: Ensure jobs are dispatched with the correct context:
      OpenTelemetry::traceJob('my-job', fn() => $this->handle());
      
    • Debug: Check if the job’s queue connection supports OpenTelemetry (e.g., Redis with otel-redis).
  5. Middleware Order:

    • Issue: TraceRequests middleware placed after authentication may miss timing for auth logic.
    • Fix: Place TraceRequests as early as possible in the middleware stack:
      // app/Http/Kernel.php
      protected $middlewareGroups = [
          'web' => [
              \Spatie\OpenTelemetry\Middleware\TraceRequests::class,
              // ...
          ],
      ];
      

Debugging Tips

  1. Enable Debug Mode:

    'debug' => true,
    

    This logs trace IDs and span events to Laravel logs.

  2. Check Trace IDs:

    • Add a middleware to log trace IDs for debugging:
      public function handle($request, Closure $next)
      {
          $traceId = OpenTelemetry::tracer()->getCurrentSpan()?->getContext()->getTraceId();
          Log::debug('Trace ID', ['trace_id' => $traceId]);
          return $next($request);
      }
      
  3. Validate Exporter:

    • Test exporters independently (e.g., curl to OTLP endpoint):
      curl -X POST http://localhost:4318/v1/traces -H "Content-Type: application/json" -d '{}'
      
    • For Jaeger, check if traces appear at http://localhost:16686.
  4. Sampling Issues:

    • If traces are missing, verify sampling rate and parent-based sampling:
      'sampling' => [
          'rate' => 1.0, // Force 100% sampling for debugging
      ],
      

Extension Points

  1. Custom Spans:

    • Extend the tracer to add domain-specific spans:
      OpenTelemetry::tracer()->startSpan('custom-event', [
          'attribute.key' => 'value',
      ]);
      
  2. Exporter Plugins:

    • Add support for custom exporters by implementing Spatie\OpenTelemetry\Contracts\Exporter:
      class CustomExporter implements Exporter
      {
          public function export(array $spans): void
          {
              // Custom logic (e.g., send to Datadog, New Relic)
          }
      }
      
    • Register in config/open-telemetry.php:
      'exporters' => [
          'custom' => \App\Exporters\CustomExporter::class,
      ],
      
  3. Middleware Hooks:

    • Extend TraceRequests to add custom attributes:
      public function handle($request, Closure $next)
      {
          $span = OpenTelemetry::tracer()->startSpan('http-request');
          $span->setAttribute('http.method', $request->method());
          $span->setAttribute('http.path', $request->
      
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport