From e23404577e1122e7ff648438903c472aae94cb8f Mon Sep 17 00:00:00 2001 From: Tobias Schmidt Date: Thu, 7 Aug 2025 13:30:17 +0200 Subject: [PATCH] fix(trace): Correctly normalize inconsistent ActiveSupport timestamps The `normalize_time` method in the google-cloud-trace library produced incorrect timestamps when used with certain versions of Rails 7 and with Rails 8. Because this change was not consistent across all versions and was altered silently (e.g., https://github.com/rails/rails/pull/50779), a simple version check is unreliable. The previous implementation incorrectly assumed any numeric timestamp was in milliseconds, causing faulty time conversions and leading to trace spans being dropped by the API. It now uses a numeric threshold to reliably differentiate between timestamps in seconds and milliseconds, ensuring correct handling regardless of the specific Rails version. Fixes #30798. --- .../lib/google/cloud/trace/notifications.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/google-cloud-trace/lib/google/cloud/trace/notifications.rb b/google-cloud-trace/lib/google/cloud/trace/notifications.rb index 236f8f088ff7..556ad637f238 100644 --- a/google-cloud-trace/lib/google/cloud/trace/notifications.rb +++ b/google-cloud-trace/lib/google/cloud/trace/notifications.rb @@ -110,17 +110,19 @@ def self.payload_to_labels event, maxlen, label_namespace labels end + TIMESTAMP_SECONDS_THRESHOLD = (2**31) - 1 + ## # @private # - # active support event's time is: - # - # - rails >= 7: timestamp in milliseconds - # - rails < 7: time + # Normalizes potentially inconsistent timestamps from + # ActiveSupport::Notifications into a consistent format in seconds since + # the Unix epoch. Some older Rails versions passed `Time` objects, while + # some versions of Rails 7+ passes a `Float` in milliseconds. def self.normalize_time time_or_float - return time_or_float if Rails::VERSION::MAJOR < 7 + return time_or_float unless time_or_float.is_a? Numeric - Time.at time_or_float / 1000 + time_or_float > TIMESTAMP_SECONDS_THRESHOLD ? time_or_float / 1000.0 : time_or_float end end end