OpenTelemetry RubyLLM Instrumentation

OpenTelemetry instrumentation for RubyLLM.

How do I get started?

Install the gem using:

gem opentelemetry-instrumentation-ruby_llm

Or, if you use bundler, include opentelemetry-instrumentation-ruby_llm in your Gemfile.

Usage

To use the instrumentation, call use with the name of the instrumentation:

OpenTelemetry::SDK.configure do |c|
  c.use 'OpenTelemetry::Instrumentation::RubyLLM'
end

Alternatively, you can also call use_all to install all the available instrumentation.

OpenTelemetry::SDK.configure do |c|
  c.use_all
end

Configuration

Content capture

By default, message content is not captured. To enable it:

OpenTelemetry::SDK.configure do |c|
  c.use 'OpenTelemetry::Instrumentation::RubyLLM', capture_content: true
end

Or set the environment variable:

export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true

When enabled, the following attributes are added to chat spans:

Attribute Description
gen_ai.system_instructions System instructions provided via with_instructions
gen_ai.input.messages Input messages sent to the model
gen_ai.output.messages Final output messages from the model

[!WARNING] Captured content may include sensitive or personally identifiable information (PII). Use with caution in production environments.

Custom attributes

Use with_otel_attributes to add arbitrary attributes to the span for each request. This is useful for adding per-request metadata like Langfuse prompt linking or trace-level tags:

chat = RubyLLM.chat
chat.with_otel_attributes(
  "langfuse.observation.prompt.name" => "supplement-assistant",
  "langfuse.observation.prompt.version" => 1,
  "langfuse.trace.tags" => ["vitamins"],
  "langfuse.trace.metadata" => { category: "health" }.to_json
)
chat.ask("What are the side effects of Vitamin D3?")

Values can also be callables (Procs/lambdas) that are evaluated after each completion, giving access to response data:

chat.with_otel_attributes(
  "langfuse.observation.prompt.name" => "supplement-assistant",
  "langfuse.observation.output" => -> { chat.messages.last&.content.to_s }
)

Attributes persist across calls on the same chat instance and the method returns self for chaining.

What's traced?

Feature Status
Chat completions Supported
Tool calls Supported
Error handling Supported
Opt-in input/output content capture Supported
Conversation tracking (gen_ai.conversation.id) Planned
System instructions capture Supported (via capture_content)
Custom attributes on traces and spans Supported (via with_otel_attributes)
Embeddings Planned
Streaming Planned

This gem follows the OpenTelemetry GenAI Semantic Conventions.

License

Copyright (c) Clarissa Borges and thoughtbot, inc.

This gem is free software and may be redistributed under the terms specified in the LICENSE file.

About thoughtbot

thoughtbot

This repo is maintained and funded by thoughtbot, inc. The names and logos for thoughtbot are trademarks of thoughtbot, inc.

We love open source software! See our other projects. We are available for hire.