Class: LlmLogs::Span

Inherits:
ApplicationRecord show all
Defined in:
app/models/llm_logs/span.rb

Instance Method Summary collapse

Instance Method Details

#finishObject



12
13
14
15
16
17
18
19
20
# File 'app/models/llm_logs/span.rb', line 12

def finish
  update!(
    completed_at: Time.current,
    duration_ms: (Time.current - started_at) * 1000
  )

  # Restore parent span as current (Fiber[] so child fibers inherit it)
  LlmLogs::Tracer.current_span = parent_span
end

#record_error(exception) ⇒ Object



37
38
39
40
# File 'app/models/llm_logs/span.rb', line 37

def record_error(exception)
  self.status = "error"
  self.error_message = "#{exception.class}: #{exception.message}"
end

#record_response(message) ⇒ Object



22
23
24
25
26
27
# File 'app/models/llm_logs/span.rb', line 22

def record_response(message)
  self.output = { content: serialize_content(message.content) }
  self.input_tokens = message.input_tokens
  self.output_tokens = message.output_tokens
  self.cached_tokens = message.cached_tokens
end

#serialize_content(content) ⇒ Object

Structured (schema) responses arrive as a Hash/Array; keep them as-is so the JSON ‘output` column stores real JSON and the UI renders nested fields. Calling `.to_s` here would serialize a Hash with Ruby inspect syntax (“key” => “value”), which is not valid JSON and shows up as an escaped blob in the dashboard.



33
34
35
# File 'app/models/llm_logs/span.rb', line 33

def serialize_content(content)
  content.is_a?(Hash) || content.is_a?(Array) ? content : content.to_s
end

#set_attribute(key, value) ⇒ Object



42
43
44
# File 'app/models/llm_logs/span.rb', line 42

def set_attribute(key, value)
  self. = ( || {}).merge(key => value)
end