Module: ActiveAgent::Telemetry::Instrumentation::GenerationInstrumentation

Defined in:
lib/active_agent/telemetry/instrumentation.rb

Overview

Module prepended to intercept generation methods.

Instance Method Summary collapse

Instance Method Details

#process_embedObject

Wraps process_embed with telemetry tracing.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/active_agent/telemetry/instrumentation.rb', line 113

def process_embed
  return super unless Telemetry.enabled?

  Telemetry.trace("#{self.class.name}.embed", span_type: :embedding) do |span|
    span.set_attribute("agent.class", self.class.name)
    span.set_attribute("agent.action", "embed")
    span.set_attribute("agent.provider", provider_name) if respond_to?(:provider_name)

    begin
      result = super

      if result.respond_to?(:usage) && result.usage.present?
        usage = result.usage
        input_tokens = (usage.input_tokens rescue 0) || 0
        span.set_tokens(input: input_tokens.to_i)
      end

      span.set_status(:ok)
      result
    rescue StandardError => e
      span.record_error(e)
      raise
    end
  end
end

#process_promptObject

Wraps process_prompt with telemetry tracing.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/active_agent/telemetry/instrumentation.rb', line 46

def process_prompt
  return super unless Telemetry.enabled?

  Telemetry.trace("#{self.class.name}.#{action_name}", span_type: :root) do |span|
    span.set_attribute("agent.class", self.class.name)
    span.set_attribute("agent.action", action_name.to_s)
    span.set_attribute("agent.provider", provider_name) if respond_to?(:provider_name)
    span.set_attribute("agent.model", model_name) if respond_to?(:model_name)

    # Add prompt span
    prompt_span = span.add_span("agent.prompt", span_type: :prompt)
    prompt_span.set_attribute("messages.count", messages.size) if respond_to?(:messages)
    prompt_span.finish

    # Execute generation with LLM span
    llm_span = span.add_span("llm.generate", span_type: :llm)
    llm_span.set_attribute("llm.provider", provider_name) if respond_to?(:provider_name)
    llm_span.set_attribute("llm.model", model_name) if respond_to?(:model_name)

    begin
      result = super

      # Record token usage from response
      if result.respond_to?(:usage) && result.usage.present?
        usage = result.usage
        # Usage model uses methods, not hash access
        input_tokens = (usage.input_tokens rescue 0) || 0
        output_tokens = (usage.output_tokens rescue 0) || 0
        reasoning_tokens = (usage.reasoning_tokens rescue 0) || 0

        llm_span.set_tokens(
          input: input_tokens.to_i,
          output: output_tokens.to_i,
          thinking: reasoning_tokens.to_i
        )
        span.set_tokens(
          input: input_tokens.to_i,
          output: output_tokens.to_i,
          thinking: reasoning_tokens.to_i
        )
      end

      # Record tool calls if present
      if result.respond_to?(:tool_calls) && result.tool_calls.present?
        result.tool_calls.each do |tool_call|
          tool_span = span.add_span("tool.#{tool_call[:name]}", span_type: :tool)
          tool_span.set_attribute("tool.name", tool_call[:name])
          tool_span.set_attribute("tool.id", tool_call[:id]) if tool_call[:id]
          tool_span.finish
        end
      end

      llm_span.set_status(:ok)
      llm_span.finish
      span.set_status(:ok)

      result
    rescue StandardError => e
      llm_span.record_error(e)
      llm_span.finish
      span.record_error(e)
      raise
    end
  end
end