-
-
Notifications
You must be signed in to change notification settings - Fork 504
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR is 1/2 to enable **Tracing without Performance**, i.e. make sure all our events are connected even if they are not Transactions. This enables use cases such as Errors / Transactions / Replays etc all being connected across services and not just Transactions. ### Summary of changes * new `PropagationContext` class that generates trace/span ids and baggage irrespective of whether there are transactions/spans active or not * this lives on the `Scope` * three new top level methods that first check the span and fallback on the scope's propagation context * `Sentry.get_traceparent` * `Sentry.get_baggage` * `Sentry.get_trace_propagation_headers` * move `dynamic_sampling_context` to `Event` from `TransactionEvent` since all events will now have this info * use the new top level helpers in `net/http` patch to set propagation headers closes #2056 also see #2089 --- This PR is 2/2 to enable Tracing without Performance, i.e. make sure all our events are connected even if they are not Transactions. ### Summary of changes * Implement new top level `Sentry.continue_trace(env, **options)` API that standardizes continuing an incoming trace from a rack env like hash. * Use this new API in rack/rails/sidekiq part of #2056 linked to #2084
- Loading branch information
1 parent
74103ea
commit 9641957
Showing
23 changed files
with
610 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
# frozen_string_literal: true | ||
|
||
require "securerandom" | ||
require "sentry/baggage" | ||
|
||
module Sentry | ||
class PropagationContext | ||
SENTRY_TRACE_REGEXP = Regexp.new( | ||
"^[ \t]*" + # whitespace | ||
"([0-9a-f]{32})?" + # trace_id | ||
"-?([0-9a-f]{16})?" + # span_id | ||
"-?([01])?" + # sampled | ||
"[ \t]*$" # whitespace | ||
) | ||
|
||
# An uuid that can be used to identify a trace. | ||
# @return [String] | ||
attr_reader :trace_id | ||
# An uuid that can be used to identify the span. | ||
# @return [String] | ||
attr_reader :span_id | ||
# Span parent's span_id. | ||
# @return [String, nil] | ||
attr_reader :parent_span_id | ||
# The sampling decision of the parent transaction. | ||
# @return [Boolean, nil] | ||
attr_reader :parent_sampled | ||
# Is there an incoming trace or not? | ||
# @return [Boolean] | ||
attr_reader :incoming_trace | ||
# This is only for accessing the current baggage variable. | ||
# Please use the #get_baggage method for interfacing outside this class. | ||
# @return [Baggage, nil] | ||
attr_reader :baggage | ||
|
||
def initialize(scope, env = nil) | ||
@scope = scope | ||
@parent_span_id = nil | ||
@parent_sampled = nil | ||
@baggage = nil | ||
@incoming_trace = false | ||
|
||
if env | ||
sentry_trace_header = env["HTTP_SENTRY_TRACE"] || env[SENTRY_TRACE_HEADER_NAME] | ||
baggage_header = env["HTTP_BAGGAGE"] || env[BAGGAGE_HEADER_NAME] | ||
|
||
if sentry_trace_header | ||
sentry_trace_data = self.class.extract_sentry_trace(sentry_trace_header) | ||
|
||
if sentry_trace_data | ||
@trace_id, @parent_span_id, @parent_sampled = sentry_trace_data | ||
|
||
@baggage = if baggage_header && !baggage_header.empty? | ||
Baggage.from_incoming_header(baggage_header) | ||
else | ||
# If there's an incoming sentry-trace but no incoming baggage header, | ||
# for instance in traces coming from older SDKs, | ||
# baggage will be empty and frozen and won't be populated as head SDK. | ||
Baggage.new({}) | ||
end | ||
|
||
@baggage.freeze! | ||
@incoming_trace = true | ||
end | ||
end | ||
end | ||
|
||
@trace_id ||= SecureRandom.uuid.delete("-") | ||
@span_id = SecureRandom.uuid.delete("-").slice(0, 16) | ||
end | ||
|
||
# Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header. | ||
# | ||
# @param sentry_trace [String] the sentry-trace header value from the previous transaction. | ||
# @return [Array, nil] | ||
def self.extract_sentry_trace(sentry_trace) | ||
match = SENTRY_TRACE_REGEXP.match(sentry_trace) | ||
return nil if match.nil? | ||
|
||
trace_id, parent_span_id, sampled_flag = match[1..3] | ||
parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0" | ||
|
||
[trace_id, parent_span_id, parent_sampled] | ||
end | ||
|
||
# Returns the trace context that can be used to embed in an Event. | ||
# @return [Hash] | ||
def get_trace_context | ||
{ | ||
trace_id: trace_id, | ||
span_id: span_id, | ||
parent_span_id: parent_span_id | ||
} | ||
end | ||
|
||
# Returns the sentry-trace header from the propagation context. | ||
# @return [String] | ||
def get_traceparent | ||
"#{trace_id}-#{span_id}" | ||
end | ||
|
||
# Returns the Baggage from the propagation context or populates as head SDK if empty. | ||
# @return [Baggage, nil] | ||
def get_baggage | ||
populate_head_baggage if @baggage.nil? || @baggage.mutable | ||
@baggage | ||
end | ||
|
||
# Returns the Dynamic Sampling Context from the baggage. | ||
# @return [String, nil] | ||
def get_dynamic_sampling_context | ||
get_baggage&.dynamic_sampling_context | ||
end | ||
|
||
private | ||
|
||
def populate_head_baggage | ||
return unless Sentry.initialized? | ||
|
||
configuration = Sentry.configuration | ||
|
||
items = { | ||
"trace_id" => trace_id, | ||
"environment" => configuration.environment, | ||
"release" => configuration.release, | ||
"public_key" => configuration.dsn&.public_key, | ||
"user_segment" => @scope.user && @scope.user["segment"] | ||
} | ||
|
||
items.compact! | ||
@baggage = Baggage.new(items, mutable: false) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.