Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update metrics configuration patch #1548

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mwear @xuan-cao-swi - The specs state that OTLP should be the default exporter or OTEL_METRICS_EXPORTER, so I updated the tests to reflect this and installed the OTLP exporter in the test group of the Gemile.

However, the OTLP exporter brings in the protobuf dependencies, making the entire metrics_sdk test suite incompatible with JRuby.

It seems like the tracing test suite gets around this by avoiding any mention of the OTLP exporter in the tests, even though the spec also expects OTLP to be the default exporter for that signal (the tests use zipkin instead).

I don't want to skip JRuby for all tests in the metrics_sdk.

My current thoughts for solutions are:

  1. conditionally install the OTLP exporter in the test environment if JRuby is present and skip the related tests if JRuby is present
  2. omit the OTLP exporter from the tests entirely, and bring in an alternate exporter for the tests, following the pattern for traces (in-memory metrics exporter seems like the best candidate, even though it's not part of the spec)
  3. something else...?

What do y'all think would be the best next step?

begin
OpenTelemetry.meter_provider.add_metric_reader(OpenTelemetry::Exporter::OTLP::MetricsExporter.new)
kaylareopelle marked this conversation as resolved.
Show resolved Hide resolved
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
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 metrics 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'
Loading