Skip to content

Commit c317a7a

Browse files
authored
Add span and trace origins (#2319)
* Add :origin attribute to span and use in trace context and span hash * Add origin to Rack::CaptureExceptions * Add origin to Net::HTTP * Add origin to Redis * Add origin to Metrics * Add origin to DelayedJob * Add origin to OpenTelemetry * Add origin to Resque * Add origin to Sidekiq * Add origin to Rails
1 parent bcf8827 commit c317a7a

34 files changed

+182
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
- Fixes [#2297](https://github.com/getsentry/sentry-ruby/issues/2297)
3232
- Don't mutate `enabled_environments` when using `Sentry::TestHelper` ([#2317](https://github.com/getsentry/sentry-ruby/pull/2317))
3333

34+
### Internal
35+
36+
- Add `origin` to spans and transactions to track integration sources for instrumentation ([#2319](https://github.com/getsentry/sentry-ruby/pull/2319))
37+
3438
## 5.17.3
3539

3640
### Internal

sentry-delayed_job/lib/sentry/delayed_job/plugin.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class Plugin < ::Delayed::Plugin
88
# need to symbolize strings as keyword arguments in Ruby 2.4~2.6
99
DELAYED_JOB_CONTEXT_KEY = :"Delayed-Job"
1010
ACTIVE_JOB_CONTEXT_KEY = :"Active-Job"
11-
OP_NAME = "queue.delayed_job".freeze
11+
OP_NAME = "queue.delayed_job"
12+
SPAN_ORIGIN = "auto.queue.delayed_job"
1213

1314
callbacks do |lifecycle|
1415
lifecycle.before(:enqueue) do |job, *args, &block|
@@ -93,7 +94,13 @@ def self.report?(job)
9394
end
9495

9596
def self.start_transaction(scope, env, contexts)
96-
options = { name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME }
97+
options = {
98+
name: scope.transaction_name,
99+
source: scope.transaction_source,
100+
op: OP_NAME,
101+
origin: SPAN_ORIGIN
102+
}
103+
97104
transaction = Sentry.continue_trace(env, **options)
98105
Sentry.start_transaction(transaction: transaction, custom_sampling_context: contexts, **options)
99106
end

sentry-delayed_job/spec/sentry/delayed_job_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ def perform
383383
expect(transaction.contexts.dig(:trace, :span_id)).to be_a(String)
384384
expect(transaction.contexts.dig(:trace, :status)).to eq("ok")
385385
expect(transaction.contexts.dig(:trace, :op)).to eq("queue.delayed_job")
386+
expect(transaction.contexts.dig(:trace, :origin)).to eq("auto.queue.delayed_job")
386387
end
387388

388389
it "records transaction with exception" do

sentry-opentelemetry/lib/sentry/opentelemetry/span_processor.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class SpanProcessor < ::OpenTelemetry::SDK::Trace::SpanProcessor
1111

1212
SEMANTIC_CONVENTIONS = ::OpenTelemetry::SemanticConventions::Trace
1313
INTERNAL_SPAN_KINDS = %i[client internal]
14+
SPAN_ORIGIN = "auto.otel"
1415

1516
# The mapping from otel span ids to sentry spans
1617
# @return [Hash]
@@ -34,7 +35,8 @@ def on_start(otel_span, parent_context)
3435
sentry_parent_span.start_child(
3536
span_id: trace_data.span_id,
3637
description: otel_span.name,
37-
start_timestamp: otel_span.start_timestamp / 1e9
38+
start_timestamp: otel_span.start_timestamp / 1e9,
39+
origin: SPAN_ORIGIN
3840
)
3941
else
4042
options = {
@@ -45,7 +47,8 @@ def on_start(otel_span, parent_context)
4547
parent_span_id: trace_data.parent_span_id,
4648
parent_sampled: trace_data.parent_sampled,
4749
baggage: trace_data.baggage,
48-
start_timestamp: otel_span.start_timestamp / 1e9
50+
start_timestamp: otel_span.start_timestamp / 1e9,
51+
origin: SPAN_ORIGIN
4952
}
5053

5154
Sentry.start_transaction(**options)

sentry-opentelemetry/spec/sentry/opentelemetry/span_processor_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
expect(event.contexts).to include(:trace)
9393
expect(event.contexts[:trace][:trace_id]).to eq(root_span.context.hex_trace_id)
9494
expect(event.contexts[:trace][:span_id]).to eq(root_span.context.hex_span_id)
95+
expect(event.contexts[:trace][:origin]).to eq('auto.otel')
9596
end
9697
end
9798
end
@@ -134,6 +135,7 @@
134135
expect(transaction.span_id).to eq(span_id)
135136
expect(transaction.trace_id).to eq(trace_id)
136137
expect(transaction.start_timestamp).to eq(root_span.start_timestamp / 1e9)
138+
expect(transaction.origin).to eq('auto.otel')
137139

138140
expect(transaction.parent_span_id).to eq(nil)
139141
expect(transaction.parent_sampled).to eq(nil)
@@ -168,6 +170,7 @@
168170
expect(sentry_span.trace_id).to eq(trace_id)
169171
expect(sentry_span.description).to eq(child_db_span.name)
170172
expect(sentry_span.start_timestamp).to eq(child_db_span.start_timestamp / 1e9)
173+
expect(sentry_span.origin).to eq('auto.otel')
171174
end
172175
end
173176
end
@@ -215,6 +218,7 @@
215218
subject.on_finish(finished_db_span)
216219

217220
expect(sentry_span.op).to eq('db')
221+
expect(sentry_span.origin).to eq('auto.otel')
218222
expect(sentry_span.description).to eq(finished_db_span.attributes['db.statement'])
219223
expect(sentry_span.data).to include(finished_db_span.attributes)
220224
expect(sentry_span.data).to include({ 'otel.kind' => finished_db_span.kind })
@@ -235,6 +239,7 @@
235239
subject.on_finish(finished_http_span)
236240

237241
expect(sentry_span.op).to eq('http.client')
242+
expect(sentry_span.origin).to eq('auto.otel')
238243
expect(sentry_span.description).to eq('GET www.google.com/search')
239244
expect(sentry_span.data).to include(finished_http_span.attributes)
240245
expect(sentry_span.data).to include({ 'otel.kind' => finished_http_span.kind })
@@ -259,6 +264,7 @@
259264
subject.on_finish(finished_root_span)
260265

261266
expect(transaction.op).to eq('http.server')
267+
expect(transaction.origin).to eq('auto.otel')
262268
expect(transaction.name).to eq(finished_root_span.name)
263269
expect(transaction.status).to eq('ok')
264270
expect(transaction.contexts[:otel]).to eq({

sentry-rails/lib/sentry/rails/action_cable.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Rails
33
module ActionCableExtensions
44
class ErrorHandler
55
OP_NAME = "websocket.server".freeze
6+
SPAN_ORIGIN = "auto.http.rails.actioncable"
67

78
class << self
89
def capture(connection, transaction_name:, extra_context: nil, &block)
@@ -33,7 +34,13 @@ def capture(connection, transaction_name:, extra_context: nil, &block)
3334
end
3435

3536
def start_transaction(env, scope)
36-
options = { name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME }
37+
options = {
38+
name: scope.transaction_name,
39+
source: scope.transaction_source,
40+
op: OP_NAME,
41+
origin: SPAN_ORIGIN
42+
}
43+
3744
transaction = Sentry.continue_trace(env, **options)
3845
Sentry.start_transaction(transaction: transaction, **options)
3946
end

sentry-rails/lib/sentry/rails/active_job.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def already_supported_by_sentry_integration?
1717

1818
class SentryReporter
1919
OP_NAME = "queue.active_job".freeze
20+
SPAN_ORIGIN = "auto.queue.active_job".freeze
2021

2122
class << self
2223
def record(job, &block)
@@ -27,7 +28,12 @@ def record(job, &block)
2728
if job.is_a?(::Sentry::SendEventJob)
2829
nil
2930
else
30-
Sentry.start_transaction(name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME)
31+
Sentry.start_transaction(
32+
name: scope.transaction_name,
33+
source: scope.transaction_source,
34+
op: OP_NAME,
35+
origin: SPAN_ORIGIN
36+
)
3137
end
3238

3339
scope.set_span(transaction) if transaction

sentry-rails/lib/sentry/rails/capture_exceptions.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module Sentry
22
module Rails
33
class CaptureExceptions < Sentry::Rack::CaptureExceptions
44
RAILS_7_1 = Gem::Version.new(::Rails.version) >= Gem::Version.new("7.1.0.alpha")
5+
SPAN_ORIGIN = 'auto.http.rails'.freeze
56

67
def initialize(_)
78
super
@@ -32,7 +33,12 @@ def capture_exception(exception, env)
3233
end
3334

3435
def start_transaction(env, scope)
35-
options = { name: scope.transaction_name, source: scope.transaction_source, op: transaction_op }
36+
options = {
37+
name: scope.transaction_name,
38+
source: scope.transaction_source,
39+
op: transaction_op,
40+
origin: SPAN_ORIGIN
41+
}
3642

3743
if @assets_regexp && scope.transaction_name.match?(@assets_regexp)
3844
options.merge!(sampled: false)

sentry-rails/lib/sentry/rails/controller_transaction.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module Sentry
22
module Rails
33
module ControllerTransaction
4+
SPAN_ORIGIN = 'auto.view.rails'.freeze
5+
46
def self.included(base)
57
base.prepend_around_action(:sentry_around_action)
68
end
@@ -11,7 +13,7 @@ def sentry_around_action
1113
if Sentry.initialized?
1214
transaction_name = "#{self.class}##{action_name}"
1315
Sentry.get_current_scope.set_transaction_name(transaction_name, source: :view)
14-
Sentry.with_child_span(op: "view.process_action.action_controller", description: transaction_name) do |child_span|
16+
Sentry.with_child_span(op: "view.process_action.action_controller", description: transaction_name, origin: SPAN_ORIGIN) do |child_span|
1517
if child_span
1618
begin
1719
result = yield

sentry-rails/lib/sentry/rails/tracing/action_controller_subscriber.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class ActionControllerSubscriber < AbstractSubscriber
99

1010
EVENT_NAMES = ["process_action.action_controller"].freeze
1111
OP_NAME = "view.process_action.action_controller".freeze
12+
SPAN_ORIGIN = "auto.view.rails".freeze
1213

1314
def self.subscribe!
1415
Sentry.logger.warn <<~MSG
@@ -22,6 +23,7 @@ def self.subscribe!
2223

2324
record_on_current_span(
2425
op: OP_NAME,
26+
origin: SPAN_ORIGIN,
2527
start_timestamp: payload[START_TIMESTAMP_NAME],
2628
description: "#{controller}##{action}",
2729
duration: duration

0 commit comments

Comments
 (0)