flare 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cee6e0910ebcd04f073efc41638823f7ed4d7abf511ab71b68caead994997af1
4
- data.tar.gz: f28d669e444b2abb8b6043990b8f1cfc5cbd39abc14d25942cf5f41e08a80cb2
3
+ metadata.gz: c94277634cce4170817b717f3ff6b3cb99ac980908f51ed6aaa6ba07a8c59de6
4
+ data.tar.gz: 4d882034612ac608246ea1a3f232a5f491c283d97b6082a97115f60f0b80fdf5
5
5
  SHA512:
6
- metadata.gz: 06647d35a64ae38dafb6e946b181fd87a8b8dc8e7065c5b0d4af3cb47419bd5be5dc9e930f3aa322740e824279169d9b2ae867c2b3c14dfda22c1d01be25507d
7
- data.tar.gz: 837f70a2ef44f4d0f8c415cc15c6455ab5250b63e7dd06580ad640492385d8d1e6842cda3f56b036d918bb38c7b55438a2d60546a6c41fd7ce77a429b2d1793a
6
+ metadata.gz: f8cfaf0827068925802b90582a3c12a2513649db82b23e51509ed689c111cfcbcd7397c2c260d13934dadfe3a2899481925875faf0bc75f3262c326fa8718e63
7
+ data.tar.gz: 38727869b8f7ebf8283354a7c696aded643a5da8260bce61d2ddacb4e6e441868d72eed7c01766b9e8d83d2d95954b1fab2fd75e8cdd1bf7adfabef3d23e4ae5
@@ -6,11 +6,14 @@ require_relative "deadline"
6
6
 
7
7
  module Flare
8
8
  module Lifecycle
9
+ FLUSH_TIMEOUT = 5 # seconds, total across traces and metrics
10
+
9
11
  # Flush all trace processors and the separate aggregated metric pipeline
10
12
  # using one monotonic timeout budget. This is safe to call from lifecycle
11
- # hooks for short-lived and fork-per-job workers.
12
- def force_flush(timeout: nil)
13
- deadline = Deadline.new(timeout)
13
+ # hooks for short-lived and fork-per-job workers. A nil timeout means the
14
+ # default, not unbounded: a hung endpoint must not stall the worker.
15
+ def force_flush(timeout: FLUSH_TIMEOUT)
16
+ deadline = Deadline.new(timeout || FLUSH_TIMEOUT)
14
17
  results = []
15
18
 
16
19
  results << tracer_provider_for_flush.force_flush(timeout: deadline.remaining)
@@ -26,6 +29,42 @@ module Flare
26
29
  OpenTelemetry::SDK::Trace::Export::FAILURE
27
30
  end
28
31
 
32
+ SHUTDOWN_TIMEOUT = 5 # seconds, total across all of Flare
33
+ TRACE_SHUTDOWN_TIMEOUT = 1 # seconds; sampled traces are expendable
34
+
35
+ # Stop everything Flare runs in the background under one budget, in
36
+ # priority order. Runs from at_exit in every forked worker, so it must
37
+ # finish well before the platform's kill deadline even if endpoints hang.
38
+ # Metrics (a minute of aggregated counts) get first claim on the time;
39
+ # span/trace processors get what's left, capped at TRACE_SHUTDOWN_TIMEOUT.
40
+ # A nil timeout means the default, not unbounded: shutdown is always bounded.
41
+ def shutdown(timeout: SHUTDOWN_TIMEOUT)
42
+ deadline = Deadline.new(timeout || SHUTDOWN_TIMEOUT)
43
+
44
+ shutdown_step("rule manager") { @rule_manager&.stop(timeout: 0) }
45
+ shutdown_step("metrics") { @metric_flusher&.stop(timeout: [deadline.remaining - TRACE_SHUTDOWN_TIMEOUT, 0].max) }
46
+
47
+ traces = Deadline.new([deadline.remaining, TRACE_SHUTDOWN_TIMEOUT].min)
48
+ if configuration.spans_enabled && @span_processor
49
+ shutdown_step("span processor") { span_processor.shutdown(timeout: traces.remaining) }
50
+ end
51
+ shutdown_step("trace processor") { @trace_span_processor&.shutdown(timeout: traces.remaining) }
52
+ end
53
+
54
+ # Each step is isolated so one failure doesn't skip the rest.
55
+ def shutdown_step(name)
56
+ yield
57
+ rescue => e
58
+ warn "[Flare] #{name} shutdown error: #{e.message}"
59
+ end
60
+
61
+ def install_shutdown_hook
62
+ return if @shutdown_hook_installed
63
+
64
+ @shutdown_hook_installed = true
65
+ at_exit { shutdown }
66
+ end
67
+
29
68
  def tracer_provider_for_flush
30
69
  OpenTelemetry.tracer_provider
31
70
  end
@@ -116,6 +116,8 @@ module Flare
116
116
  # on first span in the new process, or manually from Puma/Unicorn
117
117
  # after_fork hooks.
118
118
  def after_fork
119
+ return if @pid == $$
120
+
119
121
  @pid = $$
120
122
  @storage.after_fork if @storage.respond_to?(:after_fork)
121
123
  initialize_synchronization
@@ -60,10 +60,10 @@ module Flare
60
60
  self
61
61
  end
62
62
 
63
- def stop
63
+ def stop(timeout: 1)
64
64
  if @timer
65
65
  @timer.shutdown
66
- @timer.wait_for_termination(1)
66
+ @timer.wait_for_termination(timeout)
67
67
  @timer.kill unless @timer.shutdown?
68
68
  @timer = nil
69
69
  end
data/lib/flare/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flare
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.2"
5
5
  end
data/lib/flare.rb CHANGED
@@ -230,20 +230,7 @@ module Flare
230
230
  subscribe_to_notifications
231
231
  end
232
232
 
233
- at_exit do
234
- log "Shutting down..."
235
- if configuration.spans_enabled && @span_processor
236
- span_processor.force_flush
237
- span_processor.shutdown
238
- log "Span processor flushed and stopped"
239
- end
240
- if @trace_span_processor
241
- @trace_span_processor.force_flush
242
- @trace_span_processor.shutdown
243
- log "Trace span processor flushed and stopped"
244
- end
245
- log "Shutdown complete"
246
- end
233
+ install_shutdown_hook
247
234
 
248
235
  @otel_configured = true
249
236
  end
@@ -272,7 +259,7 @@ module Flare
272
259
  @rule_manager.start
273
260
  log "Rule manager started (poll=#{configuration.tracing_poll_interval}s)"
274
261
 
275
- at_exit { @rule_manager&.stop }
262
+ install_shutdown_hook
276
263
  end
277
264
 
278
265
  def setup_tracing_components
@@ -357,7 +344,7 @@ module Flare
357
344
  @metric_flusher.start
358
345
  log "Metrics flusher started (interval=#{configuration.metrics_flush_interval}s)"
359
346
 
360
- at_exit { @metric_flusher&.stop }
347
+ install_shutdown_hook
361
348
  else
362
349
  log "Metrics submission not configured (missing url or key)"
363
350
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flare
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker