Skip to content

Commit dcd16e4

Browse files
committed
test: test helpers for metrics
1 parent 19b5fbe commit dcd16e4

File tree

5 files changed

+163
-7
lines changed

5 files changed

+163
-7
lines changed

test_helpers/README.md

+40
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,46 @@ gem install opentelemetry-test-helpers
2222

2323
Or, if you use [bundler][bundler-home], include `opentelemetry-test-helpers` in your `Gemfile`.
2424

25+
## Testing with metrics
26+
27+
The `metrics` module facilitates testing instrumentation libraries with respect to the OpenTelemetry Metrics API and SDK. It is not required by default. It is designed to work with or without the metrics API and SDK defined, but you may experience issues if the API or SDK gem is in your Gemfile but not yet loaded when the test helpers are initialized.
28+
29+
### Usage
30+
31+
In a test_helper.rb, after the `configure` block,
32+
require this library:
33+
34+
```ruby
35+
OpenTelemetry::SDK.configure do |c|
36+
c.error_handler = ->(exception:, message:) { raise(exception || message) }
37+
c.add_span_processor span_processor
38+
end
39+
require 'opentelemetry/test_helpers/metrics'
40+
```
41+
42+
If the library uses Appraisals, it is recommended to appraise with and without the metrics api and sdk gems. Note that any metrics implementation in instrumentation libraries should be written against the API only, but for testing the SDK is required to collect metrics data - testing under all three scenarios (no metrics at all, api only, and with the sdk) helps ensure compliance with this requirement.
43+
44+
In a test:
45+
46+
```ruby
47+
with_metrics_sdk do
48+
let(:metric_snapshots) do
49+
metrics_exporter.tap(&:pull)
50+
.metric_snapshots.select { |snapshot| snapshot.data_points.any? }
51+
.group_by(&:name)
52+
end
53+
54+
it "uses metrics", with_metrics_sdk: true do
55+
# do something here ...
56+
_(metric_snapshots).count.must_equal(4)
57+
end
58+
end
59+
```
60+
61+
- `metrics_exporter` is automatically reset before each test.
62+
- `#with_metrics_sdk` will only yield if the SDK is present.
63+
- `#with_metrics_api` will only yield if the API is present
64+
2565
## How can I get involved?
2666

2767
The `opentelemetry-test-helpers` gem source is [on github][repo-github], along with related gems including `opentelemetry-api`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
require 'minitest/spec'
8+
9+
module OpenTelemetry
10+
module TestHelpers
11+
# Convenience features and Minitest extensions to support testing
12+
# around the metrics-api or metrics-sdk libraries.
13+
module Metrics
14+
module LoadedMetricsFeatures
15+
OTEL_METRICS_API_LOADED = !Gem.loaded_specs['opentelemetry-metrics-api'].nil?
16+
OTEL_METRICS_SDK_LOADED = !Gem.loaded_specs['opentelemetry-metrics-sdk'].nil?
17+
18+
extend self
19+
20+
def api_loaded?
21+
OTEL_METRICS_API_LOADED
22+
end
23+
24+
def sdk_loaded?
25+
OTEL_METRICS_SDK_LOADED
26+
end
27+
end
28+
29+
module MinitestExtensions
30+
def self.prepended(base)
31+
base.extend(self)
32+
end
33+
34+
def self.included(base)
35+
base.extend(self)
36+
end
37+
38+
def before_setup
39+
super
40+
reset_metrics_exporter
41+
end
42+
43+
def with_metrics_sdk
44+
yield if LoadedMetricsFeatures.sdk_loaded?
45+
end
46+
47+
def without_metrics_sdk
48+
yield unless LoadedMetricsFeatures.sdk_loaded?
49+
end
50+
51+
def metrics_exporter
52+
with_metrics_sdk { METRICS_EXPORTER }
53+
end
54+
55+
def reset_meter_provider
56+
with_metrics_sdk do
57+
resource = OpenTelemetry.meter_provider.resource
58+
OpenTelemetry.meter_provider = OpenTelemetry::SDK::Metrics::MeterProvider.new(resource: resource)
59+
OpenTelemetry.meter_provider.add_metric_reader(METRICS_EXPORTER)
60+
end
61+
end
62+
63+
def reset_metrics_exporter
64+
with_metrics_sdk do
65+
METRICS_EXPORTER.pull
66+
METRICS_EXPORTER.reset
67+
end
68+
end
69+
70+
def it(desc = 'anonymous', with_metrics_sdk: false, without_metrics_sdk: false, &block)
71+
return super(desc, &block) unless with_metrics_sdk || without_metrics_sdk
72+
73+
raise ArgumentError, 'without_metrics_sdk and with_metrics_sdk must be mutually exclusive' if without_metrics_sdk && with_metrics_sdk
74+
75+
return if with_metrics_sdk && !LoadedMetricsFeatures.sdk_loaded?
76+
return if without_metrics_sdk && LoadedMetricsFeatures.sdk_loaded?
77+
78+
super(desc, &block)
79+
end
80+
end
81+
82+
if LoadedMetricsFeatures.sdk_loaded?
83+
METRICS_EXPORTER = OpenTelemetry::SDK::Metrics::Export::InMemoryMetricPullExporter.new
84+
OpenTelemetry.meter_provider.add_metric_reader(METRICS_EXPORTER)
85+
end
86+
87+
Minitest::Spec.prepend(MinitestExtensions)
88+
end
89+
end
90+
end

test_helpers/opentelemetry-test-helpers.gemspec

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ Gem::Specification.new do |spec|
2525
spec.require_paths = ['lib']
2626
spec.required_ruby_version = '>= 3.0'
2727

28+
spec.add_dependency 'minitest', '~> 5.0'
29+
2830
spec.add_development_dependency 'bundler', '>= 1.17'
29-
spec.add_development_dependency 'minitest', '~> 5.0'
3031
spec.add_development_dependency 'opentelemetry-sdk'
3132
spec.add_development_dependency 'pry'
3233
spec.add_development_dependency 'pry-byebug' unless RUBY_ENGINE == 'jruby'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
require 'test_helper'
8+
9+
require 'opentelemetry/test_helpers/metrics' # not loaded by default
10+
11+
describe OpenTelemetry::TestHelpers::Metrics do
12+
describe 'dependencies' do
13+
let(:gemspec) { Gem.loaded_specs.fetch('opentelemetry-test-helpers') }
14+
let(:dependencies) { gemspec.dependencies.map(&:name) }
15+
16+
# NOTE: The `metrics` module here is intended to facilitate testing
17+
# for instrumentation libraries that should function with or without
18+
# the metrics-api in the bundle. Including it in this test helper
19+
# should be considered a mistake unless additional provisions are made to preserve
20+
# this feature.
21+
it 'does not include the api or sdk gems' do
22+
_(dependencies).wont_include('opentelemetry-metrics-sdk')
23+
_(dependencies).wont_include('opentelemetry-metrics-api')
24+
end
25+
end
26+
end

test_helpers/test/test_helper.rb

+5-6
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

7-
require 'opentelemetry-sdk'
8-
require 'opentelemetry-test-helpers'
9-
require 'minitest/autorun'
10-
require 'pry'
11-
127
if RUBY_ENGINE == 'ruby'
138
require 'simplecov'
149
SimpleCov.start
15-
SimpleCov.minimum_coverage 85
10+
SimpleCov.minimum_coverage 70
1611
end
12+
require 'opentelemetry-sdk'
13+
require 'opentelemetry-test-helpers'
14+
require 'minitest/autorun'
15+
require 'pry'

0 commit comments

Comments
 (0)