class Datadog::TraceBuffer

Trace buffer that stores application traces. The buffer has a maximum size and when the buffer is full, a random trace is discarded. This class is thread-safe and is used automatically by the “Tracer“ instance when a “Span“ is finished.

Public Class Methods

new(max_size) click to toggle source
# File lib/ddtrace/buffer.rb, line 10
def initialize(max_size)
  @max_size = max_size

  @mutex = Mutex.new()
  @traces = []
  @closed = false

  # Initialize metric values
  @buffer_accepted = 0
  @buffer_accepted_lengths = 0
  @buffer_dropped = 0
  @buffer_spans = 0
end

Public Instance Methods

close() click to toggle source
# File lib/ddtrace/buffer.rb, line 70
def close
  @mutex.synchronize do
    @closed = true
  end
end
empty?() click to toggle source

Return if the buffer is empty.

# File lib/ddtrace/buffer.rb, line 52
def empty?
  @mutex.synchronize do
    return @traces.empty?
  end
end
length() click to toggle source

Return the current number of stored traces.

# File lib/ddtrace/buffer.rb, line 45
def length
  @mutex.synchronize do
    return @traces.length
  end
end
measure_accept(trace) click to toggle source

Aggregate metrics: They reflect buffer activity since last pop. These may not be as accurate or as granular, but they don't use as much network traffic as live stats.

# File lib/ddtrace/buffer.rb, line 81
def measure_accept(trace)
  @buffer_spans += trace.length
  @buffer_accepted += 1
  @buffer_accepted_lengths += trace.length
rescue StandardError => e
  Datadog.logger.debug("Failed to measure queue accept. Cause: #{e.message} Source: #{e.backtrace.first}")
end
measure_drop(trace) click to toggle source
# File lib/ddtrace/buffer.rb, line 89
def measure_drop(trace)
  @buffer_dropped += 1
  @buffer_spans -= trace.length
  @buffer_accepted_lengths -= trace.length
rescue StandardError => e
  Datadog.logger.debug("Failed to measure queue drop. Cause: #{e.message} Source: #{e.backtrace.first}")
end
measure_pop(traces) click to toggle source
# File lib/ddtrace/buffer.rb, line 97
def measure_pop(traces)
  # Accepted
  Datadog.health_metrics.queue_accepted(@buffer_accepted)
  Datadog.health_metrics.queue_accepted_lengths(@buffer_accepted_lengths)

  # Dropped
  Datadog.health_metrics.queue_dropped(@buffer_dropped)

  # Queue gauges
  Datadog.health_metrics.queue_max_length(@max_size)
  Datadog.health_metrics.queue_spans(@buffer_spans)
  Datadog.health_metrics.queue_length(traces.length)

  # Reset aggregated metrics
  @buffer_accepted = 0
  @buffer_accepted_lengths = 0
  @buffer_dropped = 0
  @buffer_spans = 0
rescue StandardError => e
  Datadog.logger.debug("Failed to measure queue. Cause: #{e.message} Source: #{e.backtrace.first}")
end
pop() click to toggle source

Stored traces are returned and the local buffer is reset.

# File lib/ddtrace/buffer.rb, line 59
def pop
  @mutex.synchronize do
    traces = @traces
    @traces = []

    measure_pop(traces)

    return traces
  end
end
push(trace) click to toggle source

Add a new “trace“ in the local queue. This method doesn't block the execution even if the buffer is full. In that case, a random trace is discarded.

# File lib/ddtrace/buffer.rb, line 26
def push(trace)
  @mutex.synchronize do
    return if @closed
    len = @traces.length
    if len < @max_size || @max_size <= 0
      @traces << trace
    else
      # we should replace a random trace with the new one
      replace_index = rand(len)
      replaced_trace = @traces[replace_index]
      @traces[replace_index] = trace
      measure_drop(replaced_trace)
    end

    measure_accept(trace)
  end
end