Skip to content

Commit 4d60d62

Browse files
committed
test: add metrics-test-helpers
1 parent ce01f6d commit 4d60d62

13 files changed

+332
-0
lines changed
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gemfiles
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# frozen_string_literal: true
2+
3+
appraise 'metrics-sdk' do
4+
gem 'opentelemetry-metrics-sdk'
5+
end
6+
7+
appraise 'metrics-api' do
8+
gem 'opentelemetry-metrics-api'
9+
end
10+
11+
appraise 'base' do # rubocop: disable Lint/EmptyBlock
12+
end

helpers/metrics-test-helpers/Gemfile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
source 'https://rubygems.org'
4+
5+
# Specify your gem's dependencies in opentelemetry-metrics-test-helpers.gemspec
6+
gemspec
7+
8+
gem 'rake', '~> 13.0'
9+
gem 'minitest', '~> 5.16'
10+
gem 'opentelemetry-sdk'
11+
gem 'pry-byebug'
+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# OpenTelemetry Instrumentation Test Helpers: Metrics
2+
3+
This Ruby gem facilitates testing instrumentation libraries with respect to the OpenTelemetry Metrics API and SDK.
4+
5+
## Usage
6+
7+
Add the gem to your instrumentation's Gemfile:
8+
9+
```ruby
10+
# Gemfile
11+
12+
group :test, :development do
13+
gem 'opentelemetry-metrics-test-helpers', path: '../../helpers/metrics-test-helpers', require: false
14+
end
15+
```
16+
17+
It's not necessary to add this gem as a development dependency in the gemspec.
18+
`opentelemetry-metrics-test-helpers` is not currently published to RubyGems,
19+
and it is expected that it will always be bundled from the source in this
20+
repository.
21+
22+
Note that metrics-test-helpers makes no attempt to require
23+
the metrics API or SDK. 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 the gemfile but not yet loaded when the test helpers are initialized.
24+
25+
## Examples
26+
27+
In a test_helper.rb, after the `configure` block,
28+
require this library:
29+
30+
```ruby
31+
OpenTelemetry::SDK.configure do |c|
32+
c.error_handler = ->(exception:, message:) { raise(exception || message) }
33+
c.add_span_processor span_processor
34+
end
35+
require 'opentelemetry-metrics-test-helpers'
36+
```
37+
38+
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.
39+
40+
In a test:
41+
42+
```ruby
43+
with_metrics_sdk do
44+
let(:metric_snapshots) do
45+
metrics_exporter.tap(&:pull)
46+
.metric_snapshots.select { |snapshot| snapshot.data_points.any? }
47+
.group_by(&:name)
48+
end
49+
50+
it "uses metrics", with_metrics_sdk: true do
51+
# do something here ...
52+
_(metric_snapshots).count.must_equal(4)
53+
end
54+
end
55+
```
56+
57+
- `metrics_exporter` is automatically reset before each test.
58+
- `#with_metrics_sdk` will only yield if the SDK is present.
59+
- `#with_metrics_api` will only yield if the API is present
60+
61+
## How can I get involved?
62+
63+
The `opentelemetry-metrics-test-helpers` gem source is [on github][repo-github], along with related gems including `opentelemetry-instrumentation-pg` and `opentelemetry-instrumentation-trilogy`.
64+
65+
The OpenTelemetry Ruby gems are maintained by the OpenTelemetry Ruby special interest group (SIG). You can get involved by joining us on our [GitHub Discussions][discussions-url], [Slack Channel][slack-channel] or attending our weekly meeting. See the [meeting calendar][community-meetings] for dates and times. For more information on this and other language SIGs, see the OpenTelemetry [community page][ruby-sig].
66+
67+
## License
68+
69+
The `opentelemetry-helpers-sql-obfuscation` gem is distributed under the Apache 2.0 license. See [LICENSE][license-github] for more information.
70+
71+
[repo-github]: https://github.com/open-telemetry/opentelemetry-ruby
72+
[license-github]: https://github.com/open-telemetry/opentelemetry-ruby-contrib/blob/main/LICENSE
73+
[ruby-sig]: https://github.com/open-telemetry/community#ruby-sig
74+
[community-meetings]: https://github.com/open-telemetry/community#community-meetings
75+
[slack-channel]: https://cloud-native.slack.com/archives/C01NWKKMKMY
76+
[discussions-url]: https://github.com/open-telemetry/opentelemetry-ruby/discussions

helpers/metrics-test-helpers/Rakefile

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
require 'bundler/gem_tasks'
8+
require 'rake/testtask'
9+
require 'rubocop/rake_task'
10+
11+
RuboCop::RakeTask.new
12+
13+
Rake::TestTask.new do |t|
14+
t.libs << 'test'
15+
t.libs << 'lib'
16+
t.test_files = FileList['test/**/*_test.rb']
17+
t.warning = false
18+
end
19+
20+
if RUBY_ENGINE == 'truffleruby'
21+
task default: %i[test]
22+
else
23+
task default: %i[test rubocop]
24+
end
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
require 'bundler/setup'
5+
require 'opentelemetry/metrics/test/helpers'
6+
7+
# You can add fixtures and/or initialization code here to make experimenting
8+
# with your gem easier. You can also use a different console, if you like.
9+
10+
require 'irb'
11+
IRB.start(__FILE__)
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
IFS=$'\n\t'
4+
set -vx
5+
6+
bundle install
7+
8+
# Do any other automated setup that you need to do here
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
require_relative 'opentelemetry/metrics_test_helpers'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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 MetricsTestHelpers
11+
module LoadedMetricsFeatures
12+
OTEL_METRICS_API_LOADED = !Gem.loaded_specs['opentelemetry-metrics-api'].nil?
13+
OTEL_METRICS_SDK_LOADED = !Gem.loaded_specs['opentelemetry-metrics-sdk'].nil?
14+
15+
extend self
16+
17+
def api_loaded?
18+
OTEL_METRICS_API_LOADED
19+
end
20+
21+
def sdk_loaded?
22+
OTEL_METRICS_SDK_LOADED
23+
end
24+
end
25+
26+
module MinitestExtensions
27+
def self.prepended(base)
28+
base.extend(self)
29+
end
30+
31+
def self.included(base)
32+
base.extend(self)
33+
end
34+
35+
def before_setup
36+
super
37+
reset_metrics_exporter
38+
end
39+
40+
def with_metrics_sdk
41+
yield if LoadedMetricsFeatures.sdk_loaded?
42+
end
43+
44+
def without_metrics_sdk
45+
yield unless LoadedMetricsFeatures.sdk_loaded?
46+
end
47+
48+
def metrics_exporter
49+
with_metrics_sdk { METRICS_EXPORTER }
50+
end
51+
52+
def reset_meter_provider
53+
with_metrics_sdk do
54+
resource = OpenTelemetry.meter_provider.resource
55+
OpenTelemetry.meter_provider = OpenTelemetry::SDK::Metrics::MeterProvider.new(resource: resource)
56+
OpenTelemetry.meter_provider.add_metric_reader(METRICS_EXPORTER)
57+
end
58+
end
59+
60+
def reset_metrics_exporter
61+
with_metrics_sdk do
62+
METRICS_EXPORTER.pull
63+
METRICS_EXPORTER.reset
64+
end
65+
end
66+
67+
def it(desc = 'anonymous', with_metrics_sdk: false, without_metrics_sdk: false, &block)
68+
return super(desc, &block) unless with_metrics_sdk || without_metrics_sdk
69+
70+
raise ArgumentError, 'without_metrics_sdk and with_metrics_sdk must be mutually exclusive' if without_metrics_sdk && with_metrics_sdk
71+
72+
return if with_metrics_sdk && !LoadedMetricsFeatures.sdk_loaded?
73+
return if without_metrics_sdk && LoadedMetricsFeatures.sdk_loaded?
74+
75+
super(desc, &block)
76+
end
77+
end
78+
79+
if LoadedMetricsFeatures.sdk_loaded?
80+
METRICS_EXPORTER = OpenTelemetry::SDK::Metrics::Export::InMemoryMetricPullExporter.new
81+
OpenTelemetry.meter_provider.add_metric_reader(METRICS_EXPORTER)
82+
end
83+
84+
Minitest::Spec.prepend(MinitestExtensions)
85+
end
86+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
module OpenTelemetry
8+
module MetricsTestHelpers
9+
VERSION = '0.0.1'
10+
end
11+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# frozen_string_literal: true
2+
3+
require_relative 'lib/opentelemetry/metrics_test_helpers/version'
4+
5+
Gem::Specification.new do |spec|
6+
spec.name = 'opentelemetry-metrics-test-helpers'
7+
spec.version = OpenTelemetry::MetricsTestHelpers::VERSION
8+
spec.authors = ['OpenTelemetry Authors']
9+
spec.email = ['[email protected]']
10+
11+
spec.summary = 'Test helpers for adding metrics to instrumentation libraries'
12+
spec.homepage = 'https://github.com/open-telemetry/opentelemetry-ruby-contrib'
13+
spec.required_ruby_version = '>= 2.7.0'
14+
spec.license = 'Apache-2.0'
15+
16+
spec.metadata['homepage_uri'] = spec.homepage
17+
spec.metadata['source_code_uri'] = spec.homepage
18+
19+
# Specify which files should be added to the gem when it is released.
20+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21+
gemspec = File.basename(__FILE__)
22+
spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
23+
ls.readlines("\x0", chomp: true).reject do |f|
24+
(f == gemspec) ||
25+
f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
26+
end
27+
end
28+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29+
spec.require_paths = ['lib']
30+
31+
# Uncomment to register a new dependency of your gem
32+
# spec.add_dependency "example-gem", "~> 1.0"
33+
spec.add_dependency 'minitest'
34+
spec.add_development_dependency 'appraisal'
35+
spec.add_development_dependency 'rubocop'
36+
spec.add_development_dependency 'rubocop-performance'
37+
38+
# For more information and examples about making a new gem, check out our
39+
# guide at: https://bundler.io/guides/creating_gem.html
40+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
describe OpenTelemetry::MetricsTestHelpers do
10+
with_metrics_sdk do
11+
it 'must be defined' do
12+
_(!defined?(OpenTelemetry::SDK::Metrics).nil?).must_equal(true)
13+
end
14+
end
15+
16+
without_metrics_sdk do
17+
it 'must not be defined' do
18+
_(!defined?(OpenTelemetry::SDK::Metrics).nil?).must_equal(false)
19+
end
20+
end
21+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
require 'opentelemetry-sdk'
8+
9+
begin
10+
require 'opentelemetry-metrics-sdk'
11+
rescue LoadError # rubocop: disable Lint/SuppressedException
12+
end
13+
14+
begin
15+
require 'opentelemetry-metrics-api'
16+
rescue LoadError # rubocop: disable Lint/SuppressedException
17+
end
18+
19+
OpenTelemetry::SDK.configure
20+
21+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
22+
require 'opentelemetry-metrics-test-helpers'
23+
24+
require 'minitest/autorun'

0 commit comments

Comments
 (0)