Skip to content

Commit

Permalink
feat: Add configuration patch to set metrics exporter by environment …
Browse files Browse the repository at this point in the history
…variable

The environment variable has options for:
* console (default)
* otlp
* in-memory
* none

Like the Traces exporter, more than one exporter can be configured
  • Loading branch information
kaylareopelle committed Jul 10, 2024
1 parent 406cabe commit f0c7663
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 1 deletion.
41 changes: 41 additions & 0 deletions metrics_sdk/lib/opentelemetry/sdk/metrics/configuration_patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,53 @@ module Metrics
# The ConfiguratorPatch implements a hook to configure the metrics
# portion of the SDK.
module ConfiguratorPatch
def add_metric_reader(metric_reader)
@metric_readers << metric_reader
end

private

def initialize
super
@metric_readers = []
end

# The metrics_configuration_hook method is where we define the setup process
# for metrics SDK.
def metrics_configuration_hook
OpenTelemetry.meter_provider = Metrics::MeterProvider.new(resource: @resource)
configure_metric_readers
end

def configure_metric_readers
readers = @metric_readers.empty? ? wrapped_metric_exporters_from_env.compact : @metric_readers
readers.each { |r| OpenTelemetry.meter_provider.add_metric_reader(r) }
end

def wrapped_metric_exporters_from_env
exporters = ENV.fetch('OTEL_METRICS_EXPORTER', 'console')

exporters.split(',').map do |exporter|
case exporter.strip
when 'none' then nil
when 'console'
OpenTelemetry.meter_provider.add_metric_reader(Metrics::Export::ConsoleMetricPullExporter.new)
when 'in-memory'
OpenTelemetry.meter_provider.add_metric_reader(Metrics::Export::InMemoryMetricPullExporter.new)
when 'otlp'
begin
OpenTelemetry.meter_provider.add_metric_reader(OpenTelemetry::Exporter::OTLP::MetricsExporter.new)
rescue NameError
OpenTelemetry.logger.warn 'The otlp metrics exporter cannot be configured - please add ' \
'opentelemetry-exporter-otlp-metrics to your Gemfile, metrics will not be exported'
nil
end
else
OpenTelemetry.logger.warn "The #{exporter} exporter is unknown and cannot be configured, " \
'metrics will not be exported'
nil
end
end
end
end
end
Expand Down
108 changes: 108 additions & 0 deletions metrics_sdk/test/opentelemetry/sdk/metrics/configuration_patch_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# frozen_string_literal: true

# Copyright The OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

require 'test_helper'

describe OpenTelemetry::SDK::Metrics::ConfiguratorPatch do
let(:configurator) { OpenTelemetry::SDK::Configurator.new }
let(:default_resource_attributes) do
{
'telemetry.sdk.name' => 'opentelemetry',
'telemetry.sdk.language' => 'ruby',
'telemetry.sdk.version' => OpenTelemetry::SDK::VERSION,
'process.pid' => Process.pid,
'process.command' => $PROGRAM_NAME,
'process.runtime.name' => RUBY_ENGINE,
'process.runtime.version' => RUBY_VERSION,
'process.runtime.description' => RUBY_DESCRIPTION,
'service.name' => 'unknown_service'
}
end

def setup
# Suppress log warnings about trace exporter absence
ENV['OTEL_TRACES_EXPORTER'] = 'none'
end

def teardown
# Let the settings go back to their default
ENV['OTEL_TRACES_EXPORTER'] = nil
end

describe '#configure' do
describe 'meter_provider' do
it 'is an instance of SDK::Metrics::MeterProvider' do
configurator.configure

_(OpenTelemetry.meter_provider).must_be_instance_of(
OpenTelemetry::SDK::Metrics::MeterProvider
)
end
end

describe 'metric readers' do
it 'defaults to the console reader' do
configurator.configure

assert_equal 1, OpenTelemetry.meter_provider.metric_readers.size
assert_instance_of OpenTelemetry::SDK::Metrics::Export::ConsoleMetricPullExporter, OpenTelemetry.meter_provider.metric_readers[0]
end

it 'can be set by environment variable' do
OpenTelemetry::TestHelpers.with_env('OTEL_METRICS_EXPORTER' => 'in-memory') do
configurator.configure
end

assert_equal 1, OpenTelemetry.meter_provider.metric_readers.size
assert_instance_of OpenTelemetry::SDK::Metrics::Export::InMemoryMetricPullExporter, OpenTelemetry.meter_provider.metric_readers[0]
end

it 'supports "none" as an environment variable' do
OpenTelemetry::TestHelpers.with_test_logger do |log_stream|
OpenTelemetry::TestHelpers.with_env('OTEL_METRICS_EXPORTER' => 'none') do
configurator.configure
end

assert_empty OpenTelemetry.meter_provider.metric_readers

refute_match(/The none exporter is unknown and cannot be configured/, log_stream.string)
end
end

it 'supports multiple exporters passed by environment variable' do
OpenTelemetry::TestHelpers.with_env('OTEL_METRICS_EXPORTER' => 'in-memory,console') do
configurator.configure
end

assert_equal 2, OpenTelemetry.meter_provider.metric_readers.size
assert_instance_of OpenTelemetry::SDK::Metrics::Export::InMemoryMetricPullExporter, OpenTelemetry.meter_provider.metric_readers[0]
assert_instance_of OpenTelemetry::SDK::Metrics::Export::ConsoleMetricPullExporter, OpenTelemetry.meter_provider.metric_readers[1]
end

it 'defaults to noop with invalid env var' do
OpenTelemetry::TestHelpers.with_test_logger do |log_stream|
OpenTelemetry::TestHelpers.with_env('OTEL_METRICS_EXPORTER' => 'unladen_swallow') do
configurator.configure
end

assert_empty OpenTelemetry.meter_provider.metric_readers
assert_match(/The unladen_swallow exporter is unknown and cannot be configured/, log_stream.string)
end
end

it 'rescues NameErrors when otlp set to env var and the library is not installed' do
OpenTelemetry::TestHelpers.with_test_logger do |log_stream|
OpenTelemetry::TestHelpers.with_env('OTEL_METRICS_EXPORTER' => 'otlp') do
configurator.configure
end

assert_empty OpenTelemetry.meter_provider.metric_readers
assert_match(/The otlp exporter cannot be configured - please add opentelemetry-exporter-otlp-metrics to your Gemfile, metrics will not be exported/, log_stream.string)
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
describe OpenTelemetry::SDK::Metrics::MeterProvider do
before do
reset_metrics_sdk
OpenTelemetry::SDK.configure
# The MeterProvider tests deal with mock MetricReaders that are manually added
# Run the tests without the configuration patch interfering with the setup
OpenTelemetry::TestHelpers.with_env('OTEL_METRICS_EXPORTER' => 'none') do
OpenTelemetry::SDK.configure
end
end

describe '#meter' do
Expand Down
3 changes: 3 additions & 0 deletions metrics_sdk/test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ def with_test_logger
ensure
OpenTelemetry.logger = original_logger
end

# Suppress warn-level logs about a missing OTLP exporter for traces
ENV['OTEL_TRACES_EXPORTER'] = 'none'

0 comments on commit f0c7663

Please sign in to comment.