This guide provides detailed steps on how to configure OpenTelemetry in a Ruby application to send telemetry data to Axiom using the OpenTelemetry Ruby SDK.

Prerequisites

Set up the Ruby on Rails application

  1. Create a new Rails app using the rails new myapp command.
  2. Go to the app directory with the cd myapp command.
  3. Open the Gemfile and add the following OpenTelemetry packages:
gem 'opentelemetry-api'
gem 'opentelemetry-sdk'
gem 'opentelemetry-exporter-otlp'
gem 'opentelemetry-instrumentation-rails'
gem 'opentelemetry-instrumentation-http'
gem 'opentelemetry-instrumentation-active_record', require: false
gem 'opentelemetry-instrumentation-all'

Install the dependencies by running bundle install.

Configure the OpenTelemetry exporter

In the initializers folder of your Rails app, create a new file called opentelemetry.rb, and then add the following OpenTelemetry exporter configuration:

require 'opentelemetry/sdk'
require 'opentelemetry/exporter/otlp'
require 'opentelemetry/instrumentation/all'

OpenTelemetry::SDK.configure do |c|
  c.service_name = 'ruby-traces' # Set your service name
  
  c.use_all # Or specify individual instrumentation you need

  c.add_span_processor(
    OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
      OpenTelemetry::Exporter::OTLP::Exporter.new(
        endpoint: 'https://api.axiom.co/v1/traces',
        headers: {
          'Authorization' => 'Bearer API_TOKEN',
          'X-AXIOM-DATASET' => 'DATASET_NAME'
        }
      )
    )
  )
end

In the code above, make the following changes:

  • Replace API_TOKEN with your Axiom API key.
  • Replace DATASET_NAME with the name of the Axiom dataset where you want to send data.

Run the instrumented application

Run your Ruby on Rails application with OpenTelemetry instrumentation.

In development mode

Start the Rails server using the rails server command. The server will start on the default port (usually 3000), and you can access your application by visiting http://localhost:3000 in your web browser.

As you interact with your application, OpenTelemetry automatically collects telemetry data and sends it to Axiom using the configured OTLP exporter.

In production mode

For production, ensure to precompile assets and run migrations if necessary. Start the server with RAILS_ENV=production bin/rails server. This setup ensures your Ruby application is instrumented to send traces to Axiom, using OpenTelemetry for observability.

Observe the telemetry data in Axiom

As you interact with your application, traces are collected and exported to Axiom, allowing you to monitor, analyze, and gain insights into your application’s performance and behavior.

  1. In your Axiom account and click on the Datasets or Stream tab.

  2. Select your dataset from the list.

  3. From the list of fields, click on the trace_id to view your spans.

Dynamic OpenTelemetry Traces dashboard

This data can then be further viewed and analyzed in Axiom’s dashboard, offering a deeper understanding of your application’s performance and behavior.

  1. In your Axiom account, select Dashboards, and click on the traces dashboard named after your dataset.

  2. View the dashboard which displays your total traces, incoming spans, average span duration, errors, slowest operations, and top 10 span errors across services.

Send data from an existing Ruby app

Manual instrumentation

Manual instrumentation allows users to define and manage telemetry data collection points within their Ruby applications, providing granular control over what is traced.

  1. Initialize Tracer. Use the OpenTelemetry API to obtain a tracer from the global tracer provider. This tracer will be used to start and manage spans.
tracer = OpenTelemetry.tracer_provider.tracer('my-tracer')
  1. Manually start a span at the beginning of the block of code you want to trace and ensure to end it when your operations complete. This is useful for gathering detailed data about specific operations.
span = tracer.start_span('operation_name')
begin
  # Perform operation
rescue => e
  span.record_exception(e)
  span.status = OpenTelemetry::Trace::Status.error("Operation failed")
ensure
  span.finish
end
  1. Enhance spans with custom attributes to provide additional context about the traced operations, helping in debugging and monitoring performance.
span.set_attribute("user_id", user.id)
span.add_event("query_executed", attributes: { "query" => sql_query })

Automatic instrumentation

Automatic instrumentation in Ruby uses OpenTelemetry’s libraries to automatically generate telemetry data for common operations, such as HTTP requests and database queries.

  1. Set up the OpenTelemetry SDK with the necessary instrumentation libraries in your Ruby application. This typically involves modifying the Gemfile and an initializer to set up the SDK and auto-instrumentation.
# In config/initializers/opentelemetry.rb
OpenTelemetry::SDK.configure do |c|
  c.service_name = 'ruby-traces'
  c.use_all  # Automatically use all available instrumentation
end
  1. Ensure your Gemfile includes gems for the automatic instrumentation of the frameworks and libraries your application uses.
gem 'opentelemetry-instrumentation-rails'
gem 'opentelemetry-instrumentation-http'
gem 'opentelemetry-instrumentation-active_record'

After setting up, no additional manual changes are required for basic telemetry data collection. The instrumentation libraries handle the creation and management of telemetry data automatically.

Reference

List of OpenTelemetry trace fields

Field CategoryField NameDescription
General Trace Information
_rowIdUnique identifier for each row in the trace data.
_sysTimeSystem timestamp when the trace data was recorded.
_timeTimestamp when the actual event being traced occurred.
trace_idUnique identifier for the entire trace.
span_idUnique identifier for the span within the trace.
parent_span_idUnique identifier for the parent span within the trace.
HTTP Attributes
attributes.http.methodHTTP method used for the request.
attributes.http.status_codeHTTP status code returned in response.
attributes.http.targetSpecific target of the HTTP request.
attributes.http.schemeProtocol scheme (HTTP/HTTPS).
User Agent
attributes.http.user_agentUser agent string, providing client software and OS.
Custom Attributes
attributes.custom[“http.host”]Host information where the HTTP request was sent.
attributes.custom.identifierPath to a file or identifier in the trace context.
attributes.custom.layoutLayout used in the rendering process of a view or template.
Resource Process Attributes
resource.process.commandCommand line string used to start the process.
resource.process.pidProcess ID.
resource.process.runtime.descriptionDescription of the runtime environment.
resource.process.runtime.nameName of the runtime environment.
resource.process.runtime.versionVersion of the runtime environment.
Operational Details
durationTime taken for the operation.
kindType of span (e.g., server, client, internal).
nameName of the span, often a high-level title for the operation.
Code Attributes
attributes.code.functionFunction or method being executed.
attributes.code.namespaceNamespace or module that includes the function.
Scope Attributes
scope.nameName of the scope for the operation.
scope.versionVersion of the scope.
Service Attributes
service.nameName of the service generating the trace.
service.versionVersion of the service generating the trace.
service.instance.idUnique identifier for the instance of the service.
Telemetry SDK Attributes
telemetry.sdk.languageLanguage of the telemetry SDK, e.g., ruby.
telemetry.sdk.nameName of the telemetry SDK, e.g., opentelemetry.
telemetry.sdk.versionVersion of the telemetry SDK, e.g., 1.4.1.

List of imported libraries

gem 'opentelemetry-api'

The opentelemetry-api gem provides the core OpenTelemetry API for Ruby. It defines the basic concepts and interfaces for distributed tracing, such as spans, tracers, and context propagation. This gem is essential for instrumenting your Ruby application with OpenTelemetry.

gem 'opentelemetry-sdk'

The opentelemetry-sdk gem is the OpenTelemetry SDK for Ruby. It provides the implementation of the OpenTelemetry API, including the tracer provider, span processors, and exporters. This gem is responsible for managing the lifecycle of spans and sending them to the specified backend.

gem 'opentelemetry-exporter-otlp'

The opentelemetry-exporter-otlp gem is an exporter that sends trace data to a backend that supports the OpenTelemetry Protocol (OTLP), such as Axiom. It formats the trace data according to the OTLP standards and transmits it over HTTP or gRPC, ensuring compatibility and standardization in how telemetry data is sent across different systems and services.

gem 'opentelemetry-instrumentation-rails'

The opentelemetry-instrumentation-rails gem provides automatic instrumentation for Ruby on Rails applications. It integrates with various aspects of a Rails application, such as controllers, views, and database queries, to capture relevant trace data without requiring manual instrumentation. This gem simplifies the process of adding tracing to your Rails application.

gem 'opentelemetry-instrumentation-http'

The opentelemetry-instrumentation-http gem provides automatic instrumentation for HTTP requests made using the Net::HTTP library. It captures trace data for outgoing HTTP requests, including request headers, response status, and timing information. This gem helps in tracing the external dependencies of your application.

gem 'opentelemetry-instrumentation-active_record', require: false

The opentelemetry-instrumentation-active_record gem provides automatic instrumentation for ActiveRecord, the Object-Relational Mapping (ORM) library used in Ruby on Rails. It captures trace data for database queries, including the SQL statements executed and their duration. This gem helps in identifying performance bottlenecks related to database interactions.

gem 'opentelemetry-instrumentation-all'

The opentelemetry-instrumentation-all gem is a meta-gem that includes all the available instrumentation libraries for OpenTelemetry in Ruby. It provides a convenient way to install and configure multiple instrumentation libraries at once, covering various aspects of your application, such as HTTP requests, database queries, and external libraries. This gem simplifies the setup process and ensures comprehensive tracing coverage for your Ruby application.