brainzlab 0.1.2 → 0.1.3
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 +4 -4
- data/LICENSE +6 -21
- data/README.md +16 -2
- data/lib/brainzlab/beacon/client.rb +38 -40
- data/lib/brainzlab/beacon/provisioner.rb +1 -1
- data/lib/brainzlab/beacon.rb +15 -15
- data/lib/brainzlab/configuration.rb +92 -90
- data/lib/brainzlab/context.rb +2 -3
- data/lib/brainzlab/cortex/client.rb +29 -31
- data/lib/brainzlab/cortex/provisioner.rb +1 -1
- data/lib/brainzlab/cortex.rb +7 -11
- data/lib/brainzlab/dendrite/client.rb +42 -44
- data/lib/brainzlab/dendrite/provisioner.rb +1 -1
- data/lib/brainzlab/dendrite.rb +4 -4
- data/lib/brainzlab/devtools/data/collector.rb +22 -22
- data/lib/brainzlab/devtools/middleware/asset_server.rb +14 -14
- data/lib/brainzlab/devtools/middleware/database_handler.rb +52 -55
- data/lib/brainzlab/devtools/middleware/debug_panel.rb +19 -19
- data/lib/brainzlab/devtools/middleware/error_page.rb +45 -44
- data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +39 -35
- data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +13 -9
- data/lib/brainzlab/devtools.rb +11 -11
- data/lib/brainzlab/flux/buffer.rb +3 -3
- data/lib/brainzlab/flux/client.rb +14 -16
- data/lib/brainzlab/flux/provisioner.rb +13 -13
- data/lib/brainzlab/flux.rb +8 -8
- data/lib/brainzlab/instrumentation/action_mailer.rb +14 -13
- data/lib/brainzlab/instrumentation/active_record.rb +13 -15
- data/lib/brainzlab/instrumentation/aws.rb +43 -39
- data/lib/brainzlab/instrumentation/dalli.rb +20 -20
- data/lib/brainzlab/instrumentation/delayed_job.rb +27 -29
- data/lib/brainzlab/instrumentation/elasticsearch.rb +23 -24
- data/lib/brainzlab/instrumentation/excon.rb +27 -27
- data/lib/brainzlab/instrumentation/faraday.rb +3 -4
- data/lib/brainzlab/instrumentation/good_job.rb +28 -28
- data/lib/brainzlab/instrumentation/grape.rb +24 -24
- data/lib/brainzlab/instrumentation/graphql.rb +24 -23
- data/lib/brainzlab/instrumentation/httparty.rb +13 -14
- data/lib/brainzlab/instrumentation/mongodb.rb +7 -7
- data/lib/brainzlab/instrumentation/net_http.rb +6 -6
- data/lib/brainzlab/instrumentation/redis.rb +14 -21
- data/lib/brainzlab/instrumentation/resque.rb +23 -24
- data/lib/brainzlab/instrumentation/sidekiq.rb +29 -28
- data/lib/brainzlab/instrumentation/solid_queue.rb +37 -41
- data/lib/brainzlab/instrumentation/stripe.rb +36 -37
- data/lib/brainzlab/instrumentation/typhoeus.rb +19 -17
- data/lib/brainzlab/instrumentation.rb +20 -20
- data/lib/brainzlab/nerve/client.rb +38 -40
- data/lib/brainzlab/nerve/provisioner.rb +1 -1
- data/lib/brainzlab/nerve.rb +6 -6
- data/lib/brainzlab/pulse/client.rb +15 -11
- data/lib/brainzlab/pulse/instrumentation.rb +61 -57
- data/lib/brainzlab/pulse/propagation.rb +28 -28
- data/lib/brainzlab/pulse/provisioner.rb +12 -12
- data/lib/brainzlab/pulse/tracer.rb +3 -3
- data/lib/brainzlab/pulse.rb +13 -13
- data/lib/brainzlab/rails/log_formatter.rb +127 -121
- data/lib/brainzlab/rails/log_subscriber.rb +70 -76
- data/lib/brainzlab/rails/railtie.rb +66 -89
- data/lib/brainzlab/recall/buffer.rb +1 -1
- data/lib/brainzlab/recall/client.rb +14 -10
- data/lib/brainzlab/recall/logger.rb +16 -18
- data/lib/brainzlab/recall/provisioner.rb +16 -16
- data/lib/brainzlab/recall.rb +11 -13
- data/lib/brainzlab/reflex/breadcrumbs.rb +2 -2
- data/lib/brainzlab/reflex/client.rb +14 -10
- data/lib/brainzlab/reflex/provisioner.rb +12 -12
- data/lib/brainzlab/reflex.rb +29 -29
- data/lib/brainzlab/sentinel/client.rb +40 -42
- data/lib/brainzlab/sentinel/provisioner.rb +1 -1
- data/lib/brainzlab/sentinel.rb +5 -5
- data/lib/brainzlab/signal/client.rb +12 -14
- data/lib/brainzlab/signal/provisioner.rb +12 -12
- data/lib/brainzlab/signal.rb +7 -7
- data/lib/brainzlab/synapse/client.rb +42 -44
- data/lib/brainzlab/synapse/provisioner.rb +1 -1
- data/lib/brainzlab/synapse.rb +6 -6
- data/lib/brainzlab/utilities/circuit_breaker.rb +37 -41
- data/lib/brainzlab/utilities/health_check.rb +53 -55
- data/lib/brainzlab/utilities/log_formatter.rb +38 -40
- data/lib/brainzlab/utilities/rate_limiter.rb +5 -5
- data/lib/brainzlab/utilities.rb +4 -4
- data/lib/brainzlab/vault/cache.rb +1 -1
- data/lib/brainzlab/vault/client.rb +39 -41
- data/lib/brainzlab/vault/provisioner.rb +1 -1
- data/lib/brainzlab/vault.rb +19 -25
- data/lib/brainzlab/version.rb +1 -1
- data/lib/brainzlab/vision/client.rb +20 -20
- data/lib/brainzlab/vision/provisioner.rb +21 -21
- data/lib/brainzlab/vision.rb +17 -19
- data/lib/brainzlab-sdk.rb +1 -1
- data/lib/brainzlab.rb +22 -24
- data/lib/generators/brainzlab/install/install_generator.rb +29 -27
- metadata +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'active_support/log_subscriber'
|
|
4
4
|
|
|
5
5
|
module BrainzLab
|
|
6
6
|
module Rails
|
|
@@ -21,12 +21,11 @@ module BrainzLab
|
|
|
21
21
|
params = payload[:params]&.except(*INTERNAL_PARAMS) || {}
|
|
22
22
|
|
|
23
23
|
formatter.start_request(request_id,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
)
|
|
24
|
+
method: payload[:method],
|
|
25
|
+
path: payload[:path],
|
|
26
|
+
params: filter_params(params),
|
|
27
|
+
controller: payload[:controller],
|
|
28
|
+
action: payload[:action])
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
def process_action(event)
|
|
@@ -38,18 +37,15 @@ module BrainzLab
|
|
|
38
37
|
payload = event.payload
|
|
39
38
|
|
|
40
39
|
formatter.process_action(request_id,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
40
|
+
controller: payload[:controller],
|
|
41
|
+
action: payload[:action],
|
|
42
|
+
status: payload[:status],
|
|
43
|
+
duration: event.duration,
|
|
44
|
+
view_runtime: payload[:view_runtime],
|
|
45
|
+
db_runtime: payload[:db_runtime])
|
|
48
46
|
|
|
49
47
|
# Handle exception if present
|
|
50
|
-
if payload[:exception_object]
|
|
51
|
-
formatter.error(request_id, payload[:exception_object])
|
|
52
|
-
end
|
|
48
|
+
formatter.error(request_id, payload[:exception_object]) if payload[:exception_object]
|
|
53
49
|
|
|
54
50
|
# Output the formatted log
|
|
55
51
|
output = formatter.end_request(request_id)
|
|
@@ -81,11 +77,11 @@ module BrainzLab
|
|
|
81
77
|
case obj
|
|
82
78
|
when Hash
|
|
83
79
|
obj.each_with_object({}) do |(k, v), h|
|
|
84
|
-
if filter_keys.include?(k.to_s.downcase)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
80
|
+
h[k] = if filter_keys.include?(k.to_s.downcase)
|
|
81
|
+
'[FILTERED]'
|
|
82
|
+
else
|
|
83
|
+
deep_filter(v, filter_keys)
|
|
84
|
+
end
|
|
89
85
|
end
|
|
90
86
|
when Array
|
|
91
87
|
obj.map { |v| deep_filter(v, filter_keys) }
|
|
@@ -121,13 +117,12 @@ module BrainzLab
|
|
|
121
117
|
sql_pattern = normalize_sql(payload[:sql])
|
|
122
118
|
|
|
123
119
|
LogSubscriber.formatter.sql_query(request_id,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
)
|
|
120
|
+
name: payload[:name],
|
|
121
|
+
duration: event.duration,
|
|
122
|
+
sql: payload[:sql],
|
|
123
|
+
sql_pattern: sql_pattern,
|
|
124
|
+
cached: payload[:cached] || payload[:name] == 'CACHE',
|
|
125
|
+
source: source)
|
|
131
126
|
end
|
|
132
127
|
|
|
133
128
|
private
|
|
@@ -135,11 +130,11 @@ module BrainzLab
|
|
|
135
130
|
def extract_source_location(backtrace)
|
|
136
131
|
# Find the first line that's in app/ directory
|
|
137
132
|
backtrace.each do |line|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
133
|
+
next unless line.include?('/app/') && !line.include?('/brainzlab')
|
|
134
|
+
|
|
135
|
+
# Extract just the relevant part: app/models/user.rb:42
|
|
136
|
+
match = line.match(%r{(app/[^:]+:\d+)})
|
|
137
|
+
return match[1] if match
|
|
143
138
|
end
|
|
144
139
|
nil
|
|
145
140
|
end
|
|
@@ -148,11 +143,11 @@ module BrainzLab
|
|
|
148
143
|
return nil unless sql
|
|
149
144
|
|
|
150
145
|
sql
|
|
151
|
-
.gsub(/\b\d+\b/,
|
|
152
|
-
.gsub(/'[^']*'/,
|
|
153
|
-
.gsub(/\$\d+/,
|
|
154
|
-
.gsub(
|
|
155
|
-
.gsub(/\s+/,
|
|
146
|
+
.gsub(/\b\d+\b/, '?') # Replace numbers
|
|
147
|
+
.gsub(/'[^']*'/, '?') # Replace single-quoted strings
|
|
148
|
+
.gsub(/\$\d+/, '?') # Replace positional params
|
|
149
|
+
.gsub(%r{/\*.*?\*/}, '') # Remove comments
|
|
150
|
+
.gsub(/\s+/, ' ') # Normalize whitespace
|
|
156
151
|
.strip
|
|
157
152
|
end
|
|
158
153
|
end
|
|
@@ -182,18 +177,18 @@ module BrainzLab
|
|
|
182
177
|
return broadcasting unless broadcasting
|
|
183
178
|
|
|
184
179
|
# Extract channel name from gid format: logs:Z2lkOi8vcmVjYWxsL1Byb2plY3QvNDhi...
|
|
185
|
-
if broadcasting.start_with?(
|
|
186
|
-
|
|
187
|
-
elsif broadcasting.include?(
|
|
180
|
+
if broadcasting.start_with?('logs:')
|
|
181
|
+
'LogsChannel'
|
|
182
|
+
elsif broadcasting.include?(':')
|
|
188
183
|
# Generic channel:id format
|
|
189
|
-
broadcasting.split(
|
|
184
|
+
"#{broadcasting.split(':').first.capitalize}Channel"
|
|
190
185
|
else
|
|
191
186
|
broadcasting
|
|
192
187
|
end
|
|
193
188
|
end
|
|
194
189
|
|
|
195
190
|
def format_message(message)
|
|
196
|
-
return
|
|
191
|
+
return '{}' unless message
|
|
197
192
|
|
|
198
193
|
case message
|
|
199
194
|
when Hash
|
|
@@ -214,58 +209,60 @@ module BrainzLab
|
|
|
214
209
|
parts = []
|
|
215
210
|
|
|
216
211
|
# Show key fields for log entries
|
|
217
|
-
if hash[
|
|
218
|
-
level = hash[
|
|
212
|
+
if hash['level'] || hash[:level]
|
|
213
|
+
level = hash['level'] || hash[:level]
|
|
219
214
|
parts << colorize_level(level)
|
|
220
215
|
end
|
|
221
216
|
|
|
222
|
-
if hash[
|
|
223
|
-
msg = hash[
|
|
217
|
+
if hash['message'] || hash[:message]
|
|
218
|
+
msg = hash['message'] || hash[:message]
|
|
224
219
|
parts << truncate(msg.to_s, 50)
|
|
225
220
|
end
|
|
226
221
|
|
|
227
|
-
if hash[
|
|
228
|
-
id = hash[
|
|
222
|
+
if hash['id'] || hash[:id]
|
|
223
|
+
id = hash['id'] || hash[:id]
|
|
229
224
|
parts << colorize(id.to_s[0..7], :gray)
|
|
230
225
|
end
|
|
231
226
|
|
|
232
|
-
parts.any? ? parts.join(
|
|
227
|
+
parts.any? ? parts.join(' ') : hash.keys.first(3).join(', ')
|
|
233
228
|
end
|
|
234
229
|
|
|
235
230
|
def build_output(channel, message, duration)
|
|
236
|
-
time = Time.current.strftime(
|
|
237
|
-
duration_str = duration ? "#{duration.round(1)}ms" :
|
|
231
|
+
time = Time.current.strftime('%H:%M:%S')
|
|
232
|
+
duration_str = duration ? "#{duration.round(1)}ms" : ''
|
|
238
233
|
|
|
239
234
|
parts = [
|
|
240
235
|
colorize(time, :gray),
|
|
241
|
-
colorize(
|
|
236
|
+
colorize('⚡', :magenta),
|
|
242
237
|
colorize(channel, :magenta),
|
|
243
|
-
colorize(
|
|
238
|
+
colorize('→', :gray),
|
|
244
239
|
message,
|
|
245
240
|
colorize(duration_str, :gray)
|
|
246
241
|
]
|
|
247
242
|
|
|
248
|
-
"
|
|
243
|
+
" #{parts.join(' ')}\n"
|
|
249
244
|
end
|
|
250
245
|
|
|
251
246
|
def truncate(text, length)
|
|
252
247
|
return text if text.nil? || text.length <= length
|
|
248
|
+
|
|
253
249
|
"#{text[0..(length - 4)]}..."
|
|
254
250
|
end
|
|
255
251
|
|
|
256
252
|
def colorize(text, color)
|
|
257
253
|
return text unless $stdout.tty?
|
|
258
254
|
return text unless COLORS[color]
|
|
255
|
+
|
|
259
256
|
"#{COLORS[color]}#{text}#{COLORS[:reset]}"
|
|
260
257
|
end
|
|
261
258
|
|
|
262
259
|
def colorize_level(level)
|
|
263
260
|
color = case level.to_s.downcase
|
|
264
|
-
when
|
|
265
|
-
when
|
|
266
|
-
when
|
|
267
|
-
when
|
|
268
|
-
when
|
|
261
|
+
when 'debug' then :gray
|
|
262
|
+
when 'info' then :green
|
|
263
|
+
when 'warn', 'warning' then :yellow
|
|
264
|
+
when 'error' then :red
|
|
265
|
+
when 'fatal' then :red
|
|
269
266
|
else :white
|
|
270
267
|
end
|
|
271
268
|
colorize(level.to_s.upcase.ljust(5), color)
|
|
@@ -284,10 +281,9 @@ module BrainzLab
|
|
|
284
281
|
template = template_name(payload[:identifier])
|
|
285
282
|
|
|
286
283
|
LogSubscriber.formatter.render_template(request_id,
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
)
|
|
284
|
+
template: template,
|
|
285
|
+
duration: event.duration,
|
|
286
|
+
layout: payload[:layout])
|
|
291
287
|
end
|
|
292
288
|
|
|
293
289
|
def render_partial(event)
|
|
@@ -300,10 +296,9 @@ module BrainzLab
|
|
|
300
296
|
template = template_name(payload[:identifier])
|
|
301
297
|
|
|
302
298
|
LogSubscriber.formatter.render_partial(request_id,
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
)
|
|
299
|
+
template: template,
|
|
300
|
+
duration: event.duration,
|
|
301
|
+
count: payload[:count])
|
|
307
302
|
end
|
|
308
303
|
|
|
309
304
|
def render_layout(event)
|
|
@@ -316,9 +311,8 @@ module BrainzLab
|
|
|
316
311
|
layout = template_name(payload[:identifier])
|
|
317
312
|
|
|
318
313
|
LogSubscriber.formatter.render_layout(request_id,
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
)
|
|
314
|
+
layout: layout,
|
|
315
|
+
duration: event.duration)
|
|
322
316
|
end
|
|
323
317
|
|
|
324
318
|
private
|
|
@@ -327,10 +321,10 @@ module BrainzLab
|
|
|
327
321
|
return nil unless identifier
|
|
328
322
|
|
|
329
323
|
# Extract relative path from full identifier
|
|
330
|
-
if identifier.include?(
|
|
331
|
-
identifier.split(
|
|
332
|
-
elsif identifier.include?(
|
|
333
|
-
identifier.split(
|
|
324
|
+
if identifier.include?('/app/views/')
|
|
325
|
+
identifier.split('/app/views/').last
|
|
326
|
+
elsif identifier.include?('/views/')
|
|
327
|
+
identifier.split('/views/').last
|
|
334
328
|
else
|
|
335
329
|
File.basename(identifier)
|
|
336
330
|
end
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'English'
|
|
3
4
|
module BrainzLab
|
|
4
5
|
module Rails
|
|
5
6
|
class Railtie < ::Rails::Railtie
|
|
6
7
|
generators do
|
|
7
|
-
require
|
|
8
|
+
require 'generators/brainzlab/install/install_generator'
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
# Load Vault secrets early, before configuration
|
|
11
12
|
# This allows secrets to be used in config files
|
|
12
|
-
initializer
|
|
13
|
+
initializer 'brainzlab.load_vault_secrets', before: :load_environment_config do
|
|
13
14
|
if BrainzLab.configuration.vault_enabled && BrainzLab.configuration.vault_auto_load
|
|
14
|
-
BrainzLab.debug_log(
|
|
15
|
+
BrainzLab.debug_log('[Vault] Auto-loading secrets into ENV...')
|
|
15
16
|
BrainzLab::Vault.load!(
|
|
16
17
|
provider_keys: BrainzLab.configuration.vault_load_provider_keys
|
|
17
18
|
)
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
initializer
|
|
22
|
+
initializer 'brainzlab.configure_rails_initialization' do |app|
|
|
22
23
|
# Set defaults from Rails
|
|
23
24
|
BrainzLab.configure do |config|
|
|
24
25
|
config.environment ||= ::Rails.env.to_s
|
|
@@ -34,7 +35,7 @@ module BrainzLab
|
|
|
34
35
|
|
|
35
36
|
# Add DevTools middlewares if enabled
|
|
36
37
|
if BrainzLab.configuration.devtools_enabled
|
|
37
|
-
require_relative
|
|
38
|
+
require_relative '../devtools'
|
|
38
39
|
|
|
39
40
|
# Asset server (handles /__brainzlab__/* requests)
|
|
40
41
|
app.middleware.insert_before ActionDispatch::Static, BrainzLab::DevTools::Middleware::AssetServer
|
|
@@ -46,9 +47,7 @@ module BrainzLab
|
|
|
46
47
|
# Error page (catches exceptions and renders branded error page)
|
|
47
48
|
# Insert BEFORE DebugExceptions so we can intercept the HTML error page
|
|
48
49
|
# that DebugExceptions renders and replace it with our own
|
|
49
|
-
if defined?(ActionDispatch::DebugExceptions)
|
|
50
|
-
app.middleware.insert_before ActionDispatch::DebugExceptions, BrainzLab::DevTools::Middleware::ErrorPage
|
|
51
|
-
end
|
|
50
|
+
app.middleware.insert_before ActionDispatch::DebugExceptions, BrainzLab::DevTools::Middleware::ErrorPage if defined?(ActionDispatch::DebugExceptions)
|
|
52
51
|
|
|
53
52
|
# Debug panel (injects panel into HTML responses)
|
|
54
53
|
app.middleware.use BrainzLab::DevTools::Middleware::DebugPanel
|
|
@@ -71,14 +70,10 @@ module BrainzLab
|
|
|
71
70
|
end
|
|
72
71
|
|
|
73
72
|
# Hook into ActiveJob
|
|
74
|
-
if defined?(ActiveJob::Base)
|
|
75
|
-
ActiveJob::Base.include(BrainzLab::Rails::ActiveJobExtension)
|
|
76
|
-
end
|
|
73
|
+
ActiveJob::Base.include(BrainzLab::Rails::ActiveJobExtension) if defined?(ActiveJob::Base)
|
|
77
74
|
|
|
78
75
|
# Hook into ActionController for rescue_from fallback
|
|
79
|
-
if defined?(ActionController::Base)
|
|
80
|
-
ActionController::Base.include(BrainzLab::Rails::ControllerExtension)
|
|
81
|
-
end
|
|
76
|
+
ActionController::Base.include(BrainzLab::Rails::ControllerExtension) if defined?(ActionController::Base)
|
|
82
77
|
|
|
83
78
|
# Hook into Sidekiq if available
|
|
84
79
|
if defined?(Sidekiq)
|
|
@@ -91,8 +86,8 @@ module BrainzLab
|
|
|
91
86
|
class << self
|
|
92
87
|
def setup_log_formatter
|
|
93
88
|
# Lazy require to ensure Rails is fully loaded
|
|
94
|
-
require_relative
|
|
95
|
-
require_relative
|
|
89
|
+
require_relative 'log_formatter'
|
|
90
|
+
require_relative 'log_subscriber'
|
|
96
91
|
|
|
97
92
|
config = BrainzLab.configuration
|
|
98
93
|
|
|
@@ -124,37 +119,23 @@ module BrainzLab
|
|
|
124
119
|
null_logger.level = Logger::FATAL
|
|
125
120
|
|
|
126
121
|
# Silence ActiveRecord SQL logging
|
|
127
|
-
if defined?(ActiveRecord::Base)
|
|
128
|
-
ActiveRecord::Base.logger = null_logger
|
|
129
|
-
end
|
|
122
|
+
ActiveRecord::Base.logger = null_logger if defined?(ActiveRecord::Base)
|
|
130
123
|
|
|
131
124
|
# Silence ActionController logging (the "Completed" message)
|
|
132
|
-
if defined?(ActionController::Base)
|
|
133
|
-
ActionController::Base.logger = null_logger
|
|
134
|
-
end
|
|
125
|
+
ActionController::Base.logger = null_logger if defined?(ActionController::Base)
|
|
135
126
|
|
|
136
127
|
# Silence ActionView logging
|
|
137
|
-
if defined?(ActionView::Base)
|
|
138
|
-
ActionView::Base.logger = null_logger
|
|
139
|
-
end
|
|
128
|
+
ActionView::Base.logger = null_logger if defined?(ActionView::Base)
|
|
140
129
|
|
|
141
130
|
# Silence the class-level loggers for specific subscribers
|
|
142
|
-
if defined?(ActionController::LogSubscriber)
|
|
143
|
-
ActionController::LogSubscriber.logger = null_logger
|
|
144
|
-
end
|
|
131
|
+
ActionController::LogSubscriber.logger = null_logger if defined?(ActionController::LogSubscriber)
|
|
145
132
|
|
|
146
|
-
if defined?(ActionView::LogSubscriber)
|
|
147
|
-
ActionView::LogSubscriber.logger = null_logger
|
|
148
|
-
end
|
|
133
|
+
ActionView::LogSubscriber.logger = null_logger if defined?(ActionView::LogSubscriber)
|
|
149
134
|
|
|
150
|
-
if defined?(ActiveRecord::LogSubscriber)
|
|
151
|
-
ActiveRecord::LogSubscriber.logger = null_logger
|
|
152
|
-
end
|
|
135
|
+
ActiveRecord::LogSubscriber.logger = null_logger if defined?(ActiveRecord::LogSubscriber)
|
|
153
136
|
|
|
154
137
|
# Silence ActionCable logging
|
|
155
|
-
if defined?(ActionCable::Server::Base)
|
|
156
|
-
ActionCable.server.config.logger = null_logger
|
|
157
|
-
end
|
|
138
|
+
ActionCable.server.config.logger = null_logger if defined?(ActionCable::Server::Base)
|
|
158
139
|
|
|
159
140
|
if defined?(ActionCable::Connection::TaggedLoggerProxy)
|
|
160
141
|
# ActionCable uses a tagged logger proxy that we need to quiet
|
|
@@ -184,7 +165,7 @@ module BrainzLab
|
|
|
184
165
|
/^Rendering/,
|
|
185
166
|
/^Rendered/,
|
|
186
167
|
/^\[ActionCable\] Broadcasting/,
|
|
187
|
-
/^\s*$/
|
|
168
|
+
/^\s*$/ # Empty lines
|
|
188
169
|
].freeze
|
|
189
170
|
|
|
190
171
|
def call(severity, datetime, progname, msg)
|
|
@@ -215,7 +196,7 @@ module BrainzLab
|
|
|
215
196
|
|
|
216
197
|
# Set request context
|
|
217
198
|
context = BrainzLab::Context.current
|
|
218
|
-
request_id = request.request_id || env[
|
|
199
|
+
request_id = request.request_id || env['action_dispatch.request_id']
|
|
219
200
|
context.request_id = request_id
|
|
220
201
|
|
|
221
202
|
# Store request_id in thread local for log subscriber
|
|
@@ -224,7 +205,11 @@ module BrainzLab
|
|
|
224
205
|
# Capture session_id - access session to ensure it's loaded
|
|
225
206
|
if request.session.respond_to?(:id)
|
|
226
207
|
# Force session load by accessing it
|
|
227
|
-
session_id =
|
|
208
|
+
session_id = begin
|
|
209
|
+
request.session.id
|
|
210
|
+
rescue StandardError
|
|
211
|
+
nil
|
|
212
|
+
end
|
|
228
213
|
context.session_id = session_id.to_s if session_id.present?
|
|
229
214
|
end
|
|
230
215
|
|
|
@@ -238,7 +223,7 @@ module BrainzLab
|
|
|
238
223
|
# Add breadcrumb for request start
|
|
239
224
|
BrainzLab::Reflex.add_breadcrumb(
|
|
240
225
|
"#{request.request_method} #{request.path}",
|
|
241
|
-
category:
|
|
226
|
+
category: 'http.request',
|
|
242
227
|
level: :info,
|
|
243
228
|
data: { url: request.url }
|
|
244
229
|
)
|
|
@@ -262,7 +247,7 @@ module BrainzLab
|
|
|
262
247
|
Thread.current[:brainzlab_pulse_breakdown] = nil
|
|
263
248
|
BrainzLab::Pulse.start_trace(
|
|
264
249
|
"#{request.request_method} #{request.path}",
|
|
265
|
-
kind:
|
|
250
|
+
kind: 'request',
|
|
266
251
|
parent_context: parent_context
|
|
267
252
|
)
|
|
268
253
|
end
|
|
@@ -272,7 +257,7 @@ module BrainzLab
|
|
|
272
257
|
# Add breadcrumb for response
|
|
273
258
|
BrainzLab::Reflex.add_breadcrumb(
|
|
274
259
|
"Response #{status}",
|
|
275
|
-
category:
|
|
260
|
+
category: 'http.response',
|
|
276
261
|
level: status >= 400 ? :error : :info,
|
|
277
262
|
data: { status: status }
|
|
278
263
|
)
|
|
@@ -290,9 +275,7 @@ module BrainzLab
|
|
|
290
275
|
raise
|
|
291
276
|
ensure
|
|
292
277
|
# Finish Pulse trace for successful requests
|
|
293
|
-
if should_trace &&
|
|
294
|
-
record_pulse_trace(request, started_at, status)
|
|
295
|
-
end
|
|
278
|
+
record_pulse_trace(request, started_at, status) if should_trace && !$ERROR_INFO
|
|
296
279
|
|
|
297
280
|
Thread.current[:brainzlab_request_id] = nil
|
|
298
281
|
BrainzLab::Context.clear!
|
|
@@ -306,8 +289,8 @@ module BrainzLab
|
|
|
306
289
|
path = request.path
|
|
307
290
|
|
|
308
291
|
# Check if path matches any excluded pattern
|
|
309
|
-
|
|
310
|
-
if pattern.include?(
|
|
292
|
+
excluded.none? do |pattern|
|
|
293
|
+
if pattern.include?('*')
|
|
311
294
|
File.fnmatch?(pattern, path)
|
|
312
295
|
else
|
|
313
296
|
path.start_with?(pattern)
|
|
@@ -323,7 +306,6 @@ module BrainzLab
|
|
|
323
306
|
spans = Thread.current[:brainzlab_pulse_spans] || []
|
|
324
307
|
breakdown = Thread.current[:brainzlab_pulse_breakdown] || {}
|
|
325
308
|
|
|
326
|
-
|
|
327
309
|
# Format spans for API
|
|
328
310
|
formatted_spans = spans.map do |span|
|
|
329
311
|
{
|
|
@@ -339,7 +321,7 @@ module BrainzLab
|
|
|
339
321
|
|
|
340
322
|
BrainzLab::Pulse.record_trace(
|
|
341
323
|
"#{request.request_method} #{request.path}",
|
|
342
|
-
kind:
|
|
324
|
+
kind: 'request',
|
|
343
325
|
started_at: started_at,
|
|
344
326
|
ended_at: ended_at,
|
|
345
327
|
request_id: context.request_id,
|
|
@@ -377,11 +359,11 @@ module BrainzLab
|
|
|
377
359
|
case obj
|
|
378
360
|
when Hash
|
|
379
361
|
obj.each_with_object({}) do |(k, v), h|
|
|
380
|
-
if BrainzLab::Reflex::FILTERED_PARAMS.include?(k.to_s)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
362
|
+
h[k] = if BrainzLab::Reflex::FILTERED_PARAMS.include?(k.to_s)
|
|
363
|
+
'[FILTERED]'
|
|
364
|
+
else
|
|
365
|
+
deep_filter(v)
|
|
366
|
+
end
|
|
385
367
|
end
|
|
386
368
|
when Array
|
|
387
369
|
obj.map { |v| deep_filter(v) }
|
|
@@ -408,11 +390,11 @@ module BrainzLab
|
|
|
408
390
|
def extract_headers(env)
|
|
409
391
|
headers = {}
|
|
410
392
|
env.each do |key, value|
|
|
411
|
-
next unless key.start_with?(
|
|
412
|
-
next if key ==
|
|
413
|
-
next if key ==
|
|
393
|
+
next unless key.start_with?('HTTP_')
|
|
394
|
+
next if key == 'HTTP_COOKIE'
|
|
395
|
+
next if key == 'HTTP_AUTHORIZATION'
|
|
414
396
|
|
|
415
|
-
header_name = key.sub(
|
|
397
|
+
header_name = key.sub('HTTP_', '').split('_').map(&:capitalize).join('-')
|
|
416
398
|
headers[header_name] = value
|
|
417
399
|
end
|
|
418
400
|
headers
|
|
@@ -424,11 +406,10 @@ module BrainzLab
|
|
|
424
406
|
def report(error, handled:, severity:, context: {}, source: nil)
|
|
425
407
|
# Capture both handled and unhandled, but mark them
|
|
426
408
|
BrainzLab::Reflex.capture(error,
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
)
|
|
409
|
+
handled: handled,
|
|
410
|
+
severity: severity.to_s,
|
|
411
|
+
source: source,
|
|
412
|
+
extra: context)
|
|
432
413
|
rescue StandardError => e
|
|
433
414
|
BrainzLab.configuration.logger&.error("[BrainzLab] ErrorSubscriber failed: #{e.message}")
|
|
434
415
|
end
|
|
@@ -454,7 +435,7 @@ module BrainzLab
|
|
|
454
435
|
# Add breadcrumb
|
|
455
436
|
BrainzLab::Reflex.add_breadcrumb(
|
|
456
437
|
"#{self.class.name}##{action_name}",
|
|
457
|
-
category:
|
|
438
|
+
category: 'controller',
|
|
458
439
|
level: :info
|
|
459
440
|
)
|
|
460
441
|
|
|
@@ -491,7 +472,7 @@ module BrainzLab
|
|
|
491
472
|
|
|
492
473
|
BrainzLab::Reflex.add_breadcrumb(
|
|
493
474
|
"Job #{self.class.name}",
|
|
494
|
-
category:
|
|
475
|
+
category: 'job',
|
|
495
476
|
level: :info,
|
|
496
477
|
data: { job_id: job_id, queue: queue_name }
|
|
497
478
|
)
|
|
@@ -501,7 +482,7 @@ module BrainzLab
|
|
|
501
482
|
if should_trace
|
|
502
483
|
Thread.current[:brainzlab_pulse_spans] = []
|
|
503
484
|
Thread.current[:brainzlab_pulse_breakdown] = nil
|
|
504
|
-
BrainzLab::Pulse.start_trace(self.class.name, kind:
|
|
485
|
+
BrainzLab::Pulse.start_trace(self.class.name, kind: 'job')
|
|
505
486
|
end
|
|
506
487
|
|
|
507
488
|
error_occurred = nil
|
|
@@ -513,9 +494,7 @@ module BrainzLab
|
|
|
513
494
|
end
|
|
514
495
|
ensure
|
|
515
496
|
# Record Pulse trace for job
|
|
516
|
-
if should_trace
|
|
517
|
-
record_pulse_job_trace(started_at, error_occurred)
|
|
518
|
-
end
|
|
497
|
+
record_pulse_job_trace(started_at, error_occurred) if should_trace
|
|
519
498
|
|
|
520
499
|
BrainzLab::Context.clear!
|
|
521
500
|
end
|
|
@@ -550,7 +529,7 @@ module BrainzLab
|
|
|
550
529
|
|
|
551
530
|
BrainzLab::Pulse.record_trace(
|
|
552
531
|
self.class.name,
|
|
553
|
-
kind:
|
|
532
|
+
kind: 'job',
|
|
554
533
|
started_at: started_at,
|
|
555
534
|
ended_at: ended_at,
|
|
556
535
|
job_class: self.class.name,
|
|
@@ -589,15 +568,14 @@ module BrainzLab
|
|
|
589
568
|
|
|
590
569
|
def brainzlab_rescue_job(exception)
|
|
591
570
|
BrainzLab::Reflex.capture(exception,
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
)
|
|
571
|
+
tags: { type: 'background_job' },
|
|
572
|
+
extra: {
|
|
573
|
+
job_class: self.class.name,
|
|
574
|
+
job_id: job_id,
|
|
575
|
+
queue_name: queue_name,
|
|
576
|
+
executions: executions,
|
|
577
|
+
arguments: arguments.map(&:to_s).first(5)
|
|
578
|
+
})
|
|
601
579
|
raise exception # Re-raise to let ActiveJob handle retries
|
|
602
580
|
end
|
|
603
581
|
end
|
|
@@ -606,15 +584,14 @@ module BrainzLab
|
|
|
606
584
|
class SidekiqErrorHandler
|
|
607
585
|
def call(exception, context, _config = nil)
|
|
608
586
|
BrainzLab::Reflex.capture(exception,
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
)
|
|
587
|
+
tags: { type: 'sidekiq' },
|
|
588
|
+
extra: {
|
|
589
|
+
job_class: context[:job]['class'],
|
|
590
|
+
job_id: context[:job]['jid'],
|
|
591
|
+
queue: context[:job]['queue'],
|
|
592
|
+
args: context[:job]['args']&.map(&:to_s)&.first(5),
|
|
593
|
+
retry_count: context[:job]['retry_count']
|
|
594
|
+
})
|
|
618
595
|
rescue StandardError => e
|
|
619
596
|
BrainzLab.configuration.logger&.error("[BrainzLab] Sidekiq handler failed: #{e.message}")
|
|
620
597
|
end
|