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
|
@@ -25,18 +25,16 @@ module BrainzLab
|
|
|
25
25
|
overall_healthy = true
|
|
26
26
|
|
|
27
27
|
checks_to_run.each do |check|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
overall_healthy = false
|
|
35
|
-
end
|
|
28
|
+
result = send("check_#{check}")
|
|
29
|
+
results[check] = result
|
|
30
|
+
overall_healthy = false if result[:status] != 'ok'
|
|
31
|
+
rescue StandardError => e
|
|
32
|
+
results[check] = { status: 'error', message: e.message }
|
|
33
|
+
overall_healthy = false
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
{
|
|
39
|
-
status: overall_healthy ?
|
|
37
|
+
status: overall_healthy ? 'healthy' : 'unhealthy',
|
|
40
38
|
timestamp: Time.now.utc.iso8601,
|
|
41
39
|
checks: results
|
|
42
40
|
}
|
|
@@ -45,56 +43,56 @@ module BrainzLab
|
|
|
45
43
|
# Quick check - just returns status
|
|
46
44
|
def healthy?
|
|
47
45
|
result = run
|
|
48
|
-
result[:status] ==
|
|
46
|
+
result[:status] == 'healthy'
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
# Database connectivity check
|
|
52
50
|
def check_database
|
|
53
|
-
return { status:
|
|
51
|
+
return { status: 'skip', message: 'ActiveRecord not loaded' } unless defined?(ActiveRecord::Base)
|
|
54
52
|
|
|
55
53
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
56
|
-
ActiveRecord::Base.connection.execute(
|
|
54
|
+
ActiveRecord::Base.connection.execute('SELECT 1')
|
|
57
55
|
latency = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
|
|
58
56
|
|
|
59
|
-
{ status:
|
|
57
|
+
{ status: 'ok', latency_ms: latency }
|
|
60
58
|
rescue StandardError => e
|
|
61
|
-
{ status:
|
|
59
|
+
{ status: 'error', message: e.message }
|
|
62
60
|
end
|
|
63
61
|
|
|
64
62
|
# Redis connectivity check
|
|
65
63
|
def check_redis
|
|
66
|
-
return { status:
|
|
64
|
+
return { status: 'skip', message: 'Redis not configured' } unless defined?(Redis)
|
|
67
65
|
|
|
68
66
|
redis = find_redis_connection
|
|
69
|
-
return { status:
|
|
67
|
+
return { status: 'skip', message: 'No Redis connection found' } unless redis
|
|
70
68
|
|
|
71
69
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
72
70
|
redis.ping
|
|
73
71
|
latency = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
|
|
74
72
|
|
|
75
|
-
{ status:
|
|
73
|
+
{ status: 'ok', latency_ms: latency }
|
|
76
74
|
rescue StandardError => e
|
|
77
|
-
{ status:
|
|
75
|
+
{ status: 'error', message: e.message }
|
|
78
76
|
end
|
|
79
77
|
|
|
80
78
|
# Rails cache check
|
|
81
79
|
def check_cache
|
|
82
|
-
return { status:
|
|
80
|
+
return { status: 'skip', message: 'Rails not loaded' } unless defined?(Rails)
|
|
83
81
|
|
|
84
82
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
85
83
|
key = "brainzlab_health_check_#{SecureRandom.hex(4)}"
|
|
86
|
-
Rails.cache.write(key,
|
|
84
|
+
Rails.cache.write(key, 'ok', expires_in: 10.seconds)
|
|
87
85
|
value = Rails.cache.read(key)
|
|
88
86
|
Rails.cache.delete(key)
|
|
89
87
|
latency = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
|
|
90
88
|
|
|
91
|
-
if value ==
|
|
92
|
-
{ status:
|
|
89
|
+
if value == 'ok'
|
|
90
|
+
{ status: 'ok', latency_ms: latency }
|
|
93
91
|
else
|
|
94
|
-
{ status:
|
|
92
|
+
{ status: 'error', message: 'Cache read/write failed' }
|
|
95
93
|
end
|
|
96
94
|
rescue StandardError => e
|
|
97
|
-
{ status:
|
|
95
|
+
{ status: 'error', message: e.message }
|
|
98
96
|
end
|
|
99
97
|
|
|
100
98
|
# Queue system check
|
|
@@ -106,7 +104,7 @@ module BrainzLab
|
|
|
106
104
|
elsif defined?(GoodJob)
|
|
107
105
|
check_good_job
|
|
108
106
|
else
|
|
109
|
-
{ status:
|
|
107
|
+
{ status: 'skip', message: 'No queue system detected' }
|
|
110
108
|
end
|
|
111
109
|
end
|
|
112
110
|
|
|
@@ -115,11 +113,11 @@ module BrainzLab
|
|
|
115
113
|
mem_info = memory_usage
|
|
116
114
|
|
|
117
115
|
status = if mem_info[:percentage] > 90
|
|
118
|
-
|
|
116
|
+
'warning'
|
|
119
117
|
elsif mem_info[:percentage] > 95
|
|
120
|
-
|
|
118
|
+
'error'
|
|
121
119
|
else
|
|
122
|
-
|
|
120
|
+
'ok'
|
|
123
121
|
end
|
|
124
122
|
|
|
125
123
|
{
|
|
@@ -128,7 +126,7 @@ module BrainzLab
|
|
|
128
126
|
percentage: mem_info[:percentage]
|
|
129
127
|
}
|
|
130
128
|
rescue StandardError => e
|
|
131
|
-
{ status:
|
|
129
|
+
{ status: 'error', message: e.message }
|
|
132
130
|
end
|
|
133
131
|
|
|
134
132
|
# Disk space check
|
|
@@ -136,11 +134,11 @@ module BrainzLab
|
|
|
136
134
|
disk_info = disk_usage
|
|
137
135
|
|
|
138
136
|
status = if disk_info[:percentage] > 90
|
|
139
|
-
|
|
137
|
+
'warning'
|
|
140
138
|
elsif disk_info[:percentage] > 95
|
|
141
|
-
|
|
139
|
+
'error'
|
|
142
140
|
else
|
|
143
|
-
|
|
141
|
+
'ok'
|
|
144
142
|
end
|
|
145
143
|
|
|
146
144
|
{
|
|
@@ -150,7 +148,7 @@ module BrainzLab
|
|
|
150
148
|
percentage: disk_info[:percentage]
|
|
151
149
|
}
|
|
152
150
|
rescue StandardError => e
|
|
153
|
-
{ status:
|
|
151
|
+
{ status: 'error', message: e.message }
|
|
154
152
|
end
|
|
155
153
|
|
|
156
154
|
# Register a custom health check
|
|
@@ -178,54 +176,54 @@ module BrainzLab
|
|
|
178
176
|
end
|
|
179
177
|
|
|
180
178
|
def check_solid_queue
|
|
181
|
-
return { status:
|
|
179
|
+
return { status: 'skip', message: 'SolidQueue not loaded' } unless defined?(SolidQueue)
|
|
182
180
|
|
|
183
181
|
# Check if processes are running
|
|
184
182
|
if defined?(SolidQueue::Process)
|
|
185
|
-
process_count = SolidQueue::Process.where(
|
|
183
|
+
process_count = SolidQueue::Process.where('last_heartbeat_at > ?', 5.minutes.ago).count
|
|
186
184
|
{
|
|
187
|
-
status: process_count
|
|
185
|
+
status: process_count.positive? ? 'ok' : 'warning',
|
|
188
186
|
processes: process_count
|
|
189
187
|
}
|
|
190
188
|
else
|
|
191
|
-
{ status:
|
|
189
|
+
{ status: 'ok', message: 'SolidQueue configured' }
|
|
192
190
|
end
|
|
193
191
|
rescue StandardError => e
|
|
194
|
-
{ status:
|
|
192
|
+
{ status: 'error', message: e.message }
|
|
195
193
|
end
|
|
196
194
|
|
|
197
195
|
def check_sidekiq
|
|
198
|
-
return { status:
|
|
196
|
+
return { status: 'skip', message: 'Sidekiq not loaded' } unless defined?(Sidekiq)
|
|
199
197
|
|
|
200
198
|
stats = Sidekiq::Stats.new
|
|
201
199
|
{
|
|
202
|
-
status:
|
|
200
|
+
status: 'ok',
|
|
203
201
|
processed: stats.processed,
|
|
204
202
|
failed: stats.failed,
|
|
205
203
|
queues: stats.queues,
|
|
206
204
|
workers: stats.workers_size
|
|
207
205
|
}
|
|
208
206
|
rescue StandardError => e
|
|
209
|
-
{ status:
|
|
207
|
+
{ status: 'error', message: e.message }
|
|
210
208
|
end
|
|
211
209
|
|
|
212
210
|
def check_good_job
|
|
213
|
-
return { status:
|
|
211
|
+
return { status: 'skip', message: 'GoodJob not loaded' } unless defined?(GoodJob)
|
|
214
212
|
|
|
215
213
|
{
|
|
216
|
-
status:
|
|
214
|
+
status: 'ok',
|
|
217
215
|
pending: GoodJob::Job.where(performed_at: nil).count,
|
|
218
216
|
running: GoodJob::Job.running.count
|
|
219
217
|
}
|
|
220
218
|
rescue StandardError => e
|
|
221
|
-
{ status:
|
|
219
|
+
{ status: 'error', message: e.message }
|
|
222
220
|
end
|
|
223
221
|
|
|
224
222
|
def memory_usage
|
|
225
223
|
# Use /proc/self/status on Linux, ps on macOS
|
|
226
|
-
if File.exist?(
|
|
227
|
-
status = File.read(
|
|
228
|
-
vm_rss = status.match(/VmRSS:\s+(\d+)\s+kB/)&.captures&.first
|
|
224
|
+
if File.exist?('/proc/self/status')
|
|
225
|
+
status = File.read('/proc/self/status')
|
|
226
|
+
vm_rss = status.match(/VmRSS:\s+(\d+)\s+kB/)&.captures&.first.to_i
|
|
229
227
|
used_mb = (vm_rss / 1024.0).round(2)
|
|
230
228
|
else
|
|
231
229
|
# macOS fallback
|
|
@@ -235,7 +233,7 @@ module BrainzLab
|
|
|
235
233
|
end
|
|
236
234
|
|
|
237
235
|
# Estimate percentage (based on typical container memory)
|
|
238
|
-
max_mb = ENV.fetch(
|
|
236
|
+
max_mb = ENV.fetch('MEMORY_LIMIT_MB', 512).to_i
|
|
239
237
|
percentage = ((used_mb / max_mb) * 100).round(2)
|
|
240
238
|
|
|
241
239
|
{ used_mb: used_mb, percentage: percentage }
|
|
@@ -262,9 +260,9 @@ module BrainzLab
|
|
|
262
260
|
isolate_namespace BrainzLab::Utilities::HealthCheck
|
|
263
261
|
|
|
264
262
|
routes.draw do
|
|
265
|
-
get
|
|
266
|
-
get
|
|
267
|
-
get
|
|
263
|
+
get '/', to: 'health#show'
|
|
264
|
+
get '/live', to: 'health#live'
|
|
265
|
+
get '/ready', to: 'health#ready'
|
|
268
266
|
end
|
|
269
267
|
end
|
|
270
268
|
end
|
|
@@ -274,19 +272,19 @@ module BrainzLab
|
|
|
274
272
|
class HealthController < ActionController::API
|
|
275
273
|
def show
|
|
276
274
|
result = HealthCheck.run
|
|
277
|
-
status = result[:status] ==
|
|
275
|
+
status = result[:status] == 'healthy' ? :ok : :service_unavailable
|
|
278
276
|
render json: result, status: status
|
|
279
277
|
end
|
|
280
278
|
|
|
281
279
|
def live
|
|
282
280
|
# Liveness probe - just check if the app is running
|
|
283
|
-
render json: { status:
|
|
281
|
+
render json: { status: 'ok', timestamp: Time.now.utc.iso8601 }
|
|
284
282
|
end
|
|
285
283
|
|
|
286
284
|
def ready
|
|
287
285
|
# Readiness probe - check critical dependencies
|
|
288
|
-
result = HealthCheck.run(checks: [
|
|
289
|
-
status = result[:status] ==
|
|
286
|
+
result = HealthCheck.run(checks: %i[database redis])
|
|
287
|
+
status = result[:status] == 'healthy' ? :ok : :service_unavailable
|
|
290
288
|
render json: result, status: status
|
|
291
289
|
end
|
|
292
290
|
end
|
|
@@ -27,21 +27,21 @@ module BrainzLab
|
|
|
27
27
|
}.freeze
|
|
28
28
|
|
|
29
29
|
SEVERITY_ICONS = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
'DEBUG' => '🔍',
|
|
31
|
+
'INFO' => 'ℹ️ ',
|
|
32
|
+
'WARN' => '⚠️ ',
|
|
33
|
+
'ERROR' => '❌',
|
|
34
|
+
'FATAL' => '💀'
|
|
35
35
|
}.freeze
|
|
36
36
|
|
|
37
37
|
HTTP_METHODS = {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
'GET' => "\e[32m", # Green
|
|
39
|
+
'POST' => "\e[33m", # Yellow
|
|
40
|
+
'PUT' => "\e[34m", # Blue
|
|
41
|
+
'PATCH' => "\e[34m", # Blue
|
|
42
|
+
'DELETE' => "\e[31m", # Red
|
|
43
|
+
'HEAD' => "\e[36m", # Cyan
|
|
44
|
+
'OPTIONS' => "\e[36m" # Cyan
|
|
45
45
|
}.freeze
|
|
46
46
|
|
|
47
47
|
def initialize(colorize: nil, show_timestamp: true, show_severity: true, compact: false)
|
|
@@ -53,10 +53,10 @@ module BrainzLab
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def call(severity, timestamp, progname, msg)
|
|
56
|
-
return
|
|
56
|
+
return '' if msg.nil? || msg.to_s.strip.empty?
|
|
57
57
|
|
|
58
58
|
message = format_message(msg)
|
|
59
|
-
return
|
|
59
|
+
return '' if skip_message?(message)
|
|
60
60
|
|
|
61
61
|
formatted = build_output(severity, timestamp, progname, message)
|
|
62
62
|
"#{formatted}\n"
|
|
@@ -74,9 +74,9 @@ module BrainzLab
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# Also hook into ActiveSupport::TaggedLogging if present
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
return unless defined?(ActiveSupport::TaggedLogging) && Rails.logger.respond_to?(:formatter=)
|
|
78
|
+
|
|
79
|
+
Rails.logger.formatter = new
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
private
|
|
@@ -96,16 +96,16 @@ module BrainzLab
|
|
|
96
96
|
return false unless BrainzLab.configuration.log_formatter_hide_assets
|
|
97
97
|
|
|
98
98
|
# Skip asset pipeline noise
|
|
99
|
-
message.include?(
|
|
100
|
-
message.include?(
|
|
101
|
-
message.match?(
|
|
99
|
+
message.include?('/assets/') ||
|
|
100
|
+
message.include?('Asset pipeline') ||
|
|
101
|
+
message.match?(%r{Started GET "/assets/})
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
-
def build_output(severity, timestamp,
|
|
104
|
+
def build_output(severity, timestamp, _progname, message)
|
|
105
105
|
parts = []
|
|
106
106
|
|
|
107
107
|
if @show_timestamp
|
|
108
|
-
ts = colorize(timestamp.strftime(
|
|
108
|
+
ts = colorize(timestamp.strftime('%H:%M:%S.%L'), :gray)
|
|
109
109
|
parts << ts
|
|
110
110
|
end
|
|
111
111
|
|
|
@@ -116,11 +116,11 @@ module BrainzLab
|
|
|
116
116
|
|
|
117
117
|
parts << format_content(message, severity)
|
|
118
118
|
|
|
119
|
-
parts.join(
|
|
119
|
+
parts.join(' ')
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
def format_severity(severity)
|
|
123
|
-
icon = SEVERITY_ICONS[severity] ||
|
|
123
|
+
icon = SEVERITY_ICONS[severity] || ''
|
|
124
124
|
text = severity.ljust(5)
|
|
125
125
|
|
|
126
126
|
if @colorize
|
|
@@ -133,11 +133,11 @@ module BrainzLab
|
|
|
133
133
|
|
|
134
134
|
def severity_color(severity)
|
|
135
135
|
case severity
|
|
136
|
-
when
|
|
137
|
-
when
|
|
138
|
-
when
|
|
139
|
-
when
|
|
140
|
-
when
|
|
136
|
+
when 'DEBUG' then COLORS[:debug]
|
|
137
|
+
when 'INFO' then COLORS[:info]
|
|
138
|
+
when 'WARN' then COLORS[:warn]
|
|
139
|
+
when 'ERROR' then COLORS[:error]
|
|
140
|
+
when 'FATAL' then COLORS[:fatal]
|
|
141
141
|
else COLORS[:reset]
|
|
142
142
|
end
|
|
143
143
|
end
|
|
@@ -148,13 +148,13 @@ module BrainzLab
|
|
|
148
148
|
format_request_started(request_match[1], request_match[2])
|
|
149
149
|
elsif (completed_match = message.match(/Completed (\d+) .+ in (\d+(?:\.\d+)?)ms/))
|
|
150
150
|
format_request_completed(completed_match[1].to_i, completed_match[2].to_f)
|
|
151
|
-
elsif message.include?(
|
|
151
|
+
elsif message.include?('Processing by')
|
|
152
152
|
format_processing(message)
|
|
153
|
-
elsif message.include?(
|
|
153
|
+
elsif message.include?('Parameters:')
|
|
154
154
|
format_parameters(message)
|
|
155
|
-
elsif message.include?(
|
|
155
|
+
elsif message.include?('Rendering') || message.include?('Rendered')
|
|
156
156
|
format_rendering(message)
|
|
157
|
-
elsif
|
|
157
|
+
elsif %w[ERROR FATAL].include?(severity)
|
|
158
158
|
format_error(message)
|
|
159
159
|
else
|
|
160
160
|
message
|
|
@@ -220,21 +220,19 @@ module BrainzLab
|
|
|
220
220
|
if @compact
|
|
221
221
|
# Compact: just show the template name
|
|
222
222
|
if (match = message.match(/Render(?:ed|ing) ([^\s]+)/))
|
|
223
|
-
template = match[1].split(
|
|
223
|
+
template = match[1].split('/').last
|
|
224
224
|
if @colorize
|
|
225
225
|
" #{COLORS[:gray]}#{template}#{COLORS[:reset]}"
|
|
226
226
|
else
|
|
227
227
|
" #{template}"
|
|
228
228
|
end
|
|
229
229
|
else
|
|
230
|
-
|
|
230
|
+
''
|
|
231
231
|
end
|
|
232
|
+
elsif @colorize
|
|
233
|
+
" #{COLORS[:dim]}#{message}#{COLORS[:reset]}"
|
|
232
234
|
else
|
|
233
|
-
|
|
234
|
-
" #{COLORS[:dim]}#{message}#{COLORS[:reset]}"
|
|
235
|
-
else
|
|
236
|
-
" #{message}"
|
|
237
|
-
end
|
|
235
|
+
" #{message}"
|
|
238
236
|
end
|
|
239
237
|
end
|
|
240
238
|
|
|
@@ -37,7 +37,7 @@ module BrainzLab
|
|
|
37
37
|
|
|
38
38
|
# Check if request is allowed (doesn't consume a token)
|
|
39
39
|
def allowed?
|
|
40
|
-
count,
|
|
40
|
+
count, = get_current_count
|
|
41
41
|
count < @limit
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -104,7 +104,7 @@ module BrainzLab
|
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def get_current_count
|
|
107
|
-
|
|
107
|
+
current_bucket
|
|
108
108
|
data = @store.get(@key) || { buckets: {}, created_at: Time.now.to_i }
|
|
109
109
|
|
|
110
110
|
# Clean old buckets
|
|
@@ -147,15 +147,15 @@ module BrainzLab
|
|
|
147
147
|
return unless BrainzLab.configuration.flux_effectively_enabled?
|
|
148
148
|
|
|
149
149
|
if allowed
|
|
150
|
-
BrainzLab::Flux.increment(
|
|
150
|
+
BrainzLab::Flux.increment('rate_limiter.allowed', tags: { key: sanitize_key(@key) })
|
|
151
151
|
else
|
|
152
|
-
BrainzLab::Flux.increment(
|
|
152
|
+
BrainzLab::Flux.increment('rate_limiter.denied', tags: { key: sanitize_key(@key) })
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
def sanitize_key(key)
|
|
157
157
|
# Remove user-specific identifiers for aggregation
|
|
158
|
-
key.gsub(/:\d+/,
|
|
158
|
+
key.gsub(/:\d+/, ':*').gsub(/:[a-f0-9-]{36}/, ':*')
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
# Simple in-memory store (for development/single-instance)
|
data/lib/brainzlab/utilities.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
6
|
-
require_relative
|
|
3
|
+
require_relative 'utilities/rate_limiter'
|
|
4
|
+
require_relative 'utilities/circuit_breaker'
|
|
5
|
+
require_relative 'utilities/health_check'
|
|
6
|
+
require_relative 'utilities/log_formatter'
|
|
7
7
|
|
|
8
8
|
module BrainzLab
|
|
9
9
|
module Utilities
|