Class: Datadog::TraceBuffer

Inherits:
Object
  • Object
show all
Defined in:
lib/ddtrace/buffer.rb

Overview

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.

Instance Method Summary collapse

Constructor Details

#initialize(max_size) ⇒ TraceBuffer

Returns a new instance of TraceBuffer.



10
11
12
13
14
15
16
17
18
19
20
21
22
# 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

Instance Method Details

#closeObject



70
71
72
73
74
# File 'lib/ddtrace/buffer.rb', line 70

def close
  @mutex.synchronize do
    @closed = true
  end
end

#empty?Boolean

Return if the buffer is empty.

Returns:

  • (Boolean)


52
53
54
55
56
# File 'lib/ddtrace/buffer.rb', line 52

def empty?
  @mutex.synchronize do
    return @traces.empty?
  end
end

#lengthObject

Return the current number of stored traces.



45
46
47
48
49
# File 'lib/ddtrace/buffer.rb', line 45

def length
  @mutex.synchronize do
    return @traces.length
  end
end

#measure_accept(trace) ⇒ Object

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.



81
82
83
84
85
86
87
# 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::Tracer.log.debug("Failed to measure queue accept. Cause: #{e.message} Source: #{e.backtrace.first}")
end

#measure_drop(trace) ⇒ Object



89
90
91
92
93
94
95
# 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::Tracer.log.debug("Failed to measure queue drop. Cause: #{e.message} Source: #{e.backtrace.first}")
end

#measure_pop(traces) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/ddtrace/buffer.rb', line 97

def measure_pop(traces)
  # Accepted
  Diagnostics::Health.metrics.queue_accepted(@buffer_accepted)
  Diagnostics::Health.metrics.queue_accepted_lengths(@buffer_accepted_lengths)

  # Dropped
  Diagnostics::Health.metrics.queue_dropped(@buffer_dropped)

  # Queue gauges
  Diagnostics::Health.metrics.queue_max_length(@max_size)
  Diagnostics::Health.metrics.queue_spans(@buffer_spans)
  Diagnostics::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::Tracer.log.debug("Failed to measure queue. Cause: #{e.message} Source: #{e.backtrace.first}")
end

#popObject

Stored traces are returned and the local buffer is reset.



59
60
61
62
63
64
65
66
67
68
# File 'lib/ddtrace/buffer.rb', line 59

def pop
  @mutex.synchronize do
    traces = @traces
    @traces = []

    measure_pop(traces)

    return traces
  end
end

#push(trace) ⇒ Object

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.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 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