Skip to content

Commit b465762

Browse files
committed
Gracefully handle "sentry-trace" headers that don't match the regexp
Fixes the handling of invalid "sentry-trace" header values, such as "null". Related error backtrace: Rack app error handling request { POST /graphql } .../sentry-ruby-core-4.1.6/lib/sentry/transaction.rb:32:in `from_sentry_trace' .../sentry-ruby-core-4.1.6/lib/sentry/rack/capture_exceptions.rb:21:in `block in call' .../sentry-ruby-core-4.1.6/lib/sentry/hub.rb:52:in `with_scope' .../sentry-ruby-core-4.1.6/lib/sentry-ruby.rb:149:in `with_scope' .../sentry-ruby-core-4.1.6/lib/sentry/rack/capture_exceptions.rb:14:in `call'
1 parent db7be87 commit b465762

5 files changed

Lines changed: 28 additions & 6 deletions

File tree

sentry-ruby/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ end
3333

3434
- Inspect exception cause by default & don't exclude ActiveJob::DeserializationError [#1180](https://github.com/getsentry/sentry-ruby/pull/1180)
3535
- Fixes [#1071](https://github.com/getsentry/sentry-ruby/issues/1071)
36+
- Ignore invalid values for sentry-trace header that don't match the required format [#1265](https://github.com/getsentry/sentry-ruby/pull/1265)
37+
- Correctly call sampled state initialization logic when capturing sentry-trace [#1265](https://github.com/getsentry/sentry-ruby/pull/1265)
38+
- Previously the span's sampled state was always set to nil when the sentry-trace header was set,
39+
which caused child spans to not be reported
3640

3741
## 4.1.6
3842

sentry-ruby/lib/sentry/rack/capture_exceptions.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ def call(env)
1616
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
1717
scope.set_rack_env(env)
1818

19-
span =
20-
if sentry_trace = env["HTTP_SENTRY_TRACE"]
21-
Sentry::Transaction.from_sentry_trace(sentry_trace, name: scope.transaction_name, op: transaction_op)
22-
else
23-
Sentry.start_transaction(name: scope.transaction_name, op: transaction_op)
24-
end
19+
sentry_trace = env["HTTP_SENTRY_TRACE"]
20+
span = Sentry::Transaction.from_sentry_trace(sentry_trace, name: scope.transaction_name, op: transaction_op) if sentry_trace
21+
span ||= Sentry.start_transaction(name: scope.transaction_name, op: transaction_op)
2522

2623
scope.set_span(span)
2724

sentry-ruby/lib/sentry/transaction.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def self.from_sentry_trace(sentry_trace, **options)
2929
return unless sentry_trace
3030

3131
match = SENTRY_TRACE_REGEXP.match(sentry_trace)
32+
return if match.nil?
3233
trace_id, parent_span_id, sampled_flag = match[1..3]
3334

3435
sampled = sampled_flag != "0"

sentry-ruby/spec/sentry/rack/capture_exceptions_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,20 @@
194194
expect(transaction.contexts.dig(:trace, :parent_span_id)).to eq(external_transaction.span_id)
195195
expect(transaction.contexts.dig(:trace, :span_id)).not_to eq(external_transaction.span_id)
196196
end
197+
198+
it "safely handles bugus header values" do
199+
env["HTTP_SENTRY_TRACE"] = 'null'
200+
201+
stack.call(env)
202+
203+
# creates a new transaction
204+
transaction = transport.events.last
205+
expect(transaction.type).to eq("transaction")
206+
expect(transaction.timestamp).not_to be_nil
207+
expect(transaction.contexts.dig(:trace, :status)).to eq("ok")
208+
expect(transaction.contexts.dig(:trace, :op)).to eq("rack.request")
209+
expect(transaction.spans.count).to eq(0)
210+
end
197211
end
198212

199213
context "when the transaction is sampled" do

sentry-ruby/spec/sentry/transaction_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
expect(child_transaction.parent_sampled).to eq(true)
2424
expect(child_transaction.op).to eq("child")
2525
end
26+
27+
it "handles invalid values without crashing" do
28+
child_transaction = described_class.from_sentry_trace("dummy", op: "child")
29+
30+
expect(child_transaction).to be_nil
31+
end
2632
end
2733

2834
describe "#deep_dup" do

0 commit comments

Comments
 (0)