Sending OpenTelemetry Signals Directly to Scout Collector Backend
This guide explains how to configure applications to send OpenTelemetry traces, logs, and metrics directly to the Scout backend, without using intermediate collectors or agents.
Data Flow
Application → OpenTelemetry SDK → OTLP Exporter → Scout Backend
The direct export flow consists of:
- Application generates telemetry: The application is instrumented with an OpenTelemetry SDK that exports telemetry signals (traces, metrics, logs)directly into the Scout backend.
- OpenTelemetry SDK: The SDK batches and processes telemetry data
- OTLP Exporter: Data is exported via OTLP (OpenTelemetry Protocol) over HTTP/gRPC
- Authentication: OIDC token-based authentication secures the connection
- Scout Backend: The scout backend receives and processes the telemetry and send them for visualization in the Scout UI. Refer this for more details.
Tradeoffs
Pros:
- Simple to use (especially in a dev/test environment)
- No additional moving parts to operate (in production environments)
Cons:
- Requires code changes if collection, processing, or ingestion changes
- Strong coupling between the application code and the backend
- There are limited number of exporters per language implementation
Required Dependencies
All applications need these core components:
- OpenTelemetry SDK: Core functionality for generating telemetry
- OTLP Exporter: For sending data via OpenTelemetry Protocol over HTTP/gRPC
- Auto-instrumentation libraries: Framework-specific instrumentation (e.g., Rails instrumentation)
- HTTP client: For fetching OIDC tokens
Example: Rails Application
Configuration Changes Required
When sending telemetry directly to Scout backend, your application needs the following changes:
1. Environment Variables
Set these environment variables for your application:
# Service identification
OTEL_SERVICE_NAME=rails-service-name
RAILS_ENV=production # or staging
# Scout collector configuration
SCOUT_ENDPOINT=https://scout-collector-endpoint/v1/traces
SCOUT_CLIENT_ID=your-client-id
SCOUT_CLIENT_SECRET=your-client-secret
SCOUT_TOKEN_URL=https://id.b14.dev/realms/your-tenant/protocol/openid-connect/token
2. Opentelemetry Configuration
Create config/initializers/opentelemetry.rb
:
require "opentelemetry/sdk"
require "opentelemetry/exporter/otlp"
require "opentelemetry/instrumentation/all"
require "net/http"
require "json"
# Function to fetch OIDC token
def fetch_oidc_token
client_id = ENV.fetch("SCOUT_CLIENT_ID")
client_secret = ENV.fetch("SCOUT_CLIENT_SECRET")
token_url = ENV.fetch("SCOUT_TOKEN_URL")
uri = URI(token_url)
# ... (authentication logic)
request = Net::HTTP::Post.new(uri)
request.set_form_data(
"grant_type" => "client_credentials",
"client_id" => client_id,
"client_secret" => client_secret
)
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
if response.is_a?(Net::HTTPSuccess)
JSON.parse(response.body)["access_token"]
else
Rails.logger.error "Failed to fetch OIDC token: #{response.body}"
nil
end
end
# Configure OpenTelemetry
OpenTelemetry::SDK.configure do |c|
endpoint = ENV.fetch("SCOUT_ENDPOINT")
resource = OpenTelemetry::SDK::Resources::Resource.create(
{
'service.name' => ENV.fetch("OTEL_SERVICE_NAME", "default-service"),
'deployment.environment' => ENV.fetch("RAILS_ENV", "development")
}
)
c.resource = resource
# Fetch authentication token
token = fetch_oidc_token
headers = {}
headers["Authorization"] = "Bearer #{token}" if token
# Configure OTLP exporter to send telemetry to Scout OTel ingestor
otlp_exporter = OpenTelemetry::Exporter::OTLP::Exporter.new(
endpoint: endpoint,
headers: headers
)
# Add span processor
c.add_span_processor(
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(otlp_exporter)
)
# Enable all available instrumentation
c.use_all()
end
3. Application Dependencies
Ensure your application has the required OpenTelemetry packages installed and configured for direct export.
Essential Configuration Requirements
- Service Name and Environment (Critical) Always ensure these attributes are properly set.
# In your OpenTelemetry configuration
# Add environment as resource attribute
c.resource = OpenTelemetry::SDK::Resources::Resource.create({
"service.name" => ENV.fetch("OTEL_SERVICE_NAME", "rails-service-name"),
"service.version" => "1.0.0",
"deployment.environment" => ENV.fetch("RAILS_ENV", "development")
})
Authentication Options
When deploying without collector, you have several authentication options:
OIDC Token Authentication (Recommended)
# Token refresh logic (implement based on your needs)
def fetch_oidc_token
# Implement token caching and refresh logic
# Handle token expiration
# Include proper error handling
end
Production Considerations
- Token Management: Implement proper token refresh and error handling
- Retry Logic: Add exponential backoff for failed exports
- Monitoring: Monitor export success/failure rates
- Performance: Consider batch size and export intervals
- Security: Secure credential management
Troubleshooting
Common Issues
- Authentication failures: Check OIDC credentials and token URL
- Network connectivity: Verify endpoint accessibility
- Performance impact: Monitor application overhead