class XRay::Recorder

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.

Attributes

config[R]
origin[R]

Public Class Methods

new(user_config: nil) click to toggle source
# 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?
  @origin = nil
end

Public Instance Methods

annotations() click to toggle source

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

# File lib/aws-xray-sdk/recorder.rb, line 157
def annotations
  entity = current_entity
  if entity
    entity.annotations
  else
    FacadeAnnotations
  end
end
begin_segment(name, trace_id: nil, parent_id: nil, sampled: nil) click to toggle source

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. @return [Segment] thew newly created segment.

# File lib/aws-xray-sdk/recorder.rb, line 27
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, sample)
  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) click to toggle source

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. @return [Subsegment] the newly created subsegment. It could be `nil` if no active entity

can be found and `context_missing` is set to `LOG_ERROR`.
# File lib/aws-xray-sdk/recorder.rb, line 64
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) { |subsegment| ... } click to toggle source

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.

# File lib/aws-xray-sdk/recorder.rb, line 112
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_context() click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 143
def clear_context
  context.clear!
end
configure(user_config) click to toggle source

A proxy method to XRay::Configuration.configure

# File lib/aws-xray-sdk/recorder.rb, line 178
def configure(user_config)
  config.configure(user_config)
end
context() click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 182
def context
  config.context
end
current_entity() click to toggle source

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

# File lib/aws-xray-sdk/recorder.rb, line 132
def current_entity
  context.current_entity
end
current_segment() click to toggle source

@return [Segment] the active segment tied to the current context.

If the current context is under a subsegment, it returns its parent segment.
# File lib/aws-xray-sdk/recorder.rb, line 45
def current_segment
  entity = current_entity
  entity.segment if entity
end
current_subsegment() click to toggle source

@return [Subsegment] the active subsegment tied to the current context.

Returns nil if the current context has no associated subsegment.
# File lib/aws-xray-sdk/recorder.rb, line 81
def current_subsegment
  entity = context.current_entity
  entity.is_a?(Subsegment) ? entity : nil
end
emitter() click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 190
def emitter
  config.emitter
end
end_segment(end_time: nil) click to toggle source

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

# File lib/aws-xray-sdk/recorder.rb, line 51
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) click to toggle source

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.

# File lib/aws-xray-sdk/recorder.rb, line 89
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) { || ... } click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 136
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) click to toggle source

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

# File lib/aws-xray-sdk/recorder.rb, line 168
def metadata(namespace: :default)
  entity = current_entity
  if entity
    entity.metadata(namespace: namespace)
  else
    FacadeMetadata
  end
end
sampled?() { || ... } click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 147
def sampled?
  entity = current_entity
  if block_given?
    yield if entity && entity.sampled
  else
    entity && entity.sampled
  end
end
sampler() click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 186
def sampler
  config.sampler
end
sampling_enabled?() click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 202
def sampling_enabled?
  config.sampling
end
segment_naming() click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 198
def segment_naming
  config.segment_naming
end
streamer() click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 194
def streamer
  config.streamer
end

Private Instance Methods

populate_runtime_context(segment, sample) click to toggle source
# File lib/aws-xray-sdk/recorder.rb, line 208
def populate_runtime_context(segment, sample)
  @aws ||= begin
    aws = {}
    config.plugins.each do |p|
      meta = p.aws
      if meta.is_a?(Hash) && !meta.empty?
        aws.merge! meta
        @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
  segment.origin = @origin
  segment.sampling_rule_name = sample if sample.is_a?(String)
end