diff --git a/sentry-ruby/lib/sentry/rack/capture_exceptions.rb b/sentry-ruby/lib/sentry/rack/capture_exceptions.rb index a97f93079..78378942e 100644 --- a/sentry-ruby/lib/sentry/rack/capture_exceptions.rb +++ b/sentry-ruby/lib/sentry/rack/capture_exceptions.rb @@ -135,6 +135,7 @@ def extract_queue_time(env) # Parses X-Request-Start header value to extract a timestamp. # Supports multiple formats: # - Nginx: "t=1234567890.123" (seconds with decimal) + # - Render: "t=1234567890123456789" (nanoseconds) # - Heroku, HAProxy 1.9+: "t=1234567890123456" (microseconds) # - HAProxy < 1.9: "t=1234567890" (seconds) # - Generic: "1234567890.123" (raw timestamp) @@ -158,9 +159,12 @@ def parse_request_start_header(header_value) return end - # normalize: timestamps can be in seconds, milliseconds or microseconds - # any timestamp > 10 trillion = microseconds - if timestamp > 10_000_000_000_000 + # normalize: timestamps can be in seconds, milliseconds, microseconds or nanoseconds + # any timestamp > 10 quadrillion = nanoseconds + if timestamp > 10_000_000_000_000_000 + timestamp / 1_000_000_000.0 + # timestamp > 10 trillion & < 10 quadrillion = microseconds + elsif timestamp > 10_000_000_000_000 timestamp / 1_000_000.0 # timestamp > 10 billion & < 10 trillion = milliseconds elsif timestamp > 10_000_000_000 diff --git a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb index 8a037595b..d716ed610 100644 --- a/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb +++ b/sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb @@ -738,6 +738,18 @@ def will_be_sampled_by_sdk expect(queue_time).to be_within(10).of(30) end end + + it "handles Render nanosecond timestamp format" do + Timecop.freeze do + timestamp_ns = ((Time.now.to_f - 0.03) * 1_000_000_000).to_i + env["HTTP_X_REQUEST_START"] = "t=#{timestamp_ns}" + + stack.call(env) + + queue_time = transaction.contexts.dig(:trace, :data, 'http.server.request.time_in_queue') + expect(queue_time).to be_within(10).of(30) + end + end end context "without X-Request-Start header" do