Skip to content

Commit 765a3a6

Browse files
committed
setup up structure for testing with or without metrics sdk
1 parent a7a3541 commit 765a3a6

File tree

6 files changed

+139
-18
lines changed

6 files changed

+139
-18
lines changed

instrumentation/sidekiq/Appraisals

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,45 @@
22

33
appraise 'sidekiq-7.0' do
44
gem 'sidekiq', '~> 7.0'
5+
6+
remove_gem 'opentelemetry-metrics-sdk'
7+
remove_gem 'opentelemetry-metrics-api'
8+
end
9+
10+
appraise 'sidekiq-7.0-metrics-sdk' do
11+
gem 'sidekiq', '~> 7.0'
12+
end
13+
14+
# explicitly test without SDK
15+
appraise 'sidekiq-7.0-metrics-api' do
16+
gem 'sidekiq', '~> 7.0'
17+
18+
remove_gem 'opentelemetry-metrics-sdk'
519
end
620

721
appraise 'sidekiq-6.5' do
822
gem 'sidekiq', '>= 6.5', '< 7.0'
23+
remove_gem 'opentelemetry-metrics-api'
24+
remove_gem 'opentelemetry-metrics-sdk'
925
end
1026

1127
appraise 'sidekiq-6.0' do
1228
gem 'sidekiq', '>= 6.0', '< 6.5'
1329
gem 'redis', '< 4.8'
30+
remove_gem 'opentelemetry-metrics-api'
31+
remove_gem 'opentelemetry-metrics-sdk'
1432
end
1533

1634
appraise 'sidekiq-5.2' do
1735
gem 'sidekiq', '~> 5.2'
1836
gem 'redis', '< 4.8'
37+
remove_gem 'opentelemetry-metrics-api'
38+
remove_gem 'opentelemetry-metrics-sdk'
1939
end
2040

2141
appraise 'sidekiq-4.2' do
2242
gem 'sidekiq', '~> 4.2'
2343
gem 'redis', '< 4.8'
44+
remove_gem 'opentelemetry-metrics-api'
45+
remove_gem 'opentelemetry-metrics-sdk'
2446
end

instrumentation/sidekiq/Gemfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,22 @@ source 'https://rubygems.org'
88

99
gemspec
1010

11+
# FIXME: the metrics-api is behind the metrics-sdk gem for some reason; bundle from git for now
12+
OTEL_RUBY_GEM = lambda do |short_name|
13+
short_name = short_name.split(/-|_/)
14+
long_name = ['opentelemetry', *short_name].join('-')
15+
16+
gem long_name,
17+
git: 'https://www.github.com/open-telemetry/opentelemetry-ruby',
18+
glob: "#{short_name.join('_')}/*.gemspec",
19+
ref: '035c32ad9791f6200733e087f2ee49e0a615879a'
20+
end
21+
22+
OTEL_RUBY_GEM['metrics-api']
23+
1124
group :test do
1225
gem 'opentelemetry-instrumentation-base', path: '../base'
1326
gem 'opentelemetry-instrumentation-redis', path: '../redis'
27+
OTEL_RUBY_GEM['metrics-sdk']
1428
gem 'pry-byebug'
1529
end

instrumentation/sidekiq/lib/opentelemetry/instrumentation/sidekiq/middlewares/client/tracer_middleware.rb

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

7+
require_relative '../common'
8+
79
module OpenTelemetry
810
module Instrumentation
911
module Sidekiq
@@ -12,6 +14,7 @@ module Client
1214
# TracerMiddleware propagates context and instruments Sidekiq client
1315
# by way of its middleware system
1416
class TracerMiddleware
17+
include Common
1518
include ::Sidekiq::ClientMiddleware if defined?(::Sidekiq::ClientMiddleware)
1619

1720
def call(_worker_class, job, _queue, _redis_pool)
@@ -61,22 +64,6 @@ def messaging_client_sent_messages_counter
6164
instrumentation.counter('messaging.client.sent.messages')
6265
end
6366

64-
def messaging_client_operation_duration_histogram
65-
instrumentation.histogram('messaging.client.operation.duration')
66-
end
67-
68-
def messaging_client_consumed_messages_counter
69-
instrumentation.counter('messaging.client.consumed.messages')
70-
end
71-
72-
def instrumentation
73-
Sidekiq::Instrumentation.instance
74-
end
75-
76-
def instrumentation_config
77-
instrumentation.config
78-
end
79-
8067
def tracer
8168
instrumentation.tracer
8269
end

instrumentation/sidekiq/lib/opentelemetry/instrumentation/sidekiq/middlewares/server/tracer_middleware.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

7+
require_relative '../common'
8+
79
module OpenTelemetry
810
module Instrumentation
911
module Sidekiq
@@ -12,7 +14,7 @@ module Server
1214
# TracerMiddleware propagates context and instruments Sidekiq requests
1315
# by way of its middleware system
1416
class TracerMiddleware
15-
include OpenTelemetry::Instrumentation::Sidekiq::Middlewares::Common
17+
include Common
1618
include ::Sidekiq::ServerMiddleware if defined?(::Sidekiq::ServerMiddleware)
1719

1820
def call(_worker, msg, _queue)
@@ -60,6 +62,8 @@ def call(_worker, msg, _queue)
6062
end
6163
end
6264
end
65+
66+
count_consumed_message(msg)
6367
end
6468
end
6569

@@ -93,6 +97,16 @@ def messaging_process_duration_histogram
9397
instrumentation.histogram('messaging.process.duration')
9498
end
9599

100+
def count_consumed_message(msg)
101+
with_meter do
102+
messaging_client_consumed_messages_counter.add(1, attributes: metrics_attributes(msg))
103+
end
104+
end
105+
106+
def messaging_client_consumed_messages_counter
107+
instrumentation.counter('messaging.client.consumed.messages')
108+
end
109+
96110
def queue_latency_gauge
97111
instrumentation.gauge('messaging.queue.latency')
98112
end

instrumentation/sidekiq/test/opentelemetry/instrumentation/sidekiq/middlewares/server/tracer_middleware_test.rb

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,28 @@
1111
describe OpenTelemetry::Instrumentation::Sidekiq::Middlewares::Server::TracerMiddleware do
1212
let(:instrumentation) { OpenTelemetry::Instrumentation::Sidekiq::Instrumentation.instance }
1313
let(:exporter) { EXPORTER }
14+
let(:metrics_exporter) { METRICS_EXPORTER }
1415
let(:spans) { exporter.finished_spans }
1516
let(:enqueuer_span) { spans.first }
1617
let(:job_span) { spans.last }
1718
let(:root_span) { spans.find { |s| s.parent_span_id == OpenTelemetry::Trace::INVALID_SPAN_ID } }
1819
let(:config) { {} }
1920

21+
with_metrics do
22+
let(:metric_snapshots) do
23+
METRICS_EXPORTER.tap(&:pull).metric_snapshots.group_by(&:name)
24+
end
25+
end
26+
2027
before do
2128
instrumentation.install(config)
2229
exporter.reset
30+
with_metrics { metrics_exporter.tap(&:pull).reset }
2331
end
2432

25-
after { instrumentation.instance_variable_set(:@installed, false) }
33+
after do
34+
instrumentation.instance_variable_set(:@installed, false)
35+
end
2636

2737
describe 'enqueue spans' do
2838
it 'before performing any jobs' do
@@ -49,6 +59,37 @@
4959
_(job_span.events[1].name).must_equal('enqueued_at')
5060
end
5161

62+
it 'metrics processing', with_metrics: true do
63+
job_id = SimpleJob.perform_async
64+
SimpleJob.drain
65+
66+
queue_latency = metric_snapshots['messaging.queue.latency']
67+
_(queue_latency.count).must_equal 1
68+
_(queue_latency.first.data_points.count).must_equal 1
69+
queue_latency_attributes = queue_latency.first.data_points.first.attributes
70+
_(queue_latency_attributes['messaging.system']).must_equal 'sidekiq'
71+
_(queue_latency_attributes['messaging.destination.name']).must_equal 'default' # FIXME: newer semconv specifies this key
72+
73+
process_duration = metric_snapshots['messaging.process.duration']
74+
_(process_duration.count).must_equal 1
75+
_(process_duration.first.data_points.count).must_equal 1
76+
process_duration_attributes = process_duration.first.data_points.first.attributes
77+
_(process_duration_attributes['messaging.system']).must_equal 'sidekiq'
78+
_(process_duration_attributes['messaging.operation.name']).must_equal 'process'
79+
_(process_duration_attributes['messaging.destination.name']).must_equal 'default'
80+
81+
process_duration_data_point = process_duration.first.data_points.first
82+
_(process_duration_data_point.count).must_equal 1
83+
84+
consumed_messages = metric_snapshots['messaging.client.consumed.messages']
85+
_(consumed_messages.count).must_equal 1
86+
_(consumed_messages.first.data_points.count).must_equal 1
87+
consumed_messages_attributes = queue_latency.first.data_points.first.attributes
88+
_(consumed_messages_attributes['messaging.system']).must_equal 'sidekiq'
89+
_(consumed_messages_attributes['messaging.destination.name']).must_equal 'default' # FIXME: newer semconv specifies this key
90+
_(consumed_messages.first.data_points.first.value).must_equal 1
91+
end
92+
5293
it 'traces when enqueued with Active Job' do
5394
SimpleJobWithActiveJob.perform_later(1, 2)
5495
Sidekiq::Worker.drain_all

instrumentation/sidekiq/test/test_helper.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,49 @@
3030
c.add_span_processor span_processor
3131
end
3232

33+
module LoadedMetricsFeatures
34+
OTEL_METRICS_API_LOADED = !Gem.loaded_specs['opentelemetry-metrics-api'].nil?
35+
OTEL_METRICS_SDK_LOADED = !Gem.loaded_specs['opentelemetry-metrics-sdk'].nil?
36+
37+
extend self
38+
39+
def api_loaded?
40+
OTEL_METRICS_API_LOADED
41+
end
42+
43+
def sdk_loaded?
44+
OTEL_METRICS_SDK_LOADED
45+
end
46+
end
47+
48+
if LoadedMetricsFeatures.sdk_loaded?
49+
METRICS_EXPORTER = OpenTelemetry::SDK::Metrics::Export::InMemoryMetricPullExporter.new
50+
OpenTelemetry.meter_provider.add_metric_reader(METRICS_EXPORTER)
51+
end
52+
53+
module ConditionalEvaluation
54+
def self.included(base)
55+
base.extend(self)
56+
end
57+
58+
def self.prepended(base)
59+
base.extend(self)
60+
end
61+
62+
def with_metrics
63+
yield if LoadedMetricsFeatures.sdk_loaded?
64+
end
65+
66+
def it(desc = 'anonymous', with_metrics: false, &block)
67+
return super(desc, &block) unless with_metrics
68+
return unless LoadedMetricsFeatures.sdk_loaded?
69+
70+
super(desc, &block)
71+
end
72+
end
73+
74+
Minitest::Spec.prepend(ConditionalEvaluation)
75+
3376
# Sidekiq redis configuration
3477
ENV['TEST_REDIS_HOST'] ||= '127.0.0.1'
3578
ENV['TEST_REDIS_PORT'] ||= '16379'

0 commit comments

Comments
 (0)