brainzlab 0.1.32 → 0.1.33

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: 2c27f671d247f5b7274905767ed060ec3bfc90c7e2389b8fe117fb300c09a59b
4
- data.tar.gz: 3af6ac68bd7042f00aa16defa1c68d170653a9b053fe98cb375760b6f72bc14a
3
+ metadata.gz: a9a9a15a426d4a6853086c9a36851e57bd14736c5d11dbeb70fb510fe5fc1c10
4
+ data.tar.gz: 19f26af342b3d9150eacb2615da08fa063cc671388f7b97a87b207cd210cf6fc
5
5
  SHA512:
6
- metadata.gz: 571ec070d0ff6d1f3503245a6c0e201d4d81903fda8a0d6ddf316ae7148c4bee6deb93299b76e5fc22839747d9f827cbf68da46dc04cb7d01abf2685580fb647
7
- data.tar.gz: 9af9570ce725917a5093a9efbc46f81b13c454bb044549057eb49e43fa717e2750d28d580db055171bcb7e9d4c2cc2173e283bb47e7154510a16f1c82ac2ee3e
6
+ metadata.gz: b149c1fbf2c0f13fa34d0b2d2e6df634a1dc01f087f8174ba58fcc0bf05ea0301365721131e03441bf0af7e3b443d5a86acc5dfa141ba4fa9af2c24c610782a9
7
+ data.tar.gz: 737cd856a43c4c3555a566653692fd32d04798e464e24bad80d189610b82e81c0d0b2860cda232fae66063477b21687858c14e5178050a771af6745b9741d46f
@@ -43,6 +43,7 @@ module BrainzLab
43
43
  :pulse_flush_interval,
44
44
  :pulse_sample_rate,
45
45
  :pulse_sample_tier,
46
+ :pulse_always_keep_slow_ms,
46
47
  :pulse_excluded_paths,
47
48
  :flux_enabled,
48
49
  :flux_url,
@@ -261,6 +262,10 @@ module BrainzLab
261
262
  # BRAINZLAB_PULSE_TIER=client (or PULSE_SAMPLE_RATE) to keep everything.
262
263
  @pulse_sample_rate = (v = ENV['PULSE_SAMPLE_RATE'] || ENV['BRAINZLAB_PULSE_SAMPLE_RATE']).nil? || v.to_s.strip.empty? ? nil : v.to_f
263
264
  @pulse_sample_tier = (ENV['BRAINZLAB_PULSE_TIER'] || 'internal').to_s.strip.downcase
265
+ # Traces at/above this duration (ms) bypass sampling and are ALWAYS kept,
266
+ # so slow requests / N+1s are never sampled away (APM's whole purpose).
267
+ # Set to 0 to disable. Default 1000ms.
268
+ @pulse_always_keep_slow_ms = (ENV['BRAINZLAB_PULSE_ALWAYS_KEEP_SLOW_MS'] || 1000).to_i
264
269
  @pulse_excluded_paths = %w[/health /ping /up /assets]
265
270
 
266
271
  # Flux settings
@@ -72,11 +72,24 @@ module BrainzLab
72
72
  # effective per-tier sample rate (internal=0.1, standard=0.5, client=1.0).
73
73
  def keep_trace?(payload)
74
74
  return true if payload[:error] == true || payload['error'] == true
75
+ # Always keep SLOW traces, regardless of sampling. Surfacing slow
76
+ # requests (N+1s, slow endpoints) is the whole point of APM — sampling
77
+ # them out blinds debugging, which is exactly how an inquiries-page N+1
78
+ # stayed invisible on a 10%-sampled app.
79
+ return true if slow_trace?(payload)
75
80
 
76
81
  rate = @config.effective_pulse_sample_rate
77
82
  rate >= 1.0 || rand < rate
78
83
  end
79
84
 
85
+ def slow_trace?(payload)
86
+ threshold = @config.pulse_always_keep_slow_ms.to_i
87
+ return false unless threshold.positive?
88
+
89
+ duration = payload[:duration_ms] || payload['duration_ms']
90
+ !duration.nil? && duration.to_f >= threshold
91
+ end
92
+
80
93
  def buffer_trace(payload)
81
94
  should_flush = false
82
95
 
@@ -44,8 +44,8 @@ module BrainzLab
44
44
  duration_ms = ((ended_at - trace[:started_at]) * 1000).round(2)
45
45
 
46
46
  payload = trace.merge(
47
- ended_at: ended_at.iso8601(3),
48
- started_at: trace[:started_at].utc.iso8601(3),
47
+ ended_at: iso_ts(ended_at),
48
+ started_at: iso_ts(trace[:started_at]),
49
49
  duration_ms: duration_ms,
50
50
  error: error,
51
51
  error_class: error_class,
@@ -99,8 +99,8 @@ module BrainzLab
99
99
  parent_span_id: span[:parent_span_id],
100
100
  name: span[:name],
101
101
  kind: span[:kind],
102
- started_at: span[:started_at].utc.iso8601(3),
103
- ended_at: span[:ended_at].utc.iso8601(3),
102
+ started_at: iso_ts(span[:started_at]),
103
+ ended_at: iso_ts(span[:ended_at]),
104
104
  duration_ms: span[:duration_ms],
105
105
  error: span[:error],
106
106
  error_class: span[:error_class],
@@ -108,6 +108,21 @@ module BrainzLab
108
108
  data: span[:data]
109
109
  }.compact
110
110
  end
111
+
112
+ # Rails 8 changed ActiveSupport::Notifications::Event#time/#end to return a
113
+ # Float (monotonic), so spans carry Float timestamps. Calling #utc on them
114
+ # raised NoMethodError, crashing trace serialization (error/job traces) on
115
+ # Rails 8 apps. Coerce Time/Float/Integer/String safely.
116
+ def iso_ts(ts)
117
+ return nil if ts.nil?
118
+
119
+ case ts
120
+ when Time, DateTime then ts.utc.iso8601(3)
121
+ when Numeric then Time.at(ts).utc.iso8601(3)
122
+ when String then ts
123
+ else ts.to_s
124
+ end
125
+ end
111
126
  end
112
127
  end
113
128
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BrainzLab
4
- VERSION = '0.1.32'
4
+ VERSION = '0.1.33'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brainzlab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.32
4
+ version: 0.1.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - BrainzLab