Class: Sentry::Transaction

Inherits:
Span show all
Defined in:
lib/sentry/transaction.rb

Defined Under Namespace

Classes: SpanRecorder

Constant Summary collapse

SENTRY_TRACE_REGEXP =
Regexp.new(
  "^[ \t]*" +  # whitespace
  "([0-9a-f]{32})?" +  # trace_id
  "-?([0-9a-f]{16})?" +  # span_id
  "-?([01])?" +  # sampled
  "[ \t]*$"  # whitespace
)
UNLABELD_NAME =

whitespace

"<unlabeled transaction>".freeze
MESSAGE_PREFIX =
"[Tracing]"

Constants inherited from Span

Span::STATUS_MAP

Instance Attribute Summary collapse

Attributes inherited from Span

#data, #description, #op, #parent_span_id, #sampled, #span_id, #span_recorder, #start_timestamp, #status, #tags, #timestamp, #trace_id

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Span

#get_trace_context, #set_data, #set_description, #set_http_status, #set_op, #set_status, #set_tag, #set_timestamp, #to_sentry_trace, #with_child_span

Constructor Details

#initialize(name: nil, parent_sampled: nil, **options) ⇒ Transaction

Returns a new instance of Transaction.



15
16
17
18
19
20
21
# File 'lib/sentry/transaction.rb', line 15

def initialize(name: nil, parent_sampled: nil, **options)
  super(**options)

  @name = name
  @parent_sampled = parent_sampled
  set_span_recorder
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



13
14
15
# File 'lib/sentry/transaction.rb', line 13

def name
  @name
end

#parent_sampledObject (readonly)

Returns the value of attribute parent_sampled.



13
14
15
# File 'lib/sentry/transaction.rb', line 13

def parent_sampled
  @parent_sampled
end

Class Method Details

.from_sentry_trace(sentry_trace, **options) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/sentry/transaction.rb', line 28

def self.from_sentry_trace(sentry_trace, **options)
  return unless sentry_trace

  match = SENTRY_TRACE_REGEXP.match(sentry_trace)
  return if match.nil?
  trace_id, parent_span_id, sampled_flag = match[1..3]

  sampled = sampled_flag != "0"

  new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: sampled, sampled: sampled, **options)
end

Instance Method Details

#deep_dupObject



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/sentry/transaction.rb', line 57

def deep_dup
  copy = super
  copy.set_span_recorder

  @span_recorder.spans.each do |span|
    # span_recorder's first span is the current span, which should not be added to the copy's spans
    next if span == self
    copy.span_recorder.add(span.dup)
  end

  copy
end

#finish(hub: nil) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/sentry/transaction.rb', line 120

def finish(hub: nil)
  super() # Span#finish doesn't take arguments

  if @name.nil?
    @name = UNLABELD_NAME
  end

  return unless @sampled || @parent_sampled

  hub ||= Sentry.get_current_hub
  event = hub.current_client.event_from_transaction(self)
  hub.capture_event(event)
end

#set_initial_sample_desicion(sampling_context = {}) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
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
# File 'lib/sentry/transaction.rb', line 70

def set_initial_sample_desicion(sampling_context = {})
  unless Sentry.configuration.tracing_enabled?
    @sampled = false
    return
  end

  return unless @sampled.nil?

  transaction_description = generate_transaction_description

  logger = Sentry.configuration.logger
  sample_rate = Sentry.configuration.traces_sample_rate
  traces_sampler = Sentry.configuration.traces_sampler

  if traces_sampler.is_a?(Proc)
    sampling_context = sampling_context.merge(
      parent_sampled: @parent_sampled,
      transaction_context: self.to_hash
    )

    sample_rate = traces_sampler.call(sampling_context)
  end

  unless [true, false].include?(sample_rate) || (sample_rate.is_a?(Numeric) && sample_rate >= 0.0 && sample_rate <= 1.0)
    @sampled = false
    logger.warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
    return
  end

  if sample_rate == 0.0 || sample_rate == false
    @sampled = false
    logger.debug("#{MESSAGE_PREFIX} Discarding #{transaction_description} because traces_sampler returned 0 or false")
    return
  end

  if sample_rate == true
    @sampled = true
  else
    @sampled = Random.rand < sample_rate
  end

  if @sampled
    logger.debug("#{MESSAGE_PREFIX} Starting #{transaction_description}")
  else
    logger.debug(
      "#{MESSAGE_PREFIX} Discarding #{transaction_description} because it's not included in the random sample (sampling rate = #{sample_rate})"
    )
  end
end

#set_span_recorderObject



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

def set_span_recorder
  @span_recorder = SpanRecorder.new(1000)
  @span_recorder.add(self)
end

#start_child(**options) ⇒ Object



46
47
48
49
50
51
52
53
54
55
# File 'lib/sentry/transaction.rb', line 46

def start_child(**options)
  child_span = super
  child_span.span_recorder = @span_recorder

  if @sampled
    @span_recorder.add(child_span)
  end

  child_span
end

#to_hashObject



40
41
42
43
44
# File 'lib/sentry/transaction.rb', line 40

def to_hash
  hash = super
  hash.merge!(name: @name, sampled: @sampled, parent_sampled: @parent_sampled)
  hash
end