Class: XRay::Recorder

Inherits:
Object
  • Object
show all
Defined in:
lib/aws-xray-sdk/recorder.rb

Overview

A global AWS X-Ray recorder that will begin/end segments/subsegments and send them to the X-Ray daemon. It is also responsible for managing context.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user_config: nil) ⇒ Recorder

Returns a new instance of Recorder.



17
18
19
20
# File 'lib/aws-xray-sdk/recorder.rb', line 17

def initialize(user_config: nil)
  @config = Configuration.new
  @config.configure(user_config) unless user_config.nil?
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



15
16
17
# File 'lib/aws-xray-sdk/recorder.rb', line 15

def config
  @config
end

Instance Method Details

#annotationsObject

A proxy method to get the annotations from the current active entity.



156
157
158
159
160
161
162
163
# File 'lib/aws-xray-sdk/recorder.rb', line 156

def annotations
  entity = current_entity
  if entity
    entity.annotations
  else
    FacadeAnnotations
  end
end

#begin_segment(name, trace_id: nil, parent_id: nil, sampled: nil) ⇒ Segment

Begin a segment for the current context. The recorder only keeps one segment at a time. Create a second one without closing existing one will overwrite the existing one.

Returns:

  • (Segment)

    thew newly created segment.

Raises:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/aws-xray-sdk/recorder.rb', line 26

def begin_segment(name, trace_id: nil, parent_id: nil, sampled: nil)
  seg_name = name || config.name
  raise SegmentNameMissingError if seg_name.to_s.empty?

  # sampling decision comes from outside has higher precedence.
  sample = sampled.nil? ? config.sample? : sampled
  if sample
    segment = Segment.new name: seg_name, trace_id: trace_id, parent_id: parent_id
    populate_runtime_context(segment)
  else
    segment = DummySegment.new name: seg_name, trace_id: trace_id, parent_id: parent_id
  end
  context.store_entity entity: segment
  segment
end

#begin_subsegment(name, namespace: nil, segment: nil) ⇒ Subsegment

Begin a new subsegment and add it to be the child of the current active subsegment or segment. Also tie the new created subsegment to the current context. Its sampling decision will follow its parent.

Returns:

  • (Subsegment)

    the newly created subsegment. It could be ‘nil` if no active entity can be found and `context_missing` is set to `LOG_ERROR`.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/aws-xray-sdk/recorder.rb', line 63

def begin_subsegment(name, namespace: nil, segment: nil)
  entity = segment || current_entity
  return unless entity
  if entity.sampled
    subsegment = Subsegment.new name: name, segment: entity.segment, namespace: namespace
  else
    subsegment = DummySubsegment.new name: name, segment: entity.segment
  end
  # attach the new created subsegment under the current active entity
  entity.add_subsegment subsegment: subsegment
  # associate the new subsegment to the current context
  context.store_entity entity: subsegment
  subsegment
end

#capture(name, namespace: nil, segment: nil) ⇒ Object

Record the passed block as a subsegment. If ‘context_missing` is set to `LOG_ERROR` and no active entity can be found, the passed block will be executed as normal but it will not be recorded.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/aws-xray-sdk/recorder.rb', line 111

def capture(name, namespace: nil, segment: nil)
  subsegment = begin_subsegment name, namespace: namespace, segment: segment
  # prevent passed block from failing in case of context missing with log error
  if subsegment.nil?
    segment = DummySegment.new name: name
    subsegment = DummySubsegment.new name: name, segment: segment
  end

  begin
    yield subsegment
  rescue Exception => e
    subsegment.add_exception exception: e
    raise e
  ensure
    end_subsegment
  end
end

#clear_contextObject



142
143
144
# File 'lib/aws-xray-sdk/recorder.rb', line 142

def clear_context
  context.clear!
end

#configure(user_config) ⇒ Object

A proxy method to XRay::Configuration.configure



177
178
179
# File 'lib/aws-xray-sdk/recorder.rb', line 177

def configure(user_config)
  config.configure(user_config)
end

#contextObject



181
182
183
# File 'lib/aws-xray-sdk/recorder.rb', line 181

def context
  config.context
end

#current_entityObject

Returns current segment or subsegment that associated to the current context. This is a proxy method to Context class current_entity.



131
132
133
# File 'lib/aws-xray-sdk/recorder.rb', line 131

def current_entity
  context.current_entity
end

#current_segmentSegment

Returns the active segment tied to the current context. If the current context is under a subsegment, it returns its parent segment.

Returns:

  • (Segment)

    the active segment tied to the current context. If the current context is under a subsegment, it returns its parent segment.



44
45
46
47
# File 'lib/aws-xray-sdk/recorder.rb', line 44

def current_segment
  entity = current_entity
  entity.segment if entity
end

#current_subsegmentSubsegment

The active subsegment tied to the current context. Returns nil if the current context has no associated subsegment.

Returns:

  • (Subsegment)

    the active subsegment tied to the current context. Returns nil if the current context has no associated subsegment.



80
81
82
83
# File 'lib/aws-xray-sdk/recorder.rb', line 80

def current_subsegment
  entity = context.current_entity
  entity.is_a?(Subsegment) ? entity : nil
end

#emitterObject



189
190
191
# File 'lib/aws-xray-sdk/recorder.rb', line 189

def emitter
  config.emitter
end

#end_segment(end_time: nil) ⇒ Object

End the current segment and send it to X-Ray daemon if it is ready.



50
51
52
53
54
55
56
# File 'lib/aws-xray-sdk/recorder.rb', line 50

def end_segment(end_time: nil)
  segment = current_segment
  return unless segment
  segment.close end_time: end_time
  context.clear!
  emitter.send_entity entity: segment if segment.ready_to_send?
end

#end_subsegment(end_time: nil) ⇒ Object

End the current active subsegment. It also send the entire segment if this subsegment is the last one open or stream out subsegments of its parent segment if the stream threshold is breached.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/aws-xray-sdk/recorder.rb', line 88

def end_subsegment(end_time: nil)
  entity = current_entity
  return unless entity.is_a?(Subsegment)
  entity.close end_time: end_time
  # update current context
  if entity.parent.closed?
    context.clear!
  else
    context.store_entity entity: entity.parent
  end
  # check if the entire segment can be send.
  # If not, stream subsegments when threshold is reached.
  segment = entity.segment
  if segment.ready_to_send?
    emitter.send_entity entity: segment
  elsif streamer.eligible? segment: segment
    streamer.stream_subsegments root: segment, emitter: emitter
  end
end

#inject_context(entity, target_ctx: nil) ⇒ Object



135
136
137
138
139
140
# File 'lib/aws-xray-sdk/recorder.rb', line 135

def inject_context(entity, target_ctx: nil)
  context.inject_context entity, target_ctx: target_ctx
  return unless block_given?
  yield
  context.clear!
end

#metadata(namespace: :default) ⇒ Object

A proxy method to get the metadata under provided namespace from the current active entity.



167
168
169
170
171
172
173
174
# File 'lib/aws-xray-sdk/recorder.rb', line 167

def (namespace: :default)
  entity = current_entity
  if entity
    entity.(namespace: namespace)
  else
    FacadeMetadata
  end
end

#populate_runtime_context(segment) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/aws-xray-sdk/recorder.rb', line 207

def populate_runtime_context(segment)
  @aws ||= begin
    aws = {}
    config.plugins.each do |p|
      meta = p.aws
      if meta.is_a?(Hash) && !meta.empty?
        aws.merge! meta
        segment.origin = p::ORIGIN
      end
    end
    xray_meta = { xray:
      {
        sdk_version: XRay::VERSION,
        sdk: 'X-Ray for Ruby'
      }
    }
    aws.merge! xray_meta
  end

  @service ||= {
    runtime: RUBY_ENGINE,
    runtime_version: RUBY_VERSION
  }

  segment.aws = @aws
  segment.service = @service
end

#sampled?Boolean

Returns:

  • (Boolean)


146
147
148
149
150
151
152
153
# File 'lib/aws-xray-sdk/recorder.rb', line 146

def sampled?
  entity = current_entity
  if block_given?
    yield if entity && entity.sampled
  else
    entity && entity.sampled
  end
end

#samplerObject



185
186
187
# File 'lib/aws-xray-sdk/recorder.rb', line 185

def sampler
  config.sampler
end

#sampling_enabled?Boolean

Returns:

  • (Boolean)


201
202
203
# File 'lib/aws-xray-sdk/recorder.rb', line 201

def sampling_enabled?
  config.sampling
end

#segment_namingObject



197
198
199
# File 'lib/aws-xray-sdk/recorder.rb', line 197

def segment_naming
  config.segment_naming
end

#streamerObject



193
194
195
# File 'lib/aws-xray-sdk/recorder.rb', line 193

def streamer
  config.streamer
end