Class: A2A::Monitoring::DistributedTracing

Inherits:
Object
  • Object
show all
Defined in:
lib/a2a/monitoring/distributed_tracing.rb

Defined Under Namespace

Classes: NoOpSpan, Span, TraceContext

Constant Summary collapse

TRACE_PARENT_HEADER =

Trace context headers

"traceparent"
TRACE_STATE_HEADER =
"tracestate"
SPAN_KIND_CLIENT =

Span kinds

"client"
SPAN_KIND_SERVER =
"server"
SPAN_KIND_INTERNAL =
"internal"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.enabledObject

Returns the value of attribute enabled.



29
30
31
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 29

def enabled
  @enabled
end

.tracerObject

Returns the value of attribute tracer.



29
30
31
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 29

def tracer
  @tracer
end

Class Method Details

.current_spanSpan?

Get current span from context

Returns:

  • Current active span



120
121
122
123
124
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 120

def current_span
  return nil unless @enabled

  Thread.current[:a2a_current_span]
end

.extract_context(headers) ⇒ TraceContext?

Extract trace context from headers

Parameters:

  • HTTP headers

Returns:

  • Extracted trace context



93
94
95
96
97
98
99
100
101
102
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 93

def extract_context(headers)
  return nil unless @enabled

  traceparent = headers[TRACE_PARENT_HEADER] || headers[TRACE_PARENT_HEADER.upcase]
  tracestate = headers[TRACE_STATE_HEADER] || headers[TRACE_STATE_HEADER.upcase]

  return nil unless traceparent

  TraceContext.parse(traceparent, tracestate)
end

.initialize!(tracer: nil, enabled: true) ⇒ Object

Initialize distributed tracing

Parameters:

  • (defaults to: nil)

    OpenTelemetry tracer instance

  • (defaults to: true)

    Whether tracing is enabled



36
37
38
39
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 36

def initialize!(tracer: nil, enabled: true)
  @tracer = tracer
  @enabled = enabled
end

.inject_context(headers, context) ⇒ Object

Inject trace context into headers

Parameters:

  • HTTP headers to modify

  • Trace context to inject



109
110
111
112
113
114
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 109

def inject_context(headers, context)
  return unless @enabled && context

  headers[TRACE_PARENT_HEADER] = context.to_traceparent
  headers[TRACE_STATE_HEADER] = context.tracestate if context.tracestate
end

.set_current_span(span) ⇒ Object

Set current span in context

Parameters:

  • Span to set as current



130
131
132
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 130

def set_current_span(span)
  Thread.current[:a2a_current_span] = span
end

.start_span(name, kind: SPAN_KIND_INTERNAL, parent: nil, **attributes) ⇒ Span

Start a span without automatic finishing

Parameters:

  • Span name

  • (defaults to: SPAN_KIND_INTERNAL)

    Span kind

  • (defaults to: nil)

    Parent span

  • Span attributes

Returns:

  • Started span



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 76

def start_span(name, kind: SPAN_KIND_INTERNAL, parent: nil, **attributes)
  return NoOpSpan.new unless @enabled

  if @tracer.respond_to?(:start_span)
    # Use OpenTelemetry tracer if available
    @tracer.start_span(name, kind: kind, parent: parent, attributes: attributes)
  else
    # Use built-in span implementation
    Span.new(name, kind: kind, parent: parent, **attributes)
  end
end

.trace(name, kind: SPAN_KIND_INTERNAL, parent: nil, **attributes) {|span| ... } ⇒ Object

Start a new span

Parameters:

  • Span name

  • (defaults to: SPAN_KIND_INTERNAL)

    Span kind

  • (defaults to: nil)

    Parent span

  • Span attributes

Yields:

  • (span)

    Block to execute within span

Returns:

  • Result of the block



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 50

def trace(name, kind: SPAN_KIND_INTERNAL, parent: nil, **attributes)
  return yield(NoOpSpan.new) unless @enabled

  span = start_span(name, kind: kind, parent: parent, **attributes)

  begin
    result = yield(span)
    span.set_status(:ok)
    result
  rescue StandardError => e
    span.set_status(:error, description: e.message)
    span.record_exception(e)
    raise
  ensure
    span.finish
  end
end