Class: Sentry::PropagationContext

Inherits:
Object
  • Object
show all
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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope, env = nil) ⇒ PropagationContext

Returns a new instance of PropagationContext.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/sentry/propagation_context.rb', line 83

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
        @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

        @sample_rand = self.class.extract_sample_rand_from_baggage(@baggage, @trace_id)

        @baggage.freeze!
        @incoming_trace = true
      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

#baggageBaggage? (readonly)

This is only for accessing the current baggage variable. Please use the #get_baggage method for interfacing outside this class.

Returns:



34
35
36
# File 'lib/sentry/propagation_context.rb', line 34

def baggage
  @baggage
end

#incoming_traceBoolean (readonly)

Is there an incoming trace or not?

Returns:

  • (Boolean)


30
31
32
# File 'lib/sentry/propagation_context.rb', line 30

def incoming_trace
  @incoming_trace
end

#parent_sampledBoolean? (readonly)

The sampling decision of the parent transaction.

Returns:

  • (Boolean, nil)


27
28
29
# File 'lib/sentry/propagation_context.rb', line 27

def parent_sampled
  @parent_sampled
end

#parent_span_idString? (readonly)

Span parent’s span_id.

Returns:

  • (String, nil)


24
25
26
# File 'lib/sentry/propagation_context.rb', line 24

def parent_span_id
  @parent_span_id
end

#sample_randFloat? (readonly)

The propagated random value used for sampling decisions.

Returns:

  • (Float, nil)


37
38
39
# File 'lib/sentry/propagation_context.rb', line 37

def sample_rand
  @sample_rand
end

#span_idString (readonly)

An uuid that can be used to identify the span.

Returns:

  • (String)


21
22
23
# File 'lib/sentry/propagation_context.rb', line 21

def span_id
  @span_id
end

#trace_idString (readonly)

An uuid that can be used to identify a trace.

Returns:

  • (String)


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



56
57
58
59
60
61
62
63
64
# File 'lib/sentry/propagation_context.rb', line 56

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.

Parameters:

  • sentry_trace (String)

    the sentry-trace header value from the previous transaction.

Returns:

  • (Array, nil)


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



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/sentry/propagation_context.rb', line 66

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

Instance Method Details

#get_baggageBaggage?

Returns the Baggage from the propagation context or populates as head SDK if empty.

Returns:



142
143
144
145
# File 'lib/sentry/propagation_context.rb', line 142

def get_baggage
  populate_head_baggage if @baggage.nil? || @baggage.mutable
  @baggage
end

#get_dynamic_sampling_contextHash?

Returns the Dynamic Sampling Context from the baggage.

Returns:

  • (Hash, nil)


149
150
151
# File 'lib/sentry/propagation_context.rb', line 149

def get_dynamic_sampling_context
  get_baggage&.dynamic_sampling_context
end

#get_trace_contextHash

Returns the trace context that can be used to embed in an Event.

Returns:

  • (Hash)


126
127
128
129
130
131
132
# File 'lib/sentry/propagation_context.rb', line 126

def get_trace_context
  {
    trace_id: trace_id,
    span_id: span_id,
    parent_span_id: parent_span_id
  }
end

#get_traceparentString

Returns the sentry-trace header from the propagation context.

Returns:

  • (String)


136
137
138
# File 'lib/sentry/propagation_context.rb', line 136

def get_traceparent
  "#{trace_id}-#{span_id}"
end