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

Context Laravel Package

open-telemetry/context

OpenTelemetry Context for PHP: immutable execution-scoped context propagation. Activate a context to create a scope and safely detach it (try/finally). Includes debug scope warnings, and optional async support for fibers and event loops.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require open-telemetry/context
    
  2. Activate a context (e.g., in a middleware or service):

    use OpenTelemetry\Context\Context;
    use OpenTelemetry\Context\Scope;
    
    $scope = Context::getCurrent()->activate();
    try {
        // Execute code within the new context
        $this->processRequest();
    } finally {
        $scope->detach(); // Critical: Restore previous context
    }
    
  3. First use case: Instrument a Laravel HTTP request to propagate trace context:

    // In App\Http\Middleware\TraceMiddleware
    public function handle($request, Closure $next) {
        $scope = Context::getCurrent()->activate();
        try {
            return $next($request);
        } finally {
            $scope->detach();
        }
    }
    

Key Entry Points

  • Context::getCurrent(): Retrieve the current execution context.
  • ->activate(): Create a scope to run code in a new context.
  • Scope::detach(): Restore the previous context (use try/finally).
  • Debug scopes: Automatically warn about missing detach() calls in non-production.

Laravel-Specific Quickstart

  1. Add to composer.json (as above).
  2. Create a base service to wrap context activation:
    // app/Services/ObservabilityService.php
    namespace App\Services;
    
    use OpenTelemetry\Context\Context;
    use OpenTelemetry\Context\Scope;
    
    class ObservabilityService {
        public function withContext(callable $callback): mixed {
            $scope = Context::getCurrent()->activate();
            try {
                return $callback();
            } finally {
                $scope->detach();
            }
        }
    }
    
  3. Use in controllers:
    $observability = app(ObservabilityService::class);
    return $observability->withContext(function() {
        // Context is active here
        return response()->json(['data' => '...']);
    });
    

Implementation Patterns

Core Workflows

1. Request-Scoped Context Propagation

  • Pattern: Use middleware to activate a context for the entire HTTP request lifecycle.
  • Example:
    // app/Http/Middleware/TraceContext.php
    public function handle($request, Closure $next) {
        $context = Context::getCurrent()->withBaggage([
            'http.request_id' => $request->header('X-Request-ID'),
            'user.id' => auth()->id(),
        ]);
        $scope = $context->activate();
        try {
            return $next($request);
        } finally {
            $scope->detach();
        }
    }
    
  • Why: Ensures trace IDs and baggage (e.g., user.id) propagate through the request stack.

2. Queue Job Context Propagation

  • Pattern: Wrap queue job execution to preserve context across workers.
  • Example:
    // app/Jobs/ProcessOrder.php
    public function handle() {
        $observability = app(ObservabilityService::class);
        $observability->withContext(function() {
            // Context includes trace ID from the original HTTP request
            $this->processOrderLogic();
        });
    }
    
  • Laravel Tip: Use dispatchSync with context activation for synchronous job workflows.

3. Async/Fiber Context Propagation

  • Pattern: Enable fiber support for automatic context propagation.
  • Steps:
    1. Set environment variable:
      export OTEL_PHP_FIBERS_ENABLED=true
      
    2. Preload autoloader for non-CLI SAPIs (if ffi.enable=preload).
    3. Use fibers with context:
      $fiber = new Fiber(function() {
          // Context is automatically propagated
          $traceId = Context::getCurrent()->getBaggage()->get('trace_id');
          // ...
      });
      $fiber->start();
      
  • Event Loop Integration: Use the bindContext pattern for custom event loops (e.g., ReactPHP):
    $loop = React\EventLoop\Factory::create();
    $loop->addPeriodicTimer(1, $observability->bindContext(function() {
        // Context is restored for each callback
    }));
    

4. Service-to-Service Context Propagation

  • Pattern: Inject context into HTTP clients (e.g., Guzzle) for outbound requests.
  • Example:
    use OpenTelemetry\Context\Propagation\TextMapPropagator;
    
    $propagator = new TextMapPropagator();
    $context = Context::getCurrent();
    $headers = $propagator->extract($context, new ArrayAccessHeaderProvider($request->headers));
    $client = new GuzzleHttp\Client();
    $response = $client->request('GET', 'https://api.example.com', [
        'headers' => $headers,
    ]);
    

Integration Tips

Laravel-Specific Integrations

  1. Service Container Binding: Bind the ObservabilityService globally:
    // config/app.php
    'bindings' => [
        ObservabilityService::class => function($app) {
            return new ObservabilityService();
        },
    ];
    
  2. Artisan Commands: Activate context for CLI commands:
    // app/Console/Commands/ProcessPayments.php
    protected function handle() {
        $observability = app(ObservabilityService::class);
        $observability->withContext(function() {
            // Context includes trace ID from parent process
            $this->processPayments();
        });
    }
    
  3. Database Logging: Attach trace IDs to database queries via Eloquent observers:
    // app/Observers/OrderObserver.php
    public function saving(Order $order) {
        $traceId = Context::getCurrent()->getBaggage()->get('trace_id');
        $order->trace_id = $traceId;
    }
    

OpenTelemetry SDK Integration

  1. Link Context to Traces:
    use OpenTelemetry\API\Trace\TracerInterface;
    
    $tracer = app(TracerInterface::class);
    $span = $tracer->spanBuilder('user_action')
        ->setAttribute('user.id', Context::getCurrent()->getBaggage()->get('user.id'))
        ->startSpan();
    
  2. Baggage Propagation: Use Context::getBaggage() to access metadata across services:
    $baggage = Context::getCurrent()->getBaggage();
    $tenantId = $baggage->get('tenant.id');
    

Testing

  • Mock Context: Use Context::withBaggage() in tests to simulate propagation:
    $context = Context::withBaggage(['test.key' => 'test.value']);
    $scope = $context->activate();
    try {
        $this->assertEquals('test.value', Context::getCurrent()->getBaggage()->get('test.key'));
    } finally {
        $scope->detach();
    }
    
  • Assert Scope Detachment: Verify detach() is called in tests:
    $this->expectException(InvalidArgumentException::class);
    $scope = Context::getCurrent()->activate();
    // Intentionally skip detach() to trigger debug warning
    

Gotchas and Tips

Pitfalls

  1. Forgetting detach():

    • Issue: Leaks memory or corrupts context if detach() is omitted.
    • Fix: Always use try/finally:
      $scope = Context::getCurrent()->activate();
      try {
          // ...
      } finally {
          $scope->detach(); // Non-negotiable
      }
      
    • Debugging: Enable debug scopes (default in non-production) to catch missing detach().
  2. Async Context Leaks:

    • Issue: Fibers or event loop callbacks may not restore context properly.
    • Fix: Use bindContext or ensure detach() is called in finally blocks.
    • Example:
      // Bad: Missing detach in callback
      $loop->addTimer(1, function() {
          $scope = Context::getCurrent()->activate();
          // ... no detach!
      });
      
      // Good: Wrapped in bindContext
      $loop->addTimer(1, $observability->bindContext(function() {
          // Context is auto-restored
      }));
      
  3. Fiber Support Requirements:

    • Issue: Fiber context propagation fails if:
      • OTEL_PHP_FIBERS_ENABLED is not set.
      • ext-ffi is missing or misconfigured.
      • Autoloader is not preloaded for non-CLI SAPIs.
    • Fix: Verify environment and PHP extensions:
      php -m | grep ffi  # Check FFI extension
      php -r 'echo getenv("OT
      
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