brainzlab 0.1.2 → 0.1.4

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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +6 -21
  3. data/README.md +16 -2
  4. data/lib/brainzlab/beacon/client.rb +38 -40
  5. data/lib/brainzlab/beacon/provisioner.rb +1 -1
  6. data/lib/brainzlab/beacon.rb +15 -15
  7. data/lib/brainzlab/configuration.rb +112 -90
  8. data/lib/brainzlab/context.rb +2 -3
  9. data/lib/brainzlab/cortex/client.rb +29 -31
  10. data/lib/brainzlab/cortex/provisioner.rb +1 -1
  11. data/lib/brainzlab/cortex.rb +7 -11
  12. data/lib/brainzlab/dendrite/client.rb +42 -44
  13. data/lib/brainzlab/dendrite/provisioner.rb +1 -1
  14. data/lib/brainzlab/dendrite.rb +4 -4
  15. data/lib/brainzlab/devtools/data/collector.rb +22 -22
  16. data/lib/brainzlab/devtools/middleware/asset_server.rb +14 -14
  17. data/lib/brainzlab/devtools/middleware/database_handler.rb +52 -55
  18. data/lib/brainzlab/devtools/middleware/debug_panel.rb +19 -19
  19. data/lib/brainzlab/devtools/middleware/error_page.rb +45 -44
  20. data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +39 -35
  21. data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +13 -9
  22. data/lib/brainzlab/devtools.rb +11 -11
  23. data/lib/brainzlab/flux/buffer.rb +3 -3
  24. data/lib/brainzlab/flux/client.rb +14 -16
  25. data/lib/brainzlab/flux/provisioner.rb +13 -13
  26. data/lib/brainzlab/flux.rb +8 -8
  27. data/lib/brainzlab/instrumentation/action_cable.rb +351 -0
  28. data/lib/brainzlab/instrumentation/action_controller.rb +649 -0
  29. data/lib/brainzlab/instrumentation/action_dispatch.rb +259 -0
  30. data/lib/brainzlab/instrumentation/action_mailbox.rb +197 -0
  31. data/lib/brainzlab/instrumentation/action_mailer.rb +14 -13
  32. data/lib/brainzlab/instrumentation/action_view.rb +380 -0
  33. data/lib/brainzlab/instrumentation/active_job.rb +569 -0
  34. data/lib/brainzlab/instrumentation/active_record.rb +467 -36
  35. data/lib/brainzlab/instrumentation/active_storage.rb +541 -0
  36. data/lib/brainzlab/instrumentation/active_support_cache.rb +700 -0
  37. data/lib/brainzlab/instrumentation/aws.rb +43 -39
  38. data/lib/brainzlab/instrumentation/dalli.rb +20 -20
  39. data/lib/brainzlab/instrumentation/delayed_job.rb +27 -29
  40. data/lib/brainzlab/instrumentation/elasticsearch.rb +23 -24
  41. data/lib/brainzlab/instrumentation/excon.rb +27 -27
  42. data/lib/brainzlab/instrumentation/faraday.rb +3 -4
  43. data/lib/brainzlab/instrumentation/good_job.rb +28 -28
  44. data/lib/brainzlab/instrumentation/grape.rb +24 -24
  45. data/lib/brainzlab/instrumentation/graphql.rb +24 -23
  46. data/lib/brainzlab/instrumentation/httparty.rb +13 -14
  47. data/lib/brainzlab/instrumentation/mongodb.rb +7 -7
  48. data/lib/brainzlab/instrumentation/net_http.rb +6 -6
  49. data/lib/brainzlab/instrumentation/rails_deprecation.rb +139 -0
  50. data/lib/brainzlab/instrumentation/railties.rb +134 -0
  51. data/lib/brainzlab/instrumentation/redis.rb +14 -21
  52. data/lib/brainzlab/instrumentation/resque.rb +23 -24
  53. data/lib/brainzlab/instrumentation/sidekiq.rb +29 -28
  54. data/lib/brainzlab/instrumentation/solid_queue.rb +37 -41
  55. data/lib/brainzlab/instrumentation/stripe.rb +36 -37
  56. data/lib/brainzlab/instrumentation/typhoeus.rb +19 -17
  57. data/lib/brainzlab/instrumentation.rb +111 -21
  58. data/lib/brainzlab/nerve/client.rb +38 -40
  59. data/lib/brainzlab/nerve/provisioner.rb +1 -1
  60. data/lib/brainzlab/nerve.rb +6 -6
  61. data/lib/brainzlab/pulse/client.rb +15 -11
  62. data/lib/brainzlab/pulse/instrumentation.rb +61 -57
  63. data/lib/brainzlab/pulse/propagation.rb +28 -28
  64. data/lib/brainzlab/pulse/provisioner.rb +12 -12
  65. data/lib/brainzlab/pulse/tracer.rb +3 -3
  66. data/lib/brainzlab/pulse.rb +13 -13
  67. data/lib/brainzlab/rails/log_formatter.rb +127 -121
  68. data/lib/brainzlab/rails/log_subscriber.rb +70 -76
  69. data/lib/brainzlab/rails/railtie.rb +66 -89
  70. data/lib/brainzlab/recall/buffer.rb +1 -1
  71. data/lib/brainzlab/recall/client.rb +14 -10
  72. data/lib/brainzlab/recall/logger.rb +16 -18
  73. data/lib/brainzlab/recall/provisioner.rb +16 -16
  74. data/lib/brainzlab/recall.rb +11 -13
  75. data/lib/brainzlab/reflex/breadcrumbs.rb +2 -2
  76. data/lib/brainzlab/reflex/client.rb +14 -10
  77. data/lib/brainzlab/reflex/provisioner.rb +12 -12
  78. data/lib/brainzlab/reflex.rb +29 -29
  79. data/lib/brainzlab/sentinel/client.rb +40 -42
  80. data/lib/brainzlab/sentinel/provisioner.rb +1 -1
  81. data/lib/brainzlab/sentinel.rb +5 -5
  82. data/lib/brainzlab/signal/client.rb +12 -14
  83. data/lib/brainzlab/signal/provisioner.rb +12 -12
  84. data/lib/brainzlab/signal.rb +7 -7
  85. data/lib/brainzlab/synapse/client.rb +42 -44
  86. data/lib/brainzlab/synapse/provisioner.rb +1 -1
  87. data/lib/brainzlab/synapse.rb +6 -6
  88. data/lib/brainzlab/utilities/circuit_breaker.rb +37 -41
  89. data/lib/brainzlab/utilities/health_check.rb +53 -55
  90. data/lib/brainzlab/utilities/log_formatter.rb +38 -40
  91. data/lib/brainzlab/utilities/rate_limiter.rb +5 -5
  92. data/lib/brainzlab/utilities.rb +4 -4
  93. data/lib/brainzlab/vault/cache.rb +1 -1
  94. data/lib/brainzlab/vault/client.rb +39 -41
  95. data/lib/brainzlab/vault/provisioner.rb +1 -1
  96. data/lib/brainzlab/vault.rb +19 -25
  97. data/lib/brainzlab/version.rb +1 -1
  98. data/lib/brainzlab/vision/client.rb +20 -20
  99. data/lib/brainzlab/vision/provisioner.rb +21 -21
  100. data/lib/brainzlab/vision.rb +17 -19
  101. data/lib/brainzlab-sdk.rb +1 -1
  102. data/lib/brainzlab.rb +22 -24
  103. data/lib/generators/brainzlab/install/install_generator.rb +29 -27
  104. metadata +11 -1
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BrainzLab
4
+ module Instrumentation
5
+ class RailsDeprecation
6
+ class << self
7
+ def install!
8
+ return unless defined?(::Rails)
9
+ return if @installed
10
+
11
+ install_deprecation_subscriber!
12
+
13
+ @installed = true
14
+ BrainzLab.debug_log('Rails deprecation instrumentation installed')
15
+ end
16
+
17
+ def installed?
18
+ @installed == true
19
+ end
20
+
21
+ private
22
+
23
+ # ============================================
24
+ # deprecation.rails
25
+ # Fired when a deprecated Rails API is used
26
+ # ============================================
27
+ def install_deprecation_subscriber!
28
+ ActiveSupport::Notifications.subscribe('deprecation.rails') do |*args|
29
+ event = ActiveSupport::Notifications::Event.new(*args)
30
+ handle_deprecation(event)
31
+ end
32
+ end
33
+
34
+ def handle_deprecation(event)
35
+ payload = event.payload
36
+
37
+ message = payload[:message]
38
+ callstack = payload[:callstack]
39
+ gem_name = payload[:gem_name]
40
+ deprecation_horizon = payload[:deprecation_horizon]
41
+
42
+ # Extract relevant caller info
43
+ caller_info = extract_caller_info(callstack)
44
+
45
+ # Record breadcrumb with warning level
46
+ if BrainzLab.configuration.reflex_effectively_enabled?
47
+ BrainzLab::Reflex.add_breadcrumb(
48
+ "Deprecation: #{truncate_message(message)}",
49
+ category: 'rails.deprecation',
50
+ level: :warning,
51
+ data: {
52
+ message: truncate_message(message, 500),
53
+ gem_name: gem_name,
54
+ deprecation_horizon: deprecation_horizon,
55
+ caller: caller_info
56
+ }.compact
57
+ )
58
+ end
59
+
60
+ # Log to Recall for tracking
61
+ if BrainzLab.configuration.recall_effectively_enabled?
62
+ BrainzLab::Recall.warn(
63
+ "Rails deprecation warning",
64
+ message: truncate_message(message, 500),
65
+ gem_name: gem_name,
66
+ deprecation_horizon: deprecation_horizon,
67
+ caller: caller_info,
68
+ callstack: truncate_callstack(callstack)
69
+ )
70
+ end
71
+
72
+ # Track deprecation count in Pulse metrics
73
+ record_deprecation_metric(gem_name, deprecation_horizon)
74
+ rescue StandardError => e
75
+ BrainzLab.debug_log("Rails deprecation instrumentation failed: #{e.message}")
76
+ end
77
+
78
+ # ============================================
79
+ # Helper Methods
80
+ # ============================================
81
+ def extract_caller_info(callstack)
82
+ return nil unless callstack.is_a?(Array) && callstack.any?
83
+
84
+ # Find the first non-Rails, non-gem caller
85
+ app_caller = callstack.find do |line|
86
+ line_str = line.to_s
87
+ !line_str.include?('/gems/') &&
88
+ !line_str.include?('/ruby/') &&
89
+ !line_str.include?('/bundler/')
90
+ end
91
+
92
+ (app_caller || callstack.first).to_s
93
+ end
94
+
95
+ def truncate_callstack(callstack, max_lines = 5)
96
+ return nil unless callstack.is_a?(Array)
97
+
98
+ callstack.first(max_lines).map(&:to_s)
99
+ end
100
+
101
+ def truncate_message(message, max_length = 200)
102
+ return 'unknown' unless message
103
+
104
+ msg_str = message.to_s
105
+ if msg_str.length > max_length
106
+ "#{msg_str[0, max_length - 3]}..."
107
+ else
108
+ msg_str
109
+ end
110
+ end
111
+
112
+ def record_deprecation_metric(gem_name, horizon)
113
+ return unless BrainzLab.configuration.pulse_effectively_enabled?
114
+
115
+ # If Pulse has a counter/metric API, use it here
116
+ # For now, we just add a span to track it
117
+ tracer = BrainzLab::Pulse.tracer
118
+ return unless tracer.current_trace
119
+
120
+ span_data = {
121
+ span_id: SecureRandom.uuid,
122
+ name: 'rails.deprecation',
123
+ kind: 'internal',
124
+ started_at: Time.now,
125
+ ended_at: Time.now,
126
+ duration_ms: 0,
127
+ error: false,
128
+ data: {
129
+ 'deprecation.gem_name' => gem_name,
130
+ 'deprecation.horizon' => horizon
131
+ }.compact
132
+ }
133
+
134
+ tracer.current_spans << span_data
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BrainzLab
4
+ module Instrumentation
5
+ class Railties
6
+ # Thresholds for slow initializers (in milliseconds)
7
+ SLOW_INITIALIZER_THRESHOLD = 100 # 100ms
8
+ VERY_SLOW_INITIALIZER_THRESHOLD = 500 # 500ms
9
+
10
+ class << self
11
+ def install!
12
+ return unless defined?(::Rails)
13
+ return if @installed
14
+
15
+ install_load_config_initializer_subscriber!
16
+
17
+ @installed = true
18
+ BrainzLab.debug_log('Railties instrumentation installed')
19
+ end
20
+
21
+ def installed?
22
+ @installed == true
23
+ end
24
+
25
+ private
26
+
27
+ # ============================================
28
+ # load_config_initializer.railties
29
+ # Fired when each config initializer is loaded
30
+ # ============================================
31
+ def install_load_config_initializer_subscriber!
32
+ ActiveSupport::Notifications.subscribe('load_config_initializer.railties') do |*args|
33
+ event = ActiveSupport::Notifications::Event.new(*args)
34
+ handle_load_config_initializer(event)
35
+ end
36
+ end
37
+
38
+ def handle_load_config_initializer(event)
39
+ payload = event.payload
40
+ duration = event.duration.round(2)
41
+
42
+ initializer = payload[:initializer]
43
+
44
+ # Extract just the filename for cleaner display
45
+ initializer_name = extract_initializer_name(initializer)
46
+
47
+ # Determine level based on duration
48
+ level = case duration
49
+ when 0...SLOW_INITIALIZER_THRESHOLD then :info
50
+ when SLOW_INITIALIZER_THRESHOLD...VERY_SLOW_INITIALIZER_THRESHOLD then :warning
51
+ else :error
52
+ end
53
+
54
+ # Record breadcrumb (only for slow initializers to reduce noise during boot)
55
+ if duration >= 10 && BrainzLab.configuration.reflex_effectively_enabled?
56
+ BrainzLab::Reflex.add_breadcrumb(
57
+ "Initializer loaded: #{initializer_name} (#{duration}ms)",
58
+ category: 'rails.initializer',
59
+ level: level,
60
+ data: {
61
+ initializer: initializer_name,
62
+ path: initializer,
63
+ duration_ms: duration
64
+ }.compact
65
+ )
66
+ end
67
+
68
+ # Add Pulse span for tracking boot time
69
+ record_initializer_span(event, initializer_name, initializer, duration)
70
+
71
+ # Log slow initializers
72
+ log_slow_initializer(initializer_name, initializer, duration) if duration >= SLOW_INITIALIZER_THRESHOLD
73
+ rescue StandardError => e
74
+ BrainzLab.debug_log("Railties load_config_initializer instrumentation failed: #{e.message}")
75
+ end
76
+
77
+ # ============================================
78
+ # Span Recording
79
+ # ============================================
80
+ def record_initializer_span(event, name, path, duration)
81
+ return unless BrainzLab.configuration.pulse_effectively_enabled?
82
+
83
+ tracer = BrainzLab::Pulse.tracer
84
+ return unless tracer.current_trace
85
+
86
+ span_data = {
87
+ span_id: SecureRandom.uuid,
88
+ name: "rails.initializer.#{name}",
89
+ kind: 'internal',
90
+ started_at: event.time,
91
+ ended_at: event.end,
92
+ duration_ms: duration,
93
+ error: false,
94
+ data: {
95
+ 'rails.initializer.name' => name,
96
+ 'rails.initializer.path' => path
97
+ }.compact
98
+ }
99
+
100
+ tracer.current_spans << span_data
101
+ end
102
+
103
+ # ============================================
104
+ # Logging
105
+ # ============================================
106
+ def log_slow_initializer(name, path, duration)
107
+ return unless BrainzLab.configuration.recall_effectively_enabled?
108
+
109
+ level = duration >= VERY_SLOW_INITIALIZER_THRESHOLD ? :error : :warn
110
+
111
+ BrainzLab::Recall.send(
112
+ level,
113
+ "Slow initializer: #{name} (#{duration}ms)",
114
+ initializer: name,
115
+ path: path,
116
+ duration_ms: duration,
117
+ threshold_exceeded: duration >= VERY_SLOW_INITIALIZER_THRESHOLD ? 'critical' : 'warning'
118
+ )
119
+ end
120
+
121
+ # ============================================
122
+ # Helper Methods
123
+ # ============================================
124
+ def extract_initializer_name(path)
125
+ return 'unknown' unless path
126
+
127
+ # Extract filename without extension from path
128
+ # e.g., "/app/config/initializers/devise.rb" -> "devise"
129
+ File.basename(path.to_s, '.*')
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -18,7 +18,7 @@ module BrainzLab
18
18
  end
19
19
 
20
20
  @installed = true
21
- BrainzLab.debug_log("Redis instrumentation installed")
21
+ BrainzLab.debug_log('Redis instrumentation installed')
22
22
  end
23
23
 
24
24
  def installed?
@@ -32,7 +32,7 @@ module BrainzLab
32
32
  private
33
33
 
34
34
  def redis_5_or_newer?
35
- defined?(::Redis::VERSION) && Gem::Version.new(::Redis::VERSION) >= Gem::Version.new("5.0")
35
+ defined?(::Redis::VERSION) && Gem::Version.new(::Redis::VERSION) >= Gem::Version.new('5.0')
36
36
  end
37
37
 
38
38
  def install_middleware!
@@ -50,10 +50,6 @@ module BrainzLab
50
50
 
51
51
  # Middleware for Redis 5+ (RedisClient)
52
52
  module Middleware
53
- def connect(redis_config)
54
- super
55
- end
56
-
57
53
  def call(command, redis_config)
58
54
  return super unless should_track?
59
55
 
@@ -78,10 +74,10 @@ module BrainzLab
78
74
  ignore.map(&:downcase).include?(cmd_name)
79
75
  end
80
76
 
81
- def track_command(command, &block)
77
+ def track_command(command)
82
78
  return yield if should_skip_command?(command)
79
+
83
80
  started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
84
- error_info = nil
85
81
 
86
82
  begin
87
83
  result = yield
@@ -94,9 +90,8 @@ module BrainzLab
94
90
  end
95
91
  end
96
92
 
97
- def track_pipeline(commands, &block)
93
+ def track_pipeline(commands)
98
94
  started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
99
- error_info = nil
100
95
 
101
96
  begin
102
97
  result = yield
@@ -119,7 +114,7 @@ module BrainzLab
119
114
  if BrainzLab.configuration.reflex_enabled
120
115
  BrainzLab::Reflex.add_breadcrumb(
121
116
  "Redis #{cmd_name}",
122
- category: "redis",
117
+ category: 'redis',
123
118
  level: level,
124
119
  data: {
125
120
  command: cmd_name,
@@ -138,14 +133,14 @@ module BrainzLab
138
133
 
139
134
  def record_pipeline(commands, started_at, error = nil)
140
135
  duration_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at) * 1000).round(2)
141
- cmd_names = commands.map { |c| c.first.to_s.upcase }.uniq.join(", ")
136
+ cmd_names = commands.map { |c| c.first.to_s.upcase }.uniq.join(', ')
142
137
  level = error ? :error : :info
143
138
 
144
139
  # Add breadcrumb for Reflex
145
140
  if BrainzLab.configuration.reflex_enabled
146
141
  BrainzLab::Reflex.add_breadcrumb(
147
142
  "Redis PIPELINE (#{commands.size} commands)",
148
- category: "redis",
143
+ category: 'redis',
149
144
  level: level,
150
145
  data: {
151
146
  commands: cmd_names,
@@ -157,7 +152,7 @@ module BrainzLab
157
152
  end
158
153
 
159
154
  # Record span for Pulse APM
160
- record_pulse_span("PIPELINE", nil, duration_ms, error, commands.size)
155
+ record_pulse_span('PIPELINE', nil, duration_ms, error, commands.size)
161
156
  rescue StandardError => e
162
157
  BrainzLab.debug_log("Redis instrumentation error: #{e.message}")
163
158
  end
@@ -169,7 +164,7 @@ module BrainzLab
169
164
  span = {
170
165
  span_id: SecureRandom.uuid,
171
166
  name: "Redis #{command}",
172
- kind: "redis",
167
+ kind: 'redis',
173
168
  started_at: Time.now.utc - (duration_ms / 1000.0),
174
169
  ended_at: Time.now.utc,
175
170
  duration_ms: duration_ms,
@@ -210,7 +205,6 @@ module BrainzLab
210
205
  return super if should_skip_command?(command)
211
206
 
212
207
  started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
213
- error_info = nil
214
208
 
215
209
  begin
216
210
  result = super
@@ -227,7 +221,6 @@ module BrainzLab
227
221
  return super unless should_track?
228
222
 
229
223
  started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
230
- error_info = nil
231
224
  commands = pipeline.commands
232
225
 
233
226
  begin
@@ -262,7 +255,7 @@ module BrainzLab
262
255
  if BrainzLab.configuration.reflex_enabled
263
256
  BrainzLab::Reflex.add_breadcrumb(
264
257
  "Redis #{cmd_name}",
265
- category: "redis",
258
+ category: 'redis',
266
259
  level: level,
267
260
  data: {
268
261
  command: cmd_name,
@@ -285,7 +278,7 @@ module BrainzLab
285
278
  if BrainzLab.configuration.reflex_enabled
286
279
  BrainzLab::Reflex.add_breadcrumb(
287
280
  "Redis PIPELINE (#{commands.size} commands)",
288
- category: "redis",
281
+ category: 'redis',
289
282
  level: level,
290
283
  data: {
291
284
  count: commands.size,
@@ -295,7 +288,7 @@ module BrainzLab
295
288
  )
296
289
  end
297
290
 
298
- record_pulse_span("PIPELINE", nil, duration_ms, error, commands.size)
291
+ record_pulse_span('PIPELINE', nil, duration_ms, error, commands.size)
299
292
  rescue StandardError => e
300
293
  BrainzLab.debug_log("Redis instrumentation error: #{e.message}")
301
294
  end
@@ -307,7 +300,7 @@ module BrainzLab
307
300
  span = {
308
301
  span_id: SecureRandom.uuid,
309
302
  name: "Redis #{command}",
310
- kind: "redis",
303
+ kind: 'redis',
311
304
  started_at: Time.now.utc - (duration_ms / 1000.0),
312
305
  ended_at: Time.now.utc,
313
306
  duration_ms: duration_ms,
@@ -10,13 +10,13 @@ module BrainzLab
10
10
  install_hooks!
11
11
  install_failure_backend!
12
12
 
13
- BrainzLab.debug_log("[Instrumentation] Resque instrumentation installed")
13
+ BrainzLab.debug_log('[Instrumentation] Resque instrumentation installed')
14
14
  end
15
15
 
16
16
  private
17
17
 
18
18
  def install_hooks!
19
- ::Resque.before_fork do |job|
19
+ ::Resque.before_fork do |_job|
20
20
  # Clear any stale connections before forking
21
21
  BrainzLab::Recall.reset! if defined?(BrainzLab::Recall)
22
22
  BrainzLab::Pulse.reset! if defined?(BrainzLab::Pulse)
@@ -38,31 +38,30 @@ module BrainzLab
38
38
  end
39
39
 
40
40
  def save
41
- job_class = @payload["class"] || "Unknown"
41
+ job_class = @payload['class'] || 'Unknown'
42
42
 
43
43
  if BrainzLab.configuration.reflex_effectively_enabled?
44
44
  BrainzLab::Reflex.capture(@exception,
45
- tags: { job_class: job_class, queue: @queue, source: "resque" },
46
- extra: {
47
- worker: @worker.to_s,
48
- args: @payload["args"]
49
- }
50
- )
45
+ tags: { job_class: job_class, queue: @queue, source: 'resque' },
46
+ extra: {
47
+ worker: @worker.to_s,
48
+ args: @payload['args']
49
+ })
51
50
  end
52
51
 
53
- if BrainzLab.configuration.flux_effectively_enabled?
54
- BrainzLab::Flux.increment("resque.job.failed", tags: { job_class: job_class, queue: @queue })
55
- end
52
+ return unless BrainzLab.configuration.flux_effectively_enabled?
53
+
54
+ BrainzLab::Flux.increment('resque.job.failed', tags: { job_class: job_class, queue: @queue })
56
55
  end
57
56
  end
58
57
 
59
58
  # Add our failure backend to the chain
60
- if defined?(::Resque::Failure)
61
- ::Resque::Failure.backend = ::Resque::Failure::Multiple.new(
62
- ::Resque::Failure.backend,
63
- failure_backend
64
- )
65
- end
59
+ return unless defined?(::Resque::Failure)
60
+
61
+ ::Resque::Failure.backend = ::Resque::Failure::Multiple.new(
62
+ ::Resque::Failure.backend,
63
+ failure_backend
64
+ )
66
65
  end
67
66
  end
68
67
 
@@ -73,9 +72,9 @@ module BrainzLab
73
72
  end
74
73
 
75
74
  module ClassMethods
76
- def around_perform_brainzlab(*args)
77
- job_class = self.name
78
- queue = Resque.queue_from_class(self) || "default"
75
+ def around_perform_brainzlab(*_args)
76
+ job_class = name
77
+ queue = Resque.queue_from_class(self) || 'default'
79
78
  started_at = Time.now
80
79
 
81
80
  BrainzLab::Context.current.set_context(
@@ -91,7 +90,7 @@ module BrainzLab
91
90
  if BrainzLab.configuration.pulse_effectively_enabled?
92
91
  BrainzLab::Pulse.record_trace(
93
92
  "job.#{job_class}",
94
- kind: "job",
93
+ kind: 'job',
95
94
  started_at: started_at,
96
95
  ended_at: Time.now,
97
96
  job_class: job_class,
@@ -101,8 +100,8 @@ module BrainzLab
101
100
 
102
101
  if BrainzLab.configuration.flux_effectively_enabled?
103
102
  tags = { job_class: job_class, queue: queue }
104
- BrainzLab::Flux.distribution("resque.job.duration_ms", duration_ms, tags: tags)
105
- BrainzLab::Flux.increment("resque.job.processed", tags: tags)
103
+ BrainzLab::Flux.distribution('resque.job.duration_ms', duration_ms, tags: tags)
104
+ BrainzLab::Flux.increment('resque.job.processed', tags: tags)
106
105
  end
107
106
 
108
107
  BrainzLab.clear_context!
@@ -29,7 +29,7 @@ module BrainzLab
29
29
  end
30
30
 
31
31
  @installed = true
32
- BrainzLab.debug_log("Sidekiq instrumentation installed")
32
+ BrainzLab.debug_log('Sidekiq instrumentation installed')
33
33
  end
34
34
 
35
35
  def installed?
@@ -47,11 +47,11 @@ module BrainzLab
47
47
  return yield unless should_trace?
48
48
 
49
49
  started_at = Time.now.utc
50
- job_class = job["class"] || worker.class.name
51
- job_id = job["jid"]
50
+ job_class = job['class'] || worker.class.name
51
+ job_id = job['jid']
52
52
 
53
53
  # Calculate queue wait time
54
- enqueued_at = job["enqueued_at"] ? Time.at(job["enqueued_at"]) : nil
54
+ enqueued_at = job['enqueued_at'] ? Time.at(job['enqueued_at']) : nil
55
55
  queue_wait_ms = enqueued_at ? ((started_at - enqueued_at) * 1000).round(2) : nil
56
56
 
57
57
  # Extract parent trace context if present (distributed tracing)
@@ -63,9 +63,9 @@ module BrainzLab
63
63
  # Add breadcrumb
64
64
  BrainzLab::Reflex.add_breadcrumb(
65
65
  "Sidekiq #{job_class}",
66
- category: "job.sidekiq",
66
+ category: 'job.sidekiq',
67
67
  level: :info,
68
- data: { job_id: job_id, queue: queue, retry_count: job["retry_count"] }
68
+ data: { job_id: job_id, queue: queue, retry_count: job['retry_count'] }
69
69
  )
70
70
 
71
71
  # Initialize Pulse tracing
@@ -85,7 +85,7 @@ module BrainzLab
85
85
  queue: queue,
86
86
  started_at: started_at,
87
87
  queue_wait_ms: queue_wait_ms,
88
- retry_count: job["retry_count"] || 0,
88
+ retry_count: job['retry_count'] || 0,
89
89
  parent_context: parent_context,
90
90
  error: error_occurred
91
91
  )
@@ -102,11 +102,11 @@ module BrainzLab
102
102
 
103
103
  def setup_context(job, queue)
104
104
  BrainzLab::Context.current.set_context(
105
- job_class: job["class"],
106
- job_id: job["jid"],
105
+ job_class: job['class'],
106
+ job_id: job['jid'],
107
107
  queue_name: queue,
108
- retry_count: job["retry_count"],
109
- arguments: job["args"]&.map(&:to_s)&.first(5)
108
+ retry_count: job['retry_count'],
109
+ arguments: job['args']&.map(&:to_s)&.first(5)
110
110
  )
111
111
  end
112
112
 
@@ -118,19 +118,20 @@ module BrainzLab
118
118
  end
119
119
 
120
120
  def extract_trace_context(job)
121
- return nil unless job["_brainzlab_trace"]
121
+ return nil unless job['_brainzlab_trace']
122
122
 
123
- trace_data = job["_brainzlab_trace"]
123
+ trace_data = job['_brainzlab_trace']
124
124
  BrainzLab::Pulse::Propagation::Context.new(
125
- trace_id: trace_data["trace_id"],
126
- span_id: trace_data["span_id"],
127
- sampled: trace_data["sampled"] != false
125
+ trace_id: trace_data['trace_id'],
126
+ span_id: trace_data['span_id'],
127
+ sampled: trace_data['sampled'] != false
128
128
  )
129
129
  rescue StandardError
130
130
  nil
131
131
  end
132
132
 
133
- def record_trace(job_class:, job_id:, queue:, started_at:, queue_wait_ms:, retry_count:, parent_context:, error:)
133
+ def record_trace(job_class:, job_id:, queue:, started_at:, queue_wait_ms:, retry_count:, parent_context:,
134
+ error:)
134
135
  ended_at = Time.now.utc
135
136
  duration_ms = ((ended_at - started_at) * 1000).round(2)
136
137
 
@@ -156,7 +157,7 @@ module BrainzLab
156
157
  payload = {
157
158
  trace_id: SecureRandom.uuid,
158
159
  name: job_class,
159
- kind: "job",
160
+ kind: 'job',
160
161
  started_at: started_at.utc.iso8601(3),
161
162
  ended_at: ended_at.utc.iso8601(3),
162
163
  duration_ms: duration_ms,
@@ -200,7 +201,7 @@ module BrainzLab
200
201
 
201
202
  # Client middleware - runs when jobs are enqueued
202
203
  class ClientMiddleware
203
- def call(worker_class, job, queue, redis_pool)
204
+ def call(_worker_class, job, queue, _redis_pool)
204
205
  # Inject trace context for distributed tracing
205
206
  inject_trace_context(job)
206
207
 
@@ -208,9 +209,9 @@ module BrainzLab
208
209
  if BrainzLab.configuration.reflex_enabled
209
210
  BrainzLab::Reflex.add_breadcrumb(
210
211
  "Enqueue #{job['class']}",
211
- category: "job.sidekiq.enqueue",
212
+ category: 'job.sidekiq.enqueue',
212
213
  level: :info,
213
- data: { queue: queue, job_id: job["jid"] }
214
+ data: { queue: queue, job_id: job['jid'] }
214
215
  )
215
216
  end
216
217
 
@@ -231,10 +232,10 @@ module BrainzLab
231
232
 
232
233
  return unless ctx&.valid?
233
234
 
234
- job["_brainzlab_trace"] = {
235
- "trace_id" => ctx.trace_id,
236
- "span_id" => ctx.span_id,
237
- "sampled" => ctx.sampled
235
+ job['_brainzlab_trace'] = {
236
+ 'trace_id' => ctx.trace_id,
237
+ 'span_id' => ctx.span_id,
238
+ 'sampled' => ctx.sampled
238
239
  }
239
240
  rescue StandardError => e
240
241
  BrainzLab.debug_log("Failed to inject Sidekiq trace context: #{e.message}")
@@ -247,13 +248,13 @@ module BrainzLab
247
248
  spans << {
248
249
  span_id: SecureRandom.uuid,
249
250
  name: "Enqueue #{job['class']}",
250
- kind: "job",
251
+ kind: 'job',
251
252
  started_at: Time.now.utc,
252
253
  ended_at: Time.now.utc,
253
254
  duration_ms: 0,
254
255
  data: {
255
- job_class: job["class"],
256
- job_id: job["jid"],
256
+ job_class: job['class'],
257
+ job_id: job['jid'],
257
258
  queue: queue
258
259
  }
259
260
  }