Class: ActiveAgent::Telemetry::Span
- Inherits:
-
Object
- Object
- ActiveAgent::Telemetry::Span
- Defined in:
- lib/active_agent/telemetry/span.rb
Overview
Represents a single span in a trace.
Spans capture discrete operations within a trace, such as LLM calls, tool invocations, or prompt rendering. Each span has timing, attributes, and can have child spans.
Constant Summary collapse
- TYPES =
Span types for categorization
{ root: "root", # Root span for entire generation prompt: "prompt", # Prompt preparation/rendering llm: "llm", # LLM API call tool: "tool", # Tool invocation thinking: "thinking", # Extended thinking (Anthropic) embedding: "embedding", # Embedding generation error: "error" # Error handling }.freeze
- STATUS =
Span status codes
{ unset: "UNSET", ok: "OK", error: "ERROR" }.freeze
Instance Attribute Summary collapse
-
#attributes ⇒ Hash
readonly
Span attributes.
-
#children ⇒ Array<Span>
readonly
Child spans.
-
#end_time ⇒ Time?
readonly
When the span ended.
-
#events ⇒ Array<Hash>
readonly
Events recorded during the span.
-
#name ⇒ String
readonly
Span name (e.g., “llm.generate”, “tool.get_weather”).
-
#parent_span_id ⇒ String?
readonly
Parent span ID.
-
#span_id ⇒ String
readonly
Unique identifier for this span.
-
#span_type ⇒ String
readonly
Span type from TYPES.
-
#start_time ⇒ Time
readonly
When the span started.
-
#status ⇒ String
readonly
Status code from STATUS.
-
#status_message ⇒ String?
readonly
Status message.
-
#trace_id ⇒ String
readonly
Trace ID this span belongs to.
Instance Method Summary collapse
-
#add_event(name, attributes = {}) ⇒ self
Adds an event to the span.
-
#add_span(name, span_type: :root, **attributes) ⇒ Span
Creates a child span.
-
#duration_ms ⇒ Float?
Returns the duration in milliseconds.
-
#finish ⇒ self
Marks the span as finished.
-
#finished? ⇒ Boolean
Returns whether the span is finished.
-
#initialize(name, trace_id:, parent_span_id: nil, span_type: :root, **attributes) ⇒ Span
constructor
Creates a new span.
-
#measure { ... } ⇒ Object
Executes a block and records timing/errors.
-
#record_error(error) ⇒ self
Records an error on the span.
-
#set_attribute(key, value) ⇒ self
Sets a single attribute.
-
#set_attributes(attrs) ⇒ self
Sets multiple attributes at once.
-
#set_status(code, message = nil) ⇒ self
Sets the span status.
-
#set_tokens(input: 0, output: 0, thinking: 0) ⇒ self
Sets token usage for LLM spans.
-
#to_h ⇒ Hash
Serializes the span for transmission.
-
#tokens ⇒ Hash
Returns token usage.
Constructor Details
#initialize(name, trace_id:, parent_span_id: nil, span_type: :root, **attributes) ⇒ Span
Creates a new span.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/active_agent/telemetry/span.rb', line 80 def initialize(name, trace_id:, parent_span_id: nil, span_type: :root, **attributes) @span_id = SecureRandom.hex(8) @trace_id = trace_id @parent_span_id = parent_span_id @name = name @span_type = TYPES[span_type] || span_type.to_s @start_time = Time.current @end_time = nil @attributes = attributes.transform_keys(&:to_s) @children = [] @status = STATUS[:unset] @status_message = nil @events = [] @tokens = { input: 0, output: 0, thinking: 0, total: 0 } end |
Instance Attribute Details
#attributes ⇒ Hash (readonly)
Returns Span attributes.
59 60 61 |
# File 'lib/active_agent/telemetry/span.rb', line 59 def attributes @attributes end |
#children ⇒ Array<Span> (readonly)
Returns Child spans.
62 63 64 |
# File 'lib/active_agent/telemetry/span.rb', line 62 def children @children end |
#end_time ⇒ Time? (readonly)
Returns When the span ended.
56 57 58 |
# File 'lib/active_agent/telemetry/span.rb', line 56 def end_time @end_time end |
#events ⇒ Array<Hash> (readonly)
Returns Events recorded during the span.
71 72 73 |
# File 'lib/active_agent/telemetry/span.rb', line 71 def events @events end |
#name ⇒ String (readonly)
Returns Span name (e.g., “llm.generate”, “tool.get_weather”).
47 48 49 |
# File 'lib/active_agent/telemetry/span.rb', line 47 def name @name end |
#parent_span_id ⇒ String? (readonly)
Returns Parent span ID.
44 45 46 |
# File 'lib/active_agent/telemetry/span.rb', line 44 def parent_span_id @parent_span_id end |
#span_id ⇒ String (readonly)
Returns Unique identifier for this span.
38 39 40 |
# File 'lib/active_agent/telemetry/span.rb', line 38 def span_id @span_id end |
#span_type ⇒ String (readonly)
Returns Span type from TYPES.
50 51 52 |
# File 'lib/active_agent/telemetry/span.rb', line 50 def span_type @span_type end |
#start_time ⇒ Time (readonly)
Returns When the span started.
53 54 55 |
# File 'lib/active_agent/telemetry/span.rb', line 53 def start_time @start_time end |
#status ⇒ String (readonly)
Returns Status code from STATUS.
65 66 67 |
# File 'lib/active_agent/telemetry/span.rb', line 65 def status @status end |
#status_message ⇒ String? (readonly)
Returns Status message.
68 69 70 |
# File 'lib/active_agent/telemetry/span.rb', line 68 def @status_message end |
#trace_id ⇒ String (readonly)
Returns Trace ID this span belongs to.
41 42 43 |
# File 'lib/active_agent/telemetry/span.rb', line 41 def trace_id @trace_id end |
Instance Method Details
#add_event(name, attributes = {}) ⇒ self
Adds an event to the span.
195 196 197 198 199 200 201 202 |
# File 'lib/active_agent/telemetry/span.rb', line 195 def add_event(name, attributes = {}) @events << { name: name, timestamp: Time.current.iso8601(6), attributes: attributes.transform_keys(&:to_s) } self end |
#add_span(name, span_type: :root, **attributes) ⇒ Span
Creates a child span.
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/active_agent/telemetry/span.rb', line 102 def add_span(name, span_type: :root, **attributes) child = Span.new( name, trace_id: trace_id, parent_span_id: span_id, span_type: span_type, **attributes ) @children << child child end |
#duration_ms ⇒ Float?
Returns the duration in milliseconds.
223 224 225 226 227 |
# File 'lib/active_agent/telemetry/span.rb', line 223 def duration_ms return nil unless finished? ((@end_time - @start_time) * 1000).round(2) end |
#finish ⇒ self
Marks the span as finished.
207 208 209 210 211 |
# File 'lib/active_agent/telemetry/span.rb', line 207 def finish @end_time = Time.current set_status(:ok) if @status == STATUS[:unset] self end |
#finished? ⇒ Boolean
Returns whether the span is finished.
216 217 218 |
# File 'lib/active_agent/telemetry/span.rb', line 216 def finished? !@end_time.nil? end |
#measure { ... } ⇒ Object
Executes a block and records timing/errors.
255 256 257 258 259 260 261 262 263 264 |
# File 'lib/active_agent/telemetry/span.rb', line 255 def measure result = yield set_status(:ok) result rescue StandardError => e record_error(e) raise ensure finish end |
#record_error(error) ⇒ self
Records an error on the span.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/active_agent/telemetry/span.rb', line 175 def record_error(error) set_status(:error, error.) set_attribute("error.type", error.class.name) set_attribute("error.message", error.) set_attribute("error.backtrace", error.backtrace&.first(10)&.join("\n")) add_event("exception", { "exception.type" => error.class.name, "exception.message" => error., "exception.stacktrace" => error.backtrace&.join("\n") }) self end |
#set_attribute(key, value) ⇒ self
Sets a single attribute.
119 120 121 122 |
# File 'lib/active_agent/telemetry/span.rb', line 119 def set_attribute(key, value) @attributes[key.to_s] = value self end |
#set_attributes(attrs) ⇒ self
Sets multiple attributes at once.
128 129 130 131 |
# File 'lib/active_agent/telemetry/span.rb', line 128 def set_attributes(attrs) attrs.each { |k, v| set_attribute(k, v) } self end |
#set_status(code, message = nil) ⇒ self
Sets the span status.
165 166 167 168 169 |
# File 'lib/active_agent/telemetry/span.rb', line 165 def set_status(code, = nil) @status = STATUS[code] || STATUS[:unset] @status_message = self end |
#set_tokens(input: 0, output: 0, thinking: 0) ⇒ self
Sets token usage for LLM spans.
139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/active_agent/telemetry/span.rb', line 139 def set_tokens(input: 0, output: 0, thinking: 0) @tokens = { input: input, output: output, thinking: thinking, total: input + output + thinking } set_attribute("tokens.input", input) set_attribute("tokens.output", output) set_attribute("tokens.thinking", thinking) if thinking > 0 set_attribute("tokens.total", @tokens[:total]) self end |
#to_h ⇒ Hash
Serializes the span for transmission.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/active_agent/telemetry/span.rb', line 232 def to_h { span_id: span_id, trace_id: trace_id, parent_span_id: parent_span_id, name: name, type: span_type, start_time: start_time.iso8601(6), end_time: end_time&.iso8601(6), duration_ms: duration_ms, status: status, status_message: , attributes: attributes, tokens: tokens, events: events, children: children.map(&:to_h) } end |
#tokens ⇒ Hash
Returns token usage.
156 157 158 |
# File 'lib/active_agent/telemetry/span.rb', line 156 def tokens @tokens.dup end |