Class: Sentry::PropagationContext
- Inherits:
-
Object
- Object
- Sentry::PropagationContext
- Defined in:
- lib/sentry/propagation_context.rb
Constant Summary collapse
- SENTRY_TRACE_REGEXP =
Regexp.new( "\\A([0-9a-f]{32})?" + # trace_id "-?([0-9a-f]{16})?" + # span_id "-?([01])?\\z" # sampled )
Instance Attribute Summary collapse
-
#baggage ⇒ Baggage?
readonly
This is only for accessing the current baggage variable.
-
#incoming_trace ⇒ Boolean
readonly
Is there an incoming trace or not?.
-
#parent_sampled ⇒ Boolean?
readonly
The sampling decision of the parent transaction.
-
#parent_span_id ⇒ String?
readonly
Span parent’s span_id.
-
#sample_rand ⇒ Float?
readonly
The propagated random value used for sampling decisions.
-
#span_id ⇒ String
readonly
An uuid that can be used to identify the span.
-
#trace_id ⇒ String
readonly
An uuid that can be used to identify a trace.
Class Method Summary collapse
- .extract_sample_rand_from_baggage(baggage, trace_id = nil) ⇒ Object
-
.extract_sentry_trace(sentry_trace) ⇒ Array?
Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
- .generate_sample_rand(baggage, trace_id, parent_sampled) ⇒ Object
-
.should_continue_trace?(incoming_baggage) ⇒ Boolean
Determines whether we should continue an incoming trace based on org_id matching and the strict_trace_continuation configuration option.
Instance Method Summary collapse
-
#get_baggage ⇒ Baggage?
Returns the Baggage from the propagation context or populates as head SDK if empty.
-
#get_dynamic_sampling_context ⇒ Hash?
Returns the Dynamic Sampling Context from the baggage.
-
#get_trace_context ⇒ Hash
Returns the trace context that can be used to embed in an Event.
-
#get_traceparent ⇒ String
Returns the sentry-trace header from the propagation context.
-
#initialize(scope, env = nil) ⇒ PropagationContext
constructor
A new instance of PropagationContext.
Constructor Details
#initialize(scope, env = nil) ⇒ PropagationContext
Returns a new instance of PropagationContext.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/sentry/propagation_context.rb', line 121 def initialize(scope, env = nil) @scope = scope @parent_span_id = nil @parent_sampled = nil @baggage = nil @incoming_trace = false @sample_rand = nil 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 incoming_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 if self.class.should_continue_trace?(incoming_baggage) @trace_id, @parent_span_id, @parent_sampled = sentry_trace_data @baggage = incoming_baggage @sample_rand = self.class.extract_sample_rand_from_baggage(@baggage, @trace_id) @baggage.freeze! @incoming_trace = true end end end end @trace_id ||= Utils.uuid @span_id = Utils.uuid.slice(0, 16) @sample_rand ||= self.class.generate_sample_rand(@baggage, @trace_id, @parent_sampled) end |
Instance Attribute Details
#baggage ⇒ Baggage? (readonly)
This is only for accessing the current baggage variable. Please use the #get_baggage method for interfacing outside this class.
34 35 36 |
# File 'lib/sentry/propagation_context.rb', line 34 def baggage @baggage end |
#incoming_trace ⇒ Boolean (readonly)
Is there an incoming trace or not?
30 31 32 |
# File 'lib/sentry/propagation_context.rb', line 30 def incoming_trace @incoming_trace end |
#parent_sampled ⇒ Boolean? (readonly)
The sampling decision of the parent transaction.
27 28 29 |
# File 'lib/sentry/propagation_context.rb', line 27 def parent_sampled @parent_sampled end |
#parent_span_id ⇒ String? (readonly)
Span parent’s span_id.
24 25 26 |
# File 'lib/sentry/propagation_context.rb', line 24 def parent_span_id @parent_span_id end |
#sample_rand ⇒ Float? (readonly)
The propagated random value used for sampling decisions.
37 38 39 |
# File 'lib/sentry/propagation_context.rb', line 37 def sample_rand @sample_rand end |
#span_id ⇒ String (readonly)
An uuid that can be used to identify the span.
21 22 23 |
# File 'lib/sentry/propagation_context.rb', line 21 def span_id @span_id end |
#trace_id ⇒ String (readonly)
An uuid that can be used to identify a trace.
18 19 20 |
# File 'lib/sentry/propagation_context.rb', line 18 def trace_id @trace_id end |
Class Method Details
.extract_sample_rand_from_baggage(baggage, trace_id = nil) ⇒ Object
94 95 96 97 98 99 100 101 102 |
# File 'lib/sentry/propagation_context.rb', line 94 def self.extract_sample_rand_from_baggage(baggage, trace_id = nil) return unless baggage&.items sample_rand_str = baggage.items["sample_rand"] return unless sample_rand_str generator = Utils::SampleRand.new(trace_id: trace_id) generator.generate_from_value(sample_rand_str) end |
.extract_sentry_trace(sentry_trace) ⇒ Array?
Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/sentry/propagation_context.rb', line 43 def self.extract_sentry_trace(sentry_trace) value = sentry_trace.to_s.strip return if value.empty? match = SENTRY_TRACE_REGEXP.match(value) return 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 |
.generate_sample_rand(baggage, trace_id, parent_sampled) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/sentry/propagation_context.rb', line 104 def self.generate_sample_rand(baggage, trace_id, parent_sampled) generator = Utils::SampleRand.new(trace_id: trace_id) if baggage&.items && !parent_sampled.nil? sample_rate_str = baggage.items["sample_rate"] sample_rate = sample_rate_str&.to_f if sample_rate && !parent_sampled.nil? generator.generate_from_sampling_decision(parent_sampled, sample_rate) else generator.generate_from_trace_id end else generator.generate_from_trace_id end end |
.should_continue_trace?(incoming_baggage) ⇒ Boolean
Determines whether we should continue an incoming trace based on org_id matching and the strict_trace_continuation configuration option.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/sentry/propagation_context.rb', line 61 def self.should_continue_trace?(incoming_baggage) return true unless Sentry.initialized? configuration = Sentry.configuration sdk_org_id = configuration.effective_org_id baggage_org_id = incoming_baggage.items["org_id"] # Mismatched org IDs always start a new trace regardless of strict mode if sdk_org_id && baggage_org_id && sdk_org_id != baggage_org_id Sentry.sdk_logger.debug(LOGGER_PROGNAME) do "Starting a new trace because org IDs don't match (incoming baggage org_id: #{baggage_org_id}, SDK org_id: #{sdk_org_id})" end return false end return true unless configuration.strict_trace_continuation # In strict mode, both must be present and match (unless both are missing) if sdk_org_id.nil? && baggage_org_id.nil? true elsif sdk_org_id.nil? || baggage_org_id.nil? Sentry.sdk_logger.debug(LOGGER_PROGNAME) do "Starting a new trace because strict trace continuation is enabled and one org ID is missing " \ "(incoming baggage org_id: #{baggage_org_id.inspect}, SDK org_id: #{sdk_org_id.inspect})" end false else true end end |
Instance Method Details
#get_baggage ⇒ Baggage?
Returns the Baggage from the propagation context or populates as head SDK if empty.
181 182 183 184 |
# File 'lib/sentry/propagation_context.rb', line 181 def get_baggage populate_head_baggage if @baggage.nil? || @baggage.mutable @baggage end |
#get_dynamic_sampling_context ⇒ Hash?
Returns the Dynamic Sampling Context from the baggage.
188 189 190 |
# File 'lib/sentry/propagation_context.rb', line 188 def get_dynamic_sampling_context get_baggage&.dynamic_sampling_context end |
#get_trace_context ⇒ Hash
Returns the trace context that can be used to embed in an Event.
165 166 167 168 169 170 171 |
# File 'lib/sentry/propagation_context.rb', line 165 def get_trace_context { trace_id: trace_id, span_id: span_id, parent_span_id: parent_span_id } end |
#get_traceparent ⇒ String
Returns the sentry-trace header from the propagation context.
175 176 177 |
# File 'lib/sentry/propagation_context.rb', line 175 def get_traceparent "#{trace_id}-#{span_id}" end |