diff --git a/sentry-ruby/lib/sentry/hub.rb b/sentry-ruby/lib/sentry/hub.rb index 0efd00b3c..c9f95eefe 100644 --- a/sentry-ruby/lib/sentry/hub.rb +++ b/sentry-ruby/lib/sentry/hub.rb @@ -244,8 +244,6 @@ def get_baggage end def get_trace_propagation_headers - return nil unless configuration.propagate_traces - headers = {} traceparent = get_traceparent diff --git a/sentry-ruby/lib/sentry/net/http.rb b/sentry-ruby/lib/sentry/net/http.rb index 04eedb290..4b0345f52 100644 --- a/sentry-ruby/lib/sentry/net/http.rb +++ b/sentry-ruby/lib/sentry/net/http.rb @@ -32,7 +32,7 @@ def request(req, body = nil, &block) Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |sentry_span| request_info = extract_request_info(req) - if propagate_trace?(request_info[:url], Sentry.configuration.trace_propagation_targets) + if propagate_trace?(request_info[:url], Sentry.configuration) set_propagation_headers(req) end @@ -90,8 +90,10 @@ def extract_request_info(req) result end - def propagate_trace?(url, trace_propagation_targets) - url && trace_propagation_targets.any? { |target| url.match?(target) } + def propagate_trace?(url, configuration) + url && + configuration.propagate_traces && + configuration.trace_propagation_targets.any? { |target| url.match?(target) } end end end diff --git a/sentry-ruby/lib/sentry/propagation_context.rb b/sentry-ruby/lib/sentry/propagation_context.rb index 9bf163b72..aaaa3f69e 100644 --- a/sentry-ruby/lib/sentry/propagation_context.rb +++ b/sentry-ruby/lib/sentry/propagation_context.rb @@ -53,6 +53,10 @@ def get_dynamic_sampling_context get_baggage&.dynamic_sampling_context end + def deep_dup + dup + end + private def populate_head_baggage diff --git a/sentry-ruby/spec/sentry/event_spec.rb b/sentry-ruby/spec/sentry/event_spec.rb index cfa19b259..10c4b448c 100644 --- a/sentry-ruby/spec/sentry/event_spec.rb +++ b/sentry-ruby/spec/sentry/event_spec.rb @@ -30,6 +30,7 @@ expect(event.environment).to eq("test") expect(event.release).to eq("721e41770371db95eee98ca2707686226b993eda") expect(event.sdk).to eq("name" => "sentry.ruby", "version" => Sentry::VERSION) + expect(event.dynamic_sampling_context).to eq(nil) end end diff --git a/sentry-ruby/spec/sentry/net/http_spec.rb b/sentry-ruby/spec/sentry/net/http_spec.rb index 21eb96f7b..1e96f7feb 100644 --- a/sentry-ruby/spec/sentry/net/http_spec.rb +++ b/sentry-ruby/spec/sentry/net/http_spec.rb @@ -373,7 +373,20 @@ def verify_spans(transaction) perform_basic_setup end - it "doesn't affect the HTTP lib anything" do + it "adds sentry-trace and baggage headers for tracing without performance" do + stub_normal_response + + uri = URI("http://example.com/path") + http = Net::HTTP.new(uri.host, uri.port) + request = Net::HTTP::Get.new(uri.request_uri) + response = http.request(request) + + expect(request["sentry-trace"]).to eq(Sentry.get_traceparent) + expect(request["baggage"]).to eq(Sentry.get_baggage) + expect(response.code).to eq("200") + end + + it "doesn't create transaction or breadcrumbs" do stub_normal_response response = Net::HTTP.get_response(URI("http://example.com/path")) diff --git a/sentry-ruby/spec/sentry/scope_spec.rb b/sentry-ruby/spec/sentry/scope_spec.rb index 1e6d92426..3573e3a6e 100644 --- a/sentry-ruby/spec/sentry/scope_spec.rb +++ b/sentry-ruby/spec/sentry/scope_spec.rb @@ -24,6 +24,7 @@ expect(subject.fingerprint).to eq([]) expect(subject.transaction_names).to eq([]) expect(subject.transaction_sources).to eq([]) + expect(subject.propagation_context).to be_a(Sentry::PropagationContext) end it "allows setting breadcrumb buffer's size limit" do @@ -276,7 +277,7 @@ end end - it "sets trace context if there's a span" do + it "sets trace context from span if there's a span" do transaction = Sentry::Transaction.new(op: "foo", hub: hub) subject.set_span(transaction) @@ -286,6 +287,12 @@ expect(event.contexts.dig(:trace, :op)).to eq("foo") end + it "sets trace context and dynamic_sampling_context from propagation context if there's no span" do + subject.apply_to_event(event) + expect(event.contexts[:trace]).to eq(subject.propagation_context.get_trace_context) + expect(event.dynamic_sampling_context).to eq(subject.propagation_context.get_dynamic_sampling_context) + end + context "with Rack", rack: true do let(:env) do Rack::MockRequest.env_for("/test", {}) diff --git a/sentry-ruby/spec/sentry_spec.rb b/sentry-ruby/spec/sentry_spec.rb index 72fb18970..beb931131 100644 --- a/sentry-ruby/spec/sentry_spec.rb +++ b/sentry-ruby/spec/sentry_spec.rb @@ -667,6 +667,55 @@ end end + describe ".get_traceparent" do + it "returns a valid traceparent header from scope propagation context" do + traceparent = described_class.get_traceparent + propagation_context = described_class.get_current_scope.propagation_context + + expect(traceparent).to match(Sentry::Transaction::SENTRY_TRACE_REGEXP) + expect(traceparent).to eq("#{propagation_context.trace_id}-#{propagation_context.span_id}") + end + + it "returns a valid traceparent header from scope current span" do + transaction = Sentry::Transaction.new(op: "foo", hub: Sentry.get_current_hub, sampled: true) + span = transaction.start_child(op: "parent") + described_class.get_current_scope.set_span(span) + + traceparent = described_class.get_traceparent + + expect(traceparent).to match(Sentry::Transaction::SENTRY_TRACE_REGEXP) + expect(traceparent).to eq("#{span.trace_id}-#{span.span_id}-1") + end + end + + describe ".get_baggage" do + it "returns a valid baggage header from scope propagation context" do + baggage = described_class.get_baggage + propagation_context = described_class.get_current_scope.propagation_context + + expect(baggage).to eq("sentry-trace_id=#{propagation_context.trace_id},sentry-environment=development,sentry-public_key=12345") + end + + it "returns a valid baggage header from scope current span" do + transaction = Sentry::Transaction.new(op: "foo", hub: Sentry.get_current_hub, sampled: true) + span = transaction.start_child(op: "parent") + described_class.get_current_scope.set_span(span) + + baggage = described_class.get_baggage + + expect(baggage).to eq("sentry-trace_id=#{span.trace_id},sentry-sampled=true,sentry-environment=development,sentry-public_key=12345") + end + end + + describe ".get_trace_propagation_headers" do + it "returns a Hash of sentry-trace and baggage" do + expect(described_class.get_trace_propagation_headers).to eq({ + "sentry-trace" => described_class.get_traceparent, + "baggage" => described_class.get_baggage + }) + end + end + describe 'release detection' do let(:fake_root) { "/tmp/sentry/" }