Plack-Middleware-OpenTelemetry

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

0.262410 -- Fri Aug 28 21:28:30 PDT 2026
  - Fix context propagation for streaming responses (thanks @abraxxa)
  - Remove duplicate repository URL from the distribution metadata
    (thanks @abraxxa)

0.252280 -- Fri Aug 15 23:49:53 -04 2025
  - Lower minimum Perl version requirement from 5.36 to 5.30
  - Improve documentation

0.252270 -- Thu Aug 14 23:22:12 -04 2025
  - Fix variable shadowing bug in resource creation (thanks @abraxxa)
  - Ensure Plack is loaded for resource version data (José Joaquín Atria)

lib/Plack/Middleware/OpenTelemetry.pm  view on Meta::CPAN

The middleware automatically:

=over

=item * Creates OpenTelemetry spans for HTTP requests

=item * Extracts W3C trace context from incoming requests

=item * Sets standard HTTP semantic attributes following OpenTelemetry conventions

=item * Handles both synchronous and streaming responses

=item * Records exceptions and sets appropriate span status

=back

The following HTTP attributes are set on spans:

=over

=item * C<http.request.method> - HTTP method

t/otel_integration.t  view on Meta::CPAN

            my $path = $env->{PATH_INFO} || '/';
            
            if ($path eq '/success') {
                return [200, ['Content-Type' => 'text/plain'], ['OK']];
            } elsif ($path eq '/not_found') {
                return [404, ['Content-Type' => 'text/plain'], ['Not Found']];
            } elsif ($path eq '/server_error') {
                return [500, ['Content-Type' => 'text/plain'], ['Server Error']];
            } elsif ($path eq '/exception') {
                die "Test exception message";
            } elsif ($path eq '/streaming') {
                return sub {
                    my $respond = shift;
                    my $writer = $respond->([200, ['Content-Type' => 'text/plain']]);
                    $writer->write("chunk1");
                    $writer->write("chunk2");
                    $writer->close;
                };
            } else {
                return [200, ['Content-Type' => 'text/plain'], ['Default']];
            }

t/otel_integration.t  view on Meta::CPAN

    };
    
    my $span = parse_console_span($span_output);
    is $span->{status}{code}, SPAN_STATUS_ERROR, 'Exception marked span as error';
    is $span->{attributes}->{'http.response.status_code'}, 500, 'Exception sets 500 status';
    
    # Check if exception was recorded
    ok $span->{events} && @{$span->{events}}, 'Exception events recorded';
};

# Test streaming responses
subtest 'Streaming Response' => sub {
    my $app = build_app();
    
    my $span_output = capture_stderr {
        test_psgi $app, sub {
            my $cb = shift;
            my $res = $cb->(GET 'http://example.com/streaming');
            is $res->code, 200;
            is $res->content, 'chunk1chunk2', 'Streaming content received';
        };
    };
    
    # For streaming responses, multiple spans might be output or format might differ
    # Just verify we captured some span output
    ok $span_output, 'Span output captured for streaming response';
    like $span_output, qr/streaming|GET request/, 'Span output contains expected content';
};

# Test resource attributes
subtest 'Resource Attributes' => sub {
    my $app = build_app(
        resource_attributes => {
            'service.name' => 'test-service',
            'service.version' => '1.0.0'
        }
    );



( run in 1.737 second using v1.01-cache-2.11-cpan-6736b670a1e )