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 for tracing/metrics. Activate contexts with scopes (try/finally detach), debug scope leak warnings, and optional async support via fibers and event-loop context binding.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require open-telemetry/context
    
  2. First use case: Propagate a trace context across a synchronous request flow (e.g., middleware → controller → service).

    use OpenTelemetry\Context\Context;
    use OpenTelemetry\Context\Scope;
    
    // In middleware or service entry point:
    $context = Context::getCurrent()->withBaggageItem('user_id', auth()->id());
    $scope = $context->activate();
    
    try {
        // Code here runs with the new context (e.g., HTTP client calls, DB queries).
        $response = Http::get('https://api.example.com/data');
    } finally {
        $scope->detach(); // Restore previous context.
    }
    
  3. Key files to reference:


Implementation Patterns

1. Middleware Integration (HTTP Context Propagation)

Use TextMapPropagator to inject/extract trace IDs from HTTP headers (e.g., traceparent).

use OpenTelemetry\Context\Propagation\TextMapPropagator;

// Extract context from incoming request (e.g., in Laravel middleware):
$propagator = new TextMapPropagator();
$carrier = new ArrayCarrier($_SERVER); // or $_GET, $_POST for query params
$context = $propagator->extract($carrier);
$scope = $context->activate();

try {
    // Request processing...
} finally {
    $scope->detach();
}

// Inject context into outgoing responses:
$carrier = new ArrayCarrier(['headers' => []]);
$propagator->inject($carrier, $context);

2. Service Layer Context Propagation

Pass context explicitly between services to correlate logs/traces:

class UserService {
    public function getUserData(int $userId, Context $context = null) {
        $context = $context ?? Context::getCurrent();
        $context = $context->withBaggageItem('user_id', $userId);
        $scope = $context->activate();

        try {
            // Business logic...
            return $this->repository->find($userId);
        } finally {
            $scope->detach();
        }
    }
}

3. Async Workflows (Fibers/Event Loops)

Fibers: Enable automatic propagation with:

export OTEL_PHP_FIBERS_ENABLED=true
// In a fiber-aware app:
$fiber = new Fiber(function () {
    $context = Context::getCurrent(); // Automatically propagated.
    // Fiber logic...
});
$fiber->start();

Event Loops: Use bindContext() to wrap callbacks:

use OpenTelemetry\Context\Context;

function bindContext(Closure $callback): Closure {
    return function (...$args) use ($callback) {
        $scope = Context::getCurrent()->activate();
        try {
            return $callback(...$args);
        } finally {
            $scope->detach();
        }
    };
}

// Usage with ReactPHP:
$loop->addPeriodicTimer(1, bindContext(function () {
    // Context is automatically restored.
}));

4. Queue Jobs (Laravel Queues)

Propagate context to async jobs using Context::getCurrent() in job payloads:

// Dispatch job with current context:
$job = new ProcessOrder($orderId);
$job->context = Context::getCurrent()->toBaggage(); // Serialize baggage.
dispatch($job);

// In job handle():
$context = Context::getCurrent()->withBaggageItems($this->context);
$scope = $context->activate();
try {
    // Job logic...
} finally {
    $scope->detach();
}

5. CLI/Artisan Commands

Ensure trace IDs persist across Artisan commands:

use OpenTelemetry\Context\Context;

Artisan::command('process:orders', function () {
    $scope = Context::getCurrent()->activate();
    try {
        // Command logic...
    } finally {
        $scope->detach();
    }
});

Gotchas and Tips

Pitfalls

  1. Forgetting detach():

    • Symptom: Debug scopes emit warnings in non-production (E_USER_NOTICE).
    • Fix: Always use try/finally or leverage Laravel’s ensure() helper:
      $scope = Context::getCurrent()->activate();
      ensure(function () use ($scope) { $scope->detach(); });
      
  2. Fiber Context Leaks:

    • Symptom: Fibers created without OTEL_PHP_FIBERS_ENABLED lose context.
    • Fix: Set OTEL_PHP_FIBERS_ENABLED=true and preload vendor/autoload.php for non-CLI SAPIs.
  3. Async Callback Context Loss:

    • Symptom: Event loop callbacks (e.g., ReactPHP) run without the expected context.
    • Fix: Wrap callbacks with bindContext() (see Implementation Patterns).
  4. Baggage Item Collisions:

    • Symptom: Overwriting baggage items (e.g., user_id) in nested scopes.
    • Fix: Use unique prefixes (e.g., auth.user_id) or merge contexts explicitly:
      $context = Context::getCurrent()->withBaggageItems([
          'auth.user_id' => $userId,
          'request.path' => request()->path(),
      ]);
      
  5. Debug Scopes in Production:

    • Symptom: E_USER_NOTICE warnings from undetached scopes in production.
    • Fix: Disable debug scopes via:
      export OTEL_PHP_DEBUG_SCOPES_DISABLED=true
      
      Warning: Only use this if your app avoids exit/die (e.g., Laravel’s graceful shutdown).

Debugging Tips

  1. Inspect Current Context:

    $context = Context::getCurrent();
    dump($context->getBaggage()->all()); // View all baggage items.
    
  2. Log Context Boundaries:

    $scope = Context::getCurrent()->activate();
    try {
        logger()->debug('Entering context scope', ['trace_id' => $context->getTraceId()]);
        // ...
    } finally {
        $scope->detach();
        logger()->debug('Exiting context scope');
    }
    
  3. Validate Propagation:

    • Use TextMapPropagator to verify headers are correctly injected/extracted:
      $propagator = new TextMapPropagator();
      $carrier = new ArrayCarrier(['headers' => $_SERVER['HTTP_HEADERS']]);
      $context = $propagator->extract($carrier);
      dump($context->getTraceId()); // Should match incoming request.
      
  4. Fiber Debugging:

    • Check if fibers propagate context:
      $fiber = new Fiber(function () {
          dump(Context::getCurrent()->getTraceId()); // Should match parent.
      });
      $fiber->start();
      

Extension Points

  1. Custom Propagators: Extend TextMapPropagator for non-HTTP carriers (e.g., gRPC metadata):

    class GrpcPropagator extends TextMapPropagator {
        public function inject(array &$metadata, Context $context): void {
            $carrier = new ArrayCarrier($metadata);
            parent::inject($carrier, $context);
        }
    }
    
  2. Context Storage Backends: Replace the default storage (e.g., for custom async workers):

    use OpenTelemetry\Context\ContextStorageInterface;
    
    class RedisContextStorage implements ContextStorageInterface {
        // Implement get/set logic using Redis.
    }
    
  3. Baggage Item Validation: Add middleware to validate baggage items (e.g., reject malformed trace IDs):

    $context = Context::getCurrent();
    if (!$context->getTraceId() || !preg_match('/^[a-f0-9]{32}$/', $context->getTraceId())) {
        throw new \RuntimeException('Invalid trace ID');
    }
    
  4. Laravel Service Provider Integration: Bootstrap context in register():

    public function register(): void {
        $this->app->singleton(ContextStorageInterface::class, function () {
            return new ContextStorage();
        });
    }
    

Performance Considerations

  1. **A
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
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
twbs/bootstrap4