| title | Instrumentation and Logging |
|---|---|
| description | Monitor provider operations using ActiveSupport::Notifications. Track performance metrics, debug generation flows, and integrate with external monitoring services. |
ActiveAgent instruments all provider operations using ActiveSupport::Notifications, enabling detailed monitoring, logging, and custom event handling. Track performance metrics, debug generation flows, and integrate with external monitoring services.
::: warning Beta Feature This instrumentation API is in beta and may change with Rails 8.1. Event names, payload structures, and subscriber interfaces could be updated as Rails evolves its instrumentation and events patterns. :::
ActiveAgent publishes instrumentation events throughout the generation lifecycle. Subscribe to these events to monitor operations, track performance, and handle errors:
| Event | When Triggered | Description |
|---|---|---|
prompt_start.provider.active_agent |
Before prompt request | Prompt generation initiated |
embed_start.provider.active_agent |
Before embedding request | Embedding generation initiated |
request_prepared.provider.active_agent |
After request built | Request prepared with formatted messages |
api_call.provider.active_agent |
After API response | Provider API call completed |
embed_call.provider.active_agent |
After embedding API response | Embedding API call completed |
prompt_complete.provider.active_agent |
After full generation | Entire generation cycle finished |
| Event | When Triggered | Description |
|---|---|---|
stream_open.provider.active_agent |
Stream connection starts | Streaming connection opened |
stream_close.provider.active_agent |
Stream connection ends | Streaming connection closed |
| Event | When Triggered | Description |
|---|---|---|
messages_extracted.provider.active_agent |
After parsing response | Messages extracted from API response |
tool_calls_processing.provider.active_agent |
Before executing tools | Tool/function calls detected and processing |
multi_turn_continue.provider.active_agent |
After tool execution | Continuing conversation after tool use |
tool_execute.provider.active_agent |
During tool execution | Individual tool being executed |
| Event | When Triggered | Description |
|---|---|---|
retry_attempt.provider.active_agent |
After failed request | Retry attempt after error |
retry_exhausted.provider.active_agent |
After max retries | All retry attempts exhausted |
| Event | When Triggered | Description |
|---|---|---|
process.active_agent |
During agent action | Agent action processing |
ActiveAgent includes a LogSubscriber that automatically logs all provider operations at the debug level when Rails loads:
<<< @/../lib/active_agent/providers/log_subscriber.rb#log_subscriber_attach {ruby:line-numbers}
Logs include trace IDs for tracking related operations, provider names, timing information, and operation details.
Example log output:
[trace-123] [ActiveAgent] [OpenAI::Responses] Starting prompt request
[trace-123] [ActiveAgent] [OpenAI::Responses] Prepared request with 2 message(s)
[trace-123] [ActiveAgent] [OpenAI::Responses] API call completed in 543.2ms (streaming: false)
[trace-123] [ActiveAgent] [OpenAI::Responses] Prompt completed with 3 message(s) in stack (total: 567.1ms)
By default, ActiveAgent automatically inherits the logger and log level settings from your Rails application via the Railtie. This means instrumentation logging respects your Rails environment configuration without additional setup.
If you're not using Rails, see the Configuration documentation for details on configuring logging behavior.
Log Level Guidance:
DEBUG- All events logged with full detail (development default)INFO- Important operations like API calls and completions (production default)WARN- Only errors and retries (quiet production)ERROR- Only failures (minimal logging)FATAL- Disable instrumentation logging entirely
Subscribe to specific events or all ActiveAgent events for monitoring, metrics collection, debugging, and integration with external services.
# Subscribe to a specific event
ActiveSupport::Notifications.subscribe("api_call.provider.active_agent") do |event|
duration = event.duration
provider = event.payload[:provider_module]
trace_id = event.payload[:trace_id]
# Your custom handling
Rails.logger.info "AI API call: #{provider} completed in #{duration}ms (trace: #{trace_id})"
end
# Subscribe to all ActiveAgent events
ActiveSupport::Notifications.subscribe(/active_agent/) do |name, start, finish, id, payload|
duration = (finish - start) * 1000
Rails.logger.debug "Event: #{name} (#{duration.round(1)}ms)"
endEach event includes contextual data in the payload hash. Common fields across events:
| Field | Type | Description |
|---|---|---|
trace_id |
String | Unique identifier for tracking related operations across the request lifecycle (optionally set when prompting) |
provider_module |
String | Provider class handling the request (e.g., "OpenAI::Responses") |
message_count |
Integer | Number of messages in the context (varies by event) |
streaming |
Boolean | Whether streaming is enabled for this request |
tool_count |
Integer | Number of tool calls being processed (tool events only) |
usage |
Hash | Token usage information from provider response |
attempt |
Integer | Current retry attempt number (retry events only) |
max_retries |
Integer | Maximum retry attempts configured (retry events only) |
exception |
String | Exception class name (error events only) |
Access duration via event.duration (in milliseconds).
Performance Monitoring:
Track slow API calls and alert when thresholds are exceeded:
ActiveSupport::Notifications.subscribe("api_call.provider.active_agent") do |event|
if event.duration > 5000
SlackNotifier.alert(
"Slow AI API call: #{event.duration}ms",
provider: event.payload[:provider_module],
trace_id: event.payload[:trace_id]
)
end
endCost Tracking:
Monitor token usage and calculate costs by provider:
ActiveSupport::Notifications.subscribe("prompt_complete.provider.active_agent") do |event|
usage = event.payload[:usage]
next unless usage
CostTracker.record(
provider: event.payload[:provider_module],
prompt_tokens: usage[:prompt_tokens],
completion_tokens: usage[:completion_tokens],
total_tokens: usage[:total_tokens],
trace_id: event.payload[:trace_id]
)
endError Tracking:
Capture failures and send to error monitoring service:
ActiveSupport::Notifications.subscribe("retry_exhausted.provider.active_agent") do |event|
Sentry.capture_message(
"AI request failed after #{event.payload[:max_retries]} retries",
level: :error,
extra: {
trace_id: event.payload[:trace_id],
provider: event.payload[:provider_module],
exception: event.payload[:exception]
}
)
endTool Usage Analytics:
Track which tools are being called and how often:
ActiveSupport::Notifications.subscribe("tool_execute.provider.active_agent") do |event|
Analytics.increment(
"agent.tool_usage",
tags: {
tool_name: event.payload[:tool_name],
agent_class: event.payload[:agent_class]
}
)
endCreate a custom log subscriber to control formatting, verbosity, and output destinations:
# config/initializers/active_agent_logging.rb
class CustomAgentLogger < ActiveAgent::LogSubscriber
def api_call(event)
return unless logger.info? # Only log at info level or higher
duration = event.duration.round(1)
provider = event.payload[:provider_module]
info "🤖 #{provider} API call: #{duration}ms"
end
def prompt_complete(event)
return unless logger.info?
message_count = event.payload[:message_count]
duration = event.duration.round(1)
info "✅ Prompt completed: #{message_count} messages in #{duration}ms"
end
def tool_execute(event)
return unless logger.debug?
tool_name = event.payload[:tool_name]
debug "🔧 Tool executed: #{tool_name}"
end
def retry_attempt(event)
attempt = event.payload[:attempt]
max_retries = event.payload[:max_retries]
exception = event.payload[:exception]
warn "⚠️ Retry attempt #{attempt}/#{max_retries} (#{exception})"
end
end
# Replace the default subscriber
ActiveAgent::LogSubscriber.detach_from :active_agent
CustomAgentLogger.attach_to :active_agentSlow generation:
- Check
api_callevent duration - Look for multiple
tool_executeevents (multi-turn overhead) - Check
message_countinrequest_prepared(large context)
Tool execution issues:
- Enable debug logging to see
tool_executeevents - Check
tool_calls_processingfor tool count - Look for
multi_turn_continueto verify conversation flow
Retry behavior:
- Watch for
retry_attemptevents with backoff times - Check
retry_exhaustedfor ultimate failures - Review exception types in retry payloads
- Agents - Learn about agent lifecycle, callbacks, and the generation cycle
- Callbacks - Understand callback hooks like
before_generationandafter_generation - Providers - Explore provider-specific behavior and configuration
- Testing - Test agents and instrumentation in your test suite
- Configuration - Configure instrumentation behavior across environments