Class: A2A::Monitoring::DistributedTracing::Span

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

Overview

Span implementation for distributed tracing

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, kind: SPAN_KIND_INTERNAL, parent: nil, **attributes) ⇒ Span

Initialize a new span

Parameters:

  • Span name

  • (defaults to: SPAN_KIND_INTERNAL)

    Span kind

  • (defaults to: nil)

    Parent span

  • Initial attributes



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 222

def initialize(name, kind: SPAN_KIND_INTERNAL, parent: nil, **attributes)
  @name = name
  @kind = kind
  @trace_id = parent&.trace_id || generate_trace_id
  @span_id = generate_span_id
  @parent_span_id = parent&.span_id
  @start_time = Time.now
  @end_time = nil
  @attributes = attributes
  @events = []
  @status = { code: :unset }

  # Set as current span
  DistributedTracing.set_current_span(self)
end

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def attributes
  @attributes
end

#end_timeObject (readonly)

Returns the value of attribute end_time.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def end_time
  @end_time
end

#eventsObject (readonly)

Returns the value of attribute events.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def events
  @events
end

#kindObject (readonly)

Returns the value of attribute kind.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def kind
  @kind
end

#nameObject (readonly)

Returns the value of attribute name.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def name
  @name
end

#parent_span_idObject (readonly)

Returns the value of attribute parent_span_id.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def parent_span_id
  @parent_span_id
end

#span_idObject (readonly)

Returns the value of attribute span_id.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def span_id
  @span_id
end

#start_timeObject (readonly)

Returns the value of attribute start_time.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def start_time
  @start_time
end

#statusObject (readonly)

Returns the value of attribute status.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def status
  @status
end

#trace_idObject (readonly)

Returns the value of attribute trace_id.



212
213
214
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 212

def trace_id
  @trace_id
end

Instance Method Details

#add_event(name, attributes: {}, timestamp: Time.now) ⇒ Object

Add an event to the span

Parameters:

  • Event name

  • (defaults to: {})

    Event attributes

  • (defaults to: Time.now)

    Event timestamp



261
262
263
264
265
266
267
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 261

def add_event(name, attributes: {}, timestamp: Time.now)
  @events << {
    name: name,
    attributes: attributes,
    timestamp: timestamp
  }
end

#duration_msFloat?

Get span duration in milliseconds

Returns:

  • Duration in milliseconds



307
308
309
310
311
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 307

def duration_ms
  return nil unless @end_time

  (@end_time - @start_time) * 1000
end

#export_spanObject (private)

Export span to configured exporters



366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 366

def export_span
  # This would integrate with OpenTelemetry exporters
  # For now, just log the span if debugging is enabled
  return unless A2A.configuration.debug_tracing

  logger = if defined?(::Rails) && ::Rails.respond_to?(:logger) && ::Rails.logger
             ::Rails.logger
           else
             require "logger"
             Logger.new($stdout)
           end
  logger.debug { "Span: #{to_h.to_json}" }
end

#finishObject

Finish the span



293
294
295
296
297
298
299
300
301
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 293

def finish
  @end_time = Time.now

  # Clear from current context if this is the current span
  DistributedTracing.set_current_span(@parent) if DistributedTracing.current_span == self

  # Export span if exporter is available
  export_span
end

#generate_span_idString (private)

Generate a new span ID

Returns:

  • 16-character hex span ID



359
360
361
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 359

def generate_span_id
  SecureRandom.hex(8)
end

#generate_trace_idString (private)

Generate a new trace ID

Returns:

  • 32-character hex trace ID



351
352
353
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 351

def generate_trace_id
  SecureRandom.hex(16)
end

#record_exception(exception) ⇒ Object

Record an exception

Parameters:

  • Exception to record



273
274
275
276
277
278
279
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 273

def record_exception(exception)
  add_event("exception", attributes: {
              "exception.type" => exception.class.name,
              "exception.message" => exception.message,
              "exception.stacktrace" => exception.backtrace&.join("\n")
            })
end

#set_attribute(key, value) ⇒ Object

Set span attribute

Parameters:

  • Attribute key

  • Attribute value



243
244
245
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 243

def set_attribute(key, value)
  @attributes[key.to_s] = value
end

#set_attributes(**attributes) ⇒ Object

Set multiple attributes

Parameters:

  • Attributes to set



251
252
253
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 251

def set_attributes(**attributes)
  @attributes.merge!(attributes.transform_keys(&:to_s))
end

#set_status(code, description: nil) ⇒ Object

Set span status

Parameters:

  • Status code (:ok, :error, :unset)

  • (defaults to: nil)

    Status description



286
287
288
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 286

def set_status(code, description: nil)
  @status = { code: code, description: description }.compact
end

#to_hHash

Convert span to hash representation

Returns:

  • Span data



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 317

def to_h
  {
    name: @name,
    kind: @kind,
    trace_id: @trace_id,
    span_id: @span_id,
    parent_span_id: @parent_span_id,
    start_time: @start_time.to_f,
    end_time: @end_time&.to_f,
    duration_ms: duration_ms,
    attributes: @attributes,
    events: @events,
    status: @status
  }.compact
end

#trace_contextTraceContext

Get trace context for this span

Returns:

  • Trace context



337
338
339
340
341
342
343
# File 'lib/a2a/monitoring/distributed_tracing.rb', line 337

def trace_context
  TraceContext.new(
    trace_id: @trace_id,
    span_id: @span_id,
    trace_flags: 1
  )
end