Skip to content

Commit 851f2bf

Browse files
committed
fix: recover PeriodicMetricReader in forked processes
1 parent 71cecc7 commit 851f2bf

File tree

4 files changed

+52
-1
lines changed

4 files changed

+52
-1
lines changed

metrics_sdk/lib/opentelemetry/sdk/metrics/configuration_patch.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def initialize
2525
def metrics_configuration_hook
2626
OpenTelemetry.meter_provider = Metrics::MeterProvider.new(resource: @resource)
2727
configure_metric_readers
28+
attach_fork_hooks!
2829
end
2930

3031
def configure_metric_readers
@@ -52,6 +53,10 @@ def wrapped_metric_exporters_from_env
5253
end
5354
end
5455
end
56+
57+
def attach_fork_hooks!
58+
ForkHooks.attach!
59+
end
5560
end
5661
end
5762
end

metrics_sdk/lib/opentelemetry/sdk/metrics/export/periodic_metric_reader.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ def force_flush(timeout: nil)
5959
Export::FAILURE
6060
end
6161

62+
def after_fork
63+
@exporter.reset if @exporter.respond_to?(:reset)
64+
collect # move past previously reported metrics from parent process
65+
@thread = nil
66+
start
67+
end
68+
6269
private
6370

6471
def start

metrics_sdk/test/integration/periodic_metric_reader_test.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# SPDX-License-Identifier: Apache-2.0
66

77
require 'test_helper'
8+
require 'json'
89

910
describe OpenTelemetry::SDK do
1011
describe '#periodic_metric_reader' do
@@ -81,5 +82,43 @@
8182
_(snapshot.size).must_equal(1)
8283
_(periodic_metric_reader.instance_variable_get(:@thread).alive?).must_equal false
8384
end
85+
86+
it 'is restarted after forking' do
87+
OpenTelemetry::SDK.configure
88+
89+
metric_exporter = OpenTelemetry::SDK::Metrics::Export::InMemoryMetricPullExporter.new
90+
periodic_metric_reader = OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new(export_interval_millis: 5000, export_timeout_millis: 5000, exporter: metric_exporter)
91+
92+
OpenTelemetry.meter_provider.add_metric_reader(periodic_metric_reader)
93+
94+
read, write = IO.pipe
95+
96+
pid = fork do
97+
meter = OpenTelemetry.meter_provider.meter('test')
98+
counter = meter.create_counter('counter', unit: 'smidgen', description: 'a small amount of something')
99+
100+
counter.add(1)
101+
counter.add(2, attributes: { 'a' => 'b' })
102+
counter.add(2, attributes: { 'a' => 'b' })
103+
counter.add(3, attributes: { 'b' => 'c' })
104+
counter.add(4, attributes: { 'd' => 'e' })
105+
106+
sleep(8)
107+
snapshot = metric_exporter.metric_snapshots
108+
109+
json = snapshot.map { |reading| { name: reading.name } }.to_json
110+
write.puts json
111+
end
112+
113+
Timeout.timeout(10) do
114+
Process.waitpid(pid)
115+
end
116+
117+
periodic_metric_reader.shutdown
118+
snapshot = JSON.parse(read.gets.chomp)
119+
_(snapshot.size).must_equal(1)
120+
_(snapshot[0]).must_equal('name' => 'counter')
121+
_(periodic_metric_reader.instance_variable_get(:@thread).alive?).must_equal false
122+
end
84123
end
85124
end

metrics_sdk/test/test_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def reset_metrics_sdk
2020
:@meter_provider,
2121
OpenTelemetry::Internal::ProxyMeterProvider.new
2222
)
23-
23+
OpenTelemetry::SDK::Metrics::ForkHooks.instance_variable_set(:@fork_hooks_attached, false)
2424
OpenTelemetry.logger = Logger.new(File::NULL)
2525
OpenTelemetry.error_handler = nil
2626
end

0 commit comments

Comments
 (0)