Skip to content

Conversation

@Arunodoy18
Copy link

After upgrading to Dropwizard 5 (which uses Jetty 12), HTTP server metrics were not being collected or exposed correctly when virtual threads were disabled (enableVirtualThreads=false). The metrics appeared correctly only when virtual threads were enabled.

Root Cause:
The Jetty12ServerInstrumentation was ending spans in two places:

  1. In onMethodExit when the handle() method completed
  2. In HttpStream callbacks (succeeded/failed) for request completion

When virtual threads were disabled, handle() often completed synchronously BEFORE the HttpStream callbacks fired. This caused the span to end prematurely in onMethodExit, and metrics were not properly captured. The HttpStream callbacks would then try to end an already-ended span.

When virtual threads were enabled, the asynchronous nature ensured callbacks fired before method exit, so metrics were captured correctly.

Solution:

  1. Modified Jetty12ServerInstrumentation.HandlerAdvice.end() to NOT end the span in onMethodExit (except when there's an exception). The span is now ended exclusively by the HttpStream completion callbacks.

  2. Added AtomicBoolean in Jetty12Helper.start() to ensure the span ends exactly once, preventing double-ending issues regardless of callback order.

This ensures HTTP metrics (request counts, latency, body size, per-endpoint and per-status-code metrics) are collected correctly whether virtual threads are enabled or disabled.

Fixes the issue where Dropwizard 5 applications with enableVirtualThreads=false would not report HTTP server metrics.

After upgrading to Dropwizard 5 (which uses Jetty 12), HTTP server metrics
were not being collected or exposed correctly when virtual threads were
disabled (enableVirtualThreads=false). The metrics appeared correctly only
when virtual threads were enabled.

Root Cause:
The Jetty12ServerInstrumentation was ending spans in two places:
1. In onMethodExit when the handle() method completed
2. In HttpStream callbacks (succeeded/failed) for request completion

When virtual threads were disabled, handle() often completed synchronously
BEFORE the HttpStream callbacks fired. This caused the span to end prematurely
in onMethodExit, and metrics were not properly captured. The HttpStream
callbacks would then try to end an already-ended span.

When virtual threads were enabled, the asynchronous nature ensured callbacks
fired before method exit, so metrics were captured correctly.

Solution:
1. Modified Jetty12ServerInstrumentation.HandlerAdvice.end() to NOT end the
   span in onMethodExit (except when there's an exception). The span is now
   ended exclusively by the HttpStream completion callbacks.

2. Added AtomicBoolean in Jetty12Helper.start() to ensure the span ends
   exactly once, preventing double-ending issues regardless of callback order.

This ensures HTTP metrics (request counts, latency, body size, per-endpoint
and per-status-code metrics) are collected correctly whether virtual threads
are enabled or disabled.

Fixes the issue where Dropwizard 5 applications with enableVirtualThreads=false
would not report HTTP server metrics.
@Arunodoy18 Arunodoy18 requested a review from a team as a code owner December 7, 2025 21:27
Copy link
Member

@jaydeluca jaydeluca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please include tests for this change

@laurit laurit added the needs author feedback Waiting for additional feedback from the author label Dec 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs author feedback Waiting for additional feedback from the author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants