Skip to content

Commit 789bcc1

Browse files
committed
feat(queues): improve core queue conformance
1 parent e3ade51 commit 789bcc1

10 files changed

Lines changed: 55 additions & 8 deletions

File tree

‎sentry-ruby/lib/sentry-ruby.rb‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
require "sentry/utils/logging_helper"
1313
require "sentry/utils/callback_helper"
1414
require "sentry/utils/sample_rand"
15+
require "sentry/utils/latency"
1516
require "sentry/configuration"
1617
require "sentry/structured_logger"
1718
require "sentry/debug_structured_logger"

‎sentry-ruby/lib/sentry/job_extensions/extension.rb‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ def extract_trace_headers(job:, payload:)
181181
# @return [Hash] a Hash with any of the keys +:system+ (a String naming
182182
# the backend), +:message_id+ (a String), +:destination+ (a String,
183183
# such as the queue name), +:receive_latency+ (a Numeric, the
184-
# milliseconds between enqueueing and the start of the job). The fallback result is an empty Hash.
184+
# milliseconds between enqueueing and the start of the job) and
185+
# +:body_size+ (a non-negative Integer, the size of the message body
186+
# in bytes). The fallback result is an empty Hash.
185187
def messaging_data(job:)
186188
{}
187189
end

‎sentry-ruby/lib/sentry/job_extensions/instrumentation.rb‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class Instrumentation
88
system: Span::DataConventions::MESSAGING_SYSTEM,
99
message_id: Span::DataConventions::MESSAGING_MESSAGE_ID,
1010
destination: Span::DataConventions::MESSAGING_DESTINATION_NAME,
11-
receive_latency: Span::DataConventions::MESSAGING_MESSAGE_RECEIVE_LATENCY
11+
receive_latency: Span::DataConventions::MESSAGING_MESSAGE_RECEIVE_LATENCY,
12+
body_size: Span::DataConventions::MESSAGING_MESSAGE_BODY_SIZE
1213
}.freeze
1314

1415
attr_reader :registry

‎sentry-ruby/lib/sentry/job_extensions/validators.rb‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class Validators
1414
system: ->(value) { value.is_a?(String) },
1515
message_id: ->(value) { value.is_a?(String) },
1616
destination: ->(value) { value.is_a?(String) },
17-
receive_latency: ->(value) { value.is_a?(Numeric) }
17+
receive_latency: ->(value) { value.is_a?(Numeric) },
18+
body_size: ->(value) { value.is_a?(Integer) && value >= 0 }
1819
}.freeze
1920

2021
def initialize(event_keys: EVENT_DATA_KEYS, scope_keys: SCOPE_DATA_KEYS, messaging_fields: MESSAGING_DATA_VALIDATORS)

‎sentry-ruby/lib/sentry/span.rb‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ module DataConventions
5050
MESSAGING_DESTINATION_NAME = "messaging.destination.name"
5151
MESSAGING_MESSAGE_RECEIVE_LATENCY = "messaging.message.receive.latency"
5252
MESSAGING_MESSAGE_RETRY_COUNT = "messaging.message.retry.count"
53+
MESSAGING_MESSAGE_BODY_SIZE = "messaging.message.body.size"
5354

5455
# Time in ms the request spent in the server queue before processing began.
5556
HTTP_QUEUE_TIME_MS = "http.server.request.time_in_queue"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# frozen_string_literal: true
2+
3+
require "time"
4+
5+
module Sentry
6+
module Utils
7+
module Latency
8+
module_function
9+
10+
def milliseconds_since(time)
11+
return unless time
12+
13+
time = Time.parse(time) if time.is_a?(String)
14+
(Time.now.to_f - time.to_f) * 1000.0
15+
end
16+
end
17+
end
18+
end

‎sentry-ruby/spec/sentry/job_extensions/consumer_spec.rb‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def capture(consumer, exception = RuntimeError.new("boom"), **options)
4848

4949
def enriching_consumer
5050
consumer(
51-
messaging_data: ->(job:) { { system: "backend", message_id: job.id, destination: job.queue, receive_latency: 42.5 } },
51+
messaging_data: ->(job:) { { system: "backend", message_id: job.id, destination: job.queue, receive_latency: 42.5, body_size: 128 } },
5252
retry_info: ->(job:) { { count: 3, will_retry: true } },
5353
scope_data: ->(job:) { { contexts: { backend: { "jid" => "backend-jid" } }, tags: { "backend.queue" => "low" }, extra: { size: 12 } } }
5454
)
@@ -112,6 +112,7 @@ def enriching_consumer
112112
"messaging.message.id" => "job-1",
113113
"messaging.destination.name" => "critical",
114114
"messaging.message.receive.latency" => 42.5,
115+
"messaging.message.body.size" => 128,
115116
"messaging.message.retry.count" => 3
116117
)
117118
end

‎sentry-ruby/spec/sentry/job_extensions/producer_spec.rb‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def producer(origin: nil, **hooks)
1818
def enriching_producer(origin: nil)
1919
producer(
2020
origin: origin,
21-
messaging_data: ->(job:) { { system: "backend", message_id: job.id, destination: job.queue, receive_latency: 42.5 } },
21+
messaging_data: ->(job:) { { system: "backend", message_id: job.id, destination: job.queue, receive_latency: 42.5, body_size: 128 } },
2222
retry_info: ->(job:) { { count: 3, will_retry: true } }
2323
)
2424
end
@@ -62,6 +62,7 @@ def record_span(producer, **options, &enqueue)
6262
"messaging.message.id" => "job-1",
6363
"messaging.destination.name" => "critical",
6464
"messaging.message.receive.latency" => 42.5,
65+
"messaging.message.body.size" => 128,
6566
"messaging.message.retry.count" => 3
6667
)
6768
end

‎sentry-ruby/spec/sentry/job_extensions_spec.rb‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,12 +418,12 @@ def messaging_data(job:)
418418
it "returns the messaging span data an extension derives from the job" do
419419
extension = build_hooked_extension(
420420
messaging_data: lambda do |job:|
421-
{ system: "sidekiq", message_id: job.jid, destination: job.queue, receive_latency: 1500 }
421+
{ system: "sidekiq", message_id: job.jid, destination: job.queue, receive_latency: 1500, body_size: 42 }
422422
end
423423
)
424424

425425
expect(call_hook(extension, :messaging_data))
426-
.to eq(system: "sidekiq", message_id: "abc123", destination: "default", receive_latency: 1500)
426+
.to eq(system: "sidekiq", message_id: "abc123", destination: "default", receive_latency: 1500, body_size: 42)
427427
end
428428

429429
it "returns the names an extension gives the job and the integration it captures errors under" do
@@ -525,7 +525,7 @@ def messaging_data(job:)
525525
inject_trace_headers: [nil, "payload"],
526526
extract_trace_headers: ["sentry-trace", [], { "sentry-trace" => 1 }, { sentry_trace: "trace" }],
527527
messaging_data: [nil, [], { system: :sidekiq }, { message_id: 1 }, { destination: nil },
528-
{ receive_latency: "fast" }],
528+
{ receive_latency: "fast" }, { body_size: -1 }, { body_size: 1.5 }, { body_size: "42" }],
529529
transaction_name: ["", :HardJob, 1],
530530
span_origin: ["", :"auto.queue.backend"],
531531
publish_description: ["", :HardJob],
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe Sentry::Utils::Latency do
4+
let(:started_at) { Time.utc(2026, 1, 1, 12, 0, 0) }
5+
6+
around do |example|
7+
Timecop.freeze(started_at + 2.5) { example.run }
8+
end
9+
10+
it "measures the milliseconds since a Time" do
11+
expect(described_class.milliseconds_since(started_at)).to eq(2_500.0)
12+
end
13+
14+
it "measures the milliseconds since an ISO 8601 String" do
15+
expect(described_class.milliseconds_since(started_at.iso8601(3))).to eq(2_500.0)
16+
end
17+
18+
it "measures nothing without a time" do
19+
expect(described_class.milliseconds_since(nil)).to be_nil
20+
end
21+
end

0 commit comments

Comments
 (0)