Skip to content

[opentelemetry-php-contrib] Laravel: Termination phase of request handling not part of root-span #1701

@Thomas-Vos00

Description

@Thomas-Vos00

Describe your environment:
Relevant environment settings:

  • open-telemetry/opentelemetry-auto-laravel: 1.2.2

  • laravel/octane: v2.5.1

  • laravel/framework: v11.45.1

  • The issue is in the contrib package; so all Laravel versions are affected.

  • Deployment: Both standard PHP-FPM and Laravel Octane deployments are affected

Steps to reproduce

  1. Set up Laravel application with OpenTelemetry auto-instrumentation enabled
  2. Create terminable middleware that performs database operations or other traced operations:
class ExampleTerminableMiddleware
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
    
    public function terminate($request, $response)
    {
        // This database query will not have correct trace parent
        User::count(); // or any other database operation
    }
}
  1. Register the middleware and make a request to trigger it
  2. Observe the generated traces

What is the expected behavior?
Database queries and other instrumented operations executed during request termination (e.g., in terminable middleware's terminate method) should be part of the same trace as the main request, with proper parent-child span relationships.

What is the actual behavior?
Spans generated during request termination appear as root spans without the correct trace parent, breaking the trace continuity. This happens because the current auto-instrumentation only hooks into the HttpKernel's handle method in open-telemetry/opentelemetry-auto-laravel/src/Hooks/Illuminate/Contracts/Http/Kernel.php, but doesn't encompass the kernel's termination phase.

Additional context
The issue stems from Laravel's request lifecycle having two phases:

  1. Handle phase: Processing the request and generating response (currently instrumented)
  2. Termination phase: Running terminable middleware & other terminations after response is sent (not instrumented)

The challenge is that the ideal hook point varies by deployment method:

Simply hooking the kernel's handle method misses the termination phase in both deployment scenarios. A solution would need to either:

  1. Hook into the termination phase separately while maintaining trace context

  2. Hook at the application level differently for each deployment type

  3. Find a unified hook point that covers the complete request lifecycle across deployments (I didn't find one)

This affects observability for applications using terminable middleware for logging, cleanup tasks, or background job dispatching.

Tip: React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions