brainzlab 0.1.34 → 0.1.35
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/lib/brainzlab/beacon/client.rb +4 -6
- data/lib/brainzlab/configuration.rb +301 -272
- data/lib/brainzlab/cortex/client.rb +4 -6
- data/lib/brainzlab/debug.rb +6 -6
- data/lib/brainzlab/dendrite/client.rb +4 -6
- data/lib/brainzlab/development/logger.rb +2 -2
- data/lib/brainzlab/development/store.rb +2 -4
- data/lib/brainzlab/devtools/middleware/error_page.rb +1 -1
- data/lib/brainzlab/errors.rb +5 -12
- data/lib/brainzlab/instrumentation/action_cable.rb +4 -4
- data/lib/brainzlab/instrumentation/action_controller.rb +12 -12
- data/lib/brainzlab/instrumentation/action_dispatch.rb +1 -1
- data/lib/brainzlab/instrumentation/action_mailbox.rb +7 -13
- data/lib/brainzlab/instrumentation/action_view.rb +29 -33
- data/lib/brainzlab/instrumentation/active_job.rb +6 -10
- data/lib/brainzlab/instrumentation/active_record.rb +21 -24
- data/lib/brainzlab/instrumentation/active_storage.rb +4 -4
- data/lib/brainzlab/instrumentation/active_support_cache.rb +6 -8
- data/lib/brainzlab/instrumentation/aws.rb +10 -7
- data/lib/brainzlab/instrumentation/grape.rb +3 -1
- data/lib/brainzlab/instrumentation/rails_deprecation.rb +1 -1
- data/lib/brainzlab/instrumentation/railties.rb +2 -2
- data/lib/brainzlab/nerve/client.rb +4 -6
- data/lib/brainzlab/pulse/client.rb +1 -1
- data/lib/brainzlab/pulse.rb +5 -1
- data/lib/brainzlab/rails/railtie.rb +1 -3
- data/lib/brainzlab/reflex/client.rb +1 -1
- data/lib/brainzlab/sentinel/client.rb +4 -6
- data/lib/brainzlab/synapse/client.rb +4 -6
- data/lib/brainzlab/testing/event_store.rb +3 -3
- data/lib/brainzlab/testing/matchers.rb +4 -4
- data/lib/brainzlab/testing.rb +5 -3
- data/lib/brainzlab/vault/client.rb +4 -6
- data/lib/brainzlab/version.rb +1 -1
- data/lib/brainzlab/vision/client.rb +3 -3
- data/lib/fluyenta-ruby.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf1207ec18676d63267312a25c4bcbe2519a1ddc70ceb5bb34ac58f7a83e29d2
|
|
4
|
+
data.tar.gz: d8ea421af25cae73f94d4741eed9a404c6297477088eaf3df9b4a000675824da
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2bee3ad0497520af5744ccd898360f389ac30bf599382d4af14f871d2b1f30659a5879a8ad5a6dfcfd1bf008445e0262a1d2fa5887d00146128099cda99410b3
|
|
7
|
+
data.tar.gz: 0760d616e2b3a32c2c408098d5a69d4a68d3d3ab52f3dbde121d2994c4498bb5c26cbc24fd6d569a3f41d6614cceca3075a9f06df1bbdea1bd5f9da399da2861
|
|
@@ -204,9 +204,9 @@ module BrainzLab
|
|
|
204
204
|
BrainzLab.debug_log("[Beacon::Client] #{operation} failed: #{structured_error.message}")
|
|
205
205
|
|
|
206
206
|
# Call on_error callback if configured
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
return unless @config.on_error
|
|
208
|
+
|
|
209
|
+
@config.on_error.call(structured_error, { service: 'Beacon', operation: operation })
|
|
210
210
|
end
|
|
211
211
|
|
|
212
212
|
def handle_response_error(response, operation)
|
|
@@ -216,9 +216,7 @@ module BrainzLab
|
|
|
216
216
|
BrainzLab.debug_log("[Beacon::Client] #{operation} failed: #{structured_error.message}")
|
|
217
217
|
|
|
218
218
|
# Call on_error callback if configured
|
|
219
|
-
|
|
220
|
-
@config.on_error.call(structured_error, { service: 'Beacon', operation: operation })
|
|
221
|
-
end
|
|
219
|
+
@config.on_error&.call(structured_error, { service: 'Beacon', operation: operation })
|
|
222
220
|
|
|
223
221
|
structured_error
|
|
224
222
|
end
|
|
@@ -199,270 +199,13 @@ module BrainzLab
|
|
|
199
199
|
}.freeze
|
|
200
200
|
|
|
201
201
|
def initialize
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
@environment = ENV['BRAINZLAB_ENVIRONMENT'] || detect_environment
|
|
210
|
-
@service = ENV.fetch('BRAINZLAB_SERVICE', nil)
|
|
211
|
-
@host = ENV['BRAINZLAB_HOST'] || detect_host
|
|
212
|
-
|
|
213
|
-
# App name for auto-provisioning
|
|
214
|
-
@app_name = ENV.fetch('BRAINZLAB_APP_NAME', nil)
|
|
215
|
-
|
|
216
|
-
# Git context
|
|
217
|
-
@commit = ENV['GIT_COMMIT'] || ENV['COMMIT_SHA'] || detect_git_commit
|
|
218
|
-
@branch = ENV['GIT_BRANCH'] || ENV['BRANCH_NAME'] || detect_git_branch
|
|
219
|
-
|
|
220
|
-
# Debug mode - enables verbose logging
|
|
221
|
-
@debug = ENV['BRAINZLAB_DEBUG'] == 'true'
|
|
222
|
-
|
|
223
|
-
# SDK mode - :production (default) or :development (offline, local storage)
|
|
224
|
-
@mode = ENV['BRAINZLAB_MODE']&.to_sym || :production
|
|
225
|
-
|
|
226
|
-
# Development mode settings
|
|
227
|
-
@development_db_path = ENV['BRAINZLAB_DEV_DB_PATH'] || 'tmp/brainzlab.sqlite3'
|
|
228
|
-
@development_log_output = $stdout
|
|
229
|
-
|
|
230
|
-
# Disable self-tracking - prevents services from tracking to themselves
|
|
231
|
-
# e.g., Recall won't log to itself, Reflex won't track errors to itself
|
|
232
|
-
@disable_self_tracking = ENV.fetch('BRAINZLAB_DISABLE_SELF_TRACKING', 'true') == 'true'
|
|
233
|
-
|
|
234
|
-
# Recall settings
|
|
235
|
-
@recall_enabled = true
|
|
236
|
-
@recall_url = ENV['RECALL_URL'] || detect_product_url('recall')
|
|
237
|
-
@recall_min_level = :debug
|
|
238
|
-
@recall_buffer_size = 50
|
|
239
|
-
@recall_flush_interval = 5
|
|
240
|
-
@recall_master_key = ENV.fetch('RECALL_MASTER_KEY', nil)
|
|
241
|
-
@recall_auto_provision = true
|
|
242
|
-
|
|
243
|
-
# Reflex settings
|
|
244
|
-
@reflex_enabled = true
|
|
245
|
-
@reflex_url = ENV['REFLEX_URL'] || detect_product_url('reflex')
|
|
246
|
-
@reflex_api_key = ENV.fetch('REFLEX_API_KEY', nil)
|
|
247
|
-
@reflex_master_key = ENV.fetch('REFLEX_MASTER_KEY', nil)
|
|
248
|
-
@reflex_auto_provision = true
|
|
249
|
-
@reflex_excluded_exceptions = []
|
|
250
|
-
@reflex_before_send = nil
|
|
251
|
-
@reflex_sample_rate = nil
|
|
252
|
-
@reflex_fingerprint = nil # Custom fingerprint callback
|
|
253
|
-
|
|
254
|
-
# Pulse settings
|
|
255
|
-
@pulse_enabled = true
|
|
256
|
-
@pulse_url = ENV['PULSE_URL'] || detect_product_url('pulse')
|
|
257
|
-
@pulse_api_key = ENV.fetch('PULSE_API_KEY', nil)
|
|
258
|
-
@pulse_master_key = ENV.fetch('PULSE_MASTER_KEY', nil)
|
|
259
|
-
@pulse_auto_provision = true
|
|
260
|
-
@pulse_buffer_size = 50
|
|
261
|
-
@pulse_flush_interval = 5
|
|
262
|
-
# Trace sampling. Explicit rate (0.0–1.0) wins; otherwise derived from the
|
|
263
|
-
# tier. Defaults to the "internal" tier so the Brainz fleet samples ~10%
|
|
264
|
-
# (error traces are always kept). Client-facing apps set
|
|
265
|
-
# BRAINZLAB_PULSE_TIER=client (or PULSE_SAMPLE_RATE) to keep everything.
|
|
266
|
-
@pulse_sample_rate = (v = ENV['PULSE_SAMPLE_RATE'] || ENV['BRAINZLAB_PULSE_SAMPLE_RATE']).nil? || v.to_s.strip.empty? ? nil : v.to_f
|
|
267
|
-
@pulse_sample_tier = (ENV['BRAINZLAB_PULSE_TIER'] || 'internal').to_s.strip.downcase
|
|
268
|
-
# Traces at/above this duration (ms) bypass sampling and are ALWAYS kept,
|
|
269
|
-
# so slow requests / N+1s are never sampled away (APM's whole purpose).
|
|
270
|
-
# Set to 0 to disable. Default 1000ms.
|
|
271
|
-
@pulse_always_keep_slow_ms = (ENV['BRAINZLAB_PULSE_ALWAYS_KEEP_SLOW_MS'] || 1000).to_i
|
|
272
|
-
@pulse_excluded_paths = %w[/health /ping /up /assets]
|
|
273
|
-
|
|
274
|
-
# Flux settings
|
|
275
|
-
@flux_enabled = true
|
|
276
|
-
@flux_url = ENV['FLUX_URL'] || 'https://flux.brainzlab.ai'
|
|
277
|
-
@flux_api_key = ENV.fetch('FLUX_API_KEY', nil)
|
|
278
|
-
@flux_ingest_key = ENV.fetch('FLUX_INGEST_KEY', nil)
|
|
279
|
-
@flux_master_key = ENV.fetch('FLUX_MASTER_KEY', nil)
|
|
280
|
-
@flux_auto_provision = true
|
|
281
|
-
@flux_buffer_size = 100
|
|
282
|
-
@flux_flush_interval = 5
|
|
283
|
-
|
|
284
|
-
# Signal settings
|
|
285
|
-
@signal_enabled = true
|
|
286
|
-
@signal_url = ENV['SIGNAL_URL'] || detect_product_url('signal')
|
|
287
|
-
@signal_api_key = ENV.fetch('SIGNAL_API_KEY', nil)
|
|
288
|
-
@signal_ingest_key = ENV.fetch('SIGNAL_INGEST_KEY', nil)
|
|
289
|
-
@signal_master_key = ENV.fetch('SIGNAL_MASTER_KEY', nil)
|
|
290
|
-
@signal_auto_provision = true
|
|
291
|
-
|
|
292
|
-
# Vault settings
|
|
293
|
-
@vault_enabled = true
|
|
294
|
-
@vault_url = ENV['VAULT_URL'] || 'https://vault.brainzlab.ai'
|
|
295
|
-
@vault_api_key = ENV.fetch('VAULT_API_KEY', nil)
|
|
296
|
-
@vault_master_key = ENV.fetch('VAULT_MASTER_KEY', nil)
|
|
297
|
-
@vault_auto_provision = true
|
|
298
|
-
@vault_cache_enabled = true
|
|
299
|
-
@vault_cache_ttl = 300 # 5 minutes
|
|
300
|
-
@vault_auto_load = ENV.fetch('VAULT_AUTO_LOAD', 'false') == 'true' # Auto-load secrets into ENV
|
|
301
|
-
@vault_load_provider_keys = true # Also load provider keys (OpenAI, etc.)
|
|
302
|
-
|
|
303
|
-
# Vision settings (AI browser automation)
|
|
304
|
-
@vision_enabled = true
|
|
305
|
-
@vision_url = ENV['VISION_URL'] || 'https://vision.brainzlab.ai'
|
|
306
|
-
@vision_api_key = ENV.fetch('VISION_API_KEY', nil)
|
|
307
|
-
@vision_ingest_key = ENV.fetch('VISION_INGEST_KEY', nil)
|
|
308
|
-
@vision_master_key = ENV.fetch('VISION_MASTER_KEY', nil)
|
|
309
|
-
@vision_auto_provision = true
|
|
310
|
-
@vision_default_model = ENV['VISION_DEFAULT_MODEL'] || 'claude-sonnet-4'
|
|
311
|
-
@vision_default_browser_provider = ENV['VISION_DEFAULT_BROWSER_PROVIDER'] || 'local'
|
|
312
|
-
|
|
313
|
-
# Cortex settings (feature flags)
|
|
314
|
-
@cortex_enabled = true
|
|
315
|
-
@cortex_url = ENV['CORTEX_URL'] || 'https://cortex.brainzlab.ai'
|
|
316
|
-
@cortex_api_key = ENV.fetch('CORTEX_API_KEY', nil)
|
|
317
|
-
@cortex_master_key = ENV.fetch('CORTEX_MASTER_KEY', nil)
|
|
318
|
-
@cortex_auto_provision = true
|
|
319
|
-
@cortex_cache_enabled = true
|
|
320
|
-
@cortex_cache_ttl = 60 # 1 minute
|
|
321
|
-
@cortex_default_context = {}
|
|
322
|
-
|
|
323
|
-
# Beacon settings (uptime monitoring)
|
|
324
|
-
@beacon_enabled = true
|
|
325
|
-
@beacon_url = ENV['BEACON_URL'] || 'https://beacon.brainzlab.ai'
|
|
326
|
-
@beacon_api_key = ENV.fetch('BEACON_API_KEY', nil)
|
|
327
|
-
@beacon_master_key = ENV.fetch('BEACON_MASTER_KEY', nil)
|
|
328
|
-
@beacon_auto_provision = true
|
|
329
|
-
|
|
330
|
-
# Nerve settings (job monitoring)
|
|
331
|
-
@nerve_enabled = true
|
|
332
|
-
@nerve_url = ENV['NERVE_URL'] || 'https://nerve.brainzlab.ai'
|
|
333
|
-
@nerve_api_key = ENV.fetch('NERVE_API_KEY', nil)
|
|
334
|
-
@nerve_master_key = ENV.fetch('NERVE_MASTER_KEY', nil)
|
|
335
|
-
@nerve_auto_provision = true
|
|
336
|
-
|
|
337
|
-
# Dendrite settings (AI documentation)
|
|
338
|
-
@dendrite_enabled = true
|
|
339
|
-
@dendrite_url = ENV['DENDRITE_URL'] || 'https://dendrite.brainzlab.ai'
|
|
340
|
-
@dendrite_api_key = ENV.fetch('DENDRITE_API_KEY', nil)
|
|
341
|
-
@dendrite_master_key = ENV.fetch('DENDRITE_MASTER_KEY', nil)
|
|
342
|
-
@dendrite_auto_provision = true
|
|
343
|
-
|
|
344
|
-
# Sentinel settings (host monitoring)
|
|
345
|
-
@sentinel_enabled = true
|
|
346
|
-
@sentinel_url = ENV['SENTINEL_URL'] || 'https://sentinel.brainzlab.ai'
|
|
347
|
-
@sentinel_api_key = ENV.fetch('SENTINEL_API_KEY', nil)
|
|
348
|
-
@sentinel_agent_key = ENV.fetch('SENTINEL_AGENT_KEY', nil)
|
|
349
|
-
@sentinel_master_key = ENV.fetch('SENTINEL_MASTER_KEY', nil)
|
|
350
|
-
@sentinel_auto_provision = true
|
|
351
|
-
|
|
352
|
-
# Synapse settings (AI development orchestration)
|
|
353
|
-
@synapse_enabled = true
|
|
354
|
-
@synapse_url = ENV['SYNAPSE_URL'] || 'https://synapse.brainzlab.ai'
|
|
355
|
-
@synapse_api_key = ENV.fetch('SYNAPSE_API_KEY', nil)
|
|
356
|
-
@synapse_master_key = ENV.fetch('SYNAPSE_MASTER_KEY', nil)
|
|
357
|
-
@synapse_auto_provision = true
|
|
358
|
-
|
|
359
|
-
# Filtering
|
|
360
|
-
@scrub_fields = %i[password password_confirmation token api_key secret]
|
|
361
|
-
|
|
362
|
-
# Internal logger for debugging SDK issues
|
|
363
|
-
@logger = nil
|
|
364
|
-
|
|
365
|
-
# Debug callbacks
|
|
366
|
-
# Called when an SDK error occurs (lambda/proc receiving error object and context hash)
|
|
367
|
-
@on_error = nil
|
|
368
|
-
# Called before each API request (lambda/proc receiving service, method, path, and payload)
|
|
369
|
-
@on_send = nil
|
|
370
|
-
|
|
371
|
-
# Instrumentation
|
|
372
|
-
@instrument_http = true # Enable HTTP client instrumentation (Net::HTTP, Faraday, HTTParty)
|
|
373
|
-
@instrument_active_record = true # AR breadcrumbs for Reflex
|
|
374
|
-
@instrument_redis = true # Redis command instrumentation
|
|
375
|
-
@instrument_sidekiq = true # Sidekiq job instrumentation
|
|
376
|
-
@instrument_graphql = true # GraphQL query instrumentation
|
|
377
|
-
@instrument_mongodb = true # MongoDB/Mongoid instrumentation
|
|
378
|
-
@instrument_elasticsearch = true # Elasticsearch instrumentation
|
|
379
|
-
@instrument_action_controller = true # ActionController instrumentation (requests, redirects, filters)
|
|
380
|
-
@instrument_action_view = true # ActionView instrumentation (templates, partials, collections)
|
|
381
|
-
@instrument_action_mailer = true # ActionMailer instrumentation
|
|
382
|
-
@instrument_active_job = true # ActiveJob instrumentation (enqueue, perform, retry, discard)
|
|
383
|
-
@instrument_active_support_cache = true # ActiveSupport::Cache instrumentation (read, write, fetch)
|
|
384
|
-
@instrument_delayed_job = true # Delayed::Job instrumentation
|
|
385
|
-
@instrument_grape = true # Grape API instrumentation
|
|
386
|
-
@instrument_solid_queue = true # Solid Queue job instrumentation
|
|
387
|
-
@instrument_good_job = true # GoodJob instrumentation
|
|
388
|
-
@instrument_resque = true # Resque instrumentation
|
|
389
|
-
@instrument_excon = true # Excon HTTP client instrumentation
|
|
390
|
-
@instrument_typhoeus = true # Typhoeus HTTP client instrumentation
|
|
391
|
-
@instrument_dalli = true # Dalli/Memcached instrumentation
|
|
392
|
-
@instrument_aws = true # AWS SDK instrumentation
|
|
393
|
-
@instrument_stripe = true # Stripe API instrumentation
|
|
394
|
-
@instrument_active_storage = true # ActiveStorage instrumentation (uploads, downloads, transforms)
|
|
395
|
-
@instrument_action_cable = true # ActionCable WebSocket instrumentation
|
|
396
|
-
@instrument_action_dispatch = true # ActionDispatch instrumentation (middleware, redirects, requests)
|
|
397
|
-
@instrument_rails_deprecation = true # Rails deprecation warnings tracking
|
|
398
|
-
@instrument_action_mailbox = true # ActionMailbox inbound email processing instrumentation
|
|
399
|
-
@instrument_railties = true # Railties config initializer loading instrumentation
|
|
400
|
-
@http_ignore_hosts = %w[localhost 127.0.0.1]
|
|
401
|
-
@redis_ignore_commands = %w[ping info] # Commands to skip tracking
|
|
402
|
-
|
|
403
|
-
# ActiveRecord slow-query / N+1 detection — all tunable so a single chatty
|
|
404
|
-
# default can't flood Recall. Slow-query duration is APM data (Pulse already
|
|
405
|
-
# records it), so it defaults to a quiet level (:debug) and a higher threshold.
|
|
406
|
-
@slow_query_threshold = (ENV['BRAINZLAB_SLOW_QUERY_THRESHOLD'] || 500).to_i # ms (was hardcoded 100)
|
|
407
|
-
|
|
408
|
-
# Query plan capture. Off by default: it issues an extra (read-only)
|
|
409
|
-
# EXPLAIN against the app's own database, so an app opts in deliberately.
|
|
410
|
-
# Threshold defaults to the slow query threshold — a fast query has no
|
|
411
|
-
# plan worth looking at.
|
|
412
|
-
@pulse_explain_enabled = ENV['BRAINZLAB_PULSE_EXPLAIN_ENABLED'] == 'true'
|
|
413
|
-
@pulse_explain_threshold = (ENV['BRAINZLAB_PULSE_EXPLAIN_THRESHOLD'] || @slow_query_threshold).to_i
|
|
414
|
-
@pulse_explain_timeout = (ENV['BRAINZLAB_PULSE_EXPLAIN_TIMEOUT'] || 2).to_i
|
|
415
|
-
@very_slow_query_threshold = (ENV['BRAINZLAB_VERY_SLOW_QUERY_THRESHOLD'] || 2000).to_i # ms (was hardcoded 1000)
|
|
416
|
-
@slow_query_log_level = (ENV['BRAINZLAB_SLOW_QUERY_LOG_LEVEL'] || 'debug').to_sym # was :warn → floods
|
|
417
|
-
@very_slow_query_log_level = (ENV['BRAINZLAB_VERY_SLOW_QUERY_LOG_LEVEL'] || 'warn').to_sym
|
|
418
|
-
@n_plus_one_threshold = (ENV['BRAINZLAB_N_PLUS_ONE_THRESHOLD'] || 10).to_i # was hardcoded 5
|
|
419
|
-
@n_plus_one_log_level = (ENV['BRAINZLAB_N_PLUS_ONE_LOG_LEVEL'] || 'debug').to_sym # was :warning
|
|
420
|
-
|
|
421
|
-
# Per-instrumentation slow / very-slow thresholds (ms) — all env-tunable so a
|
|
422
|
-
# single low default can't flood Recall or wrongly escalate normal latency to
|
|
423
|
-
# :error. Defaults preserve prior behaviour EXCEPT cache, which is raised off
|
|
424
|
-
# DB-backed Solid Cache's normal write latency (~50ms paid a DB round-trip and
|
|
425
|
-
# tripped the old VERY_SLOW=50 → thousands of false :error logs/hour).
|
|
426
|
-
@slow_request_threshold = (ENV['BRAINZLAB_SLOW_REQUEST_THRESHOLD'] || 500).to_i
|
|
427
|
-
@very_slow_request_threshold = (ENV['BRAINZLAB_VERY_SLOW_REQUEST_THRESHOLD'] || 2000).to_i
|
|
428
|
-
@slow_cache_threshold = (ENV['BRAINZLAB_SLOW_CACHE_THRESHOLD'] || 100).to_i # was 10
|
|
429
|
-
@very_slow_cache_threshold = (ENV['BRAINZLAB_VERY_SLOW_CACHE_THRESHOLD'] || 500).to_i # was 50 → flooded :error
|
|
430
|
-
@slow_render_threshold = (ENV['BRAINZLAB_SLOW_RENDER_THRESHOLD'] || 50).to_i
|
|
431
|
-
@very_slow_render_threshold = (ENV['BRAINZLAB_VERY_SLOW_RENDER_THRESHOLD'] || 200).to_i
|
|
432
|
-
@slow_storage_threshold = (ENV['BRAINZLAB_SLOW_STORAGE_THRESHOLD'] || 500).to_i
|
|
433
|
-
@very_slow_storage_threshold = (ENV['BRAINZLAB_VERY_SLOW_STORAGE_THRESHOLD'] || 2000).to_i
|
|
434
|
-
@slow_cable_threshold = (ENV['BRAINZLAB_SLOW_CABLE_THRESHOLD'] || 100).to_i
|
|
435
|
-
@very_slow_cable_threshold = (ENV['BRAINZLAB_VERY_SLOW_CABLE_THRESHOLD'] || 500).to_i
|
|
436
|
-
@slow_initializer_threshold = (ENV['BRAINZLAB_SLOW_INITIALIZER_THRESHOLD'] || 100).to_i
|
|
437
|
-
@very_slow_initializer_threshold = (ENV['BRAINZLAB_VERY_SLOW_INITIALIZER_THRESHOLD'] || 500).to_i
|
|
438
|
-
@slow_middleware_threshold = (ENV['BRAINZLAB_SLOW_MIDDLEWARE_THRESHOLD'] || 50).to_i
|
|
439
|
-
@very_slow_middleware_threshold = (ENV['BRAINZLAB_VERY_SLOW_MIDDLEWARE_THRESHOLD'] || 200).to_i
|
|
440
|
-
@slow_mailbox_threshold = (ENV['BRAINZLAB_SLOW_MAILBOX_THRESHOLD'] || 1000).to_i
|
|
441
|
-
@very_slow_mailbox_threshold = (ENV['BRAINZLAB_VERY_SLOW_MAILBOX_THRESHOLD'] || 5000).to_i
|
|
442
|
-
@slow_job_threshold = (ENV['BRAINZLAB_SLOW_JOB_THRESHOLD'] || 5000).to_i
|
|
443
|
-
@very_slow_job_threshold = (ENV['BRAINZLAB_VERY_SLOW_JOB_THRESHOLD'] || 30_000).to_i
|
|
444
|
-
|
|
445
|
-
# Log formatter settings
|
|
446
|
-
@log_formatter_enabled = true
|
|
447
|
-
@log_formatter_colors = nil # auto-detect TTY
|
|
448
|
-
@log_formatter_hide_assets = false
|
|
449
|
-
@log_formatter_compact_assets = true
|
|
450
|
-
@log_formatter_show_params = true
|
|
451
|
-
|
|
452
|
-
# DevTools settings (development error page and debug panel)
|
|
453
|
-
@devtools_enabled = true
|
|
454
|
-
@devtools_error_page_enabled = true
|
|
455
|
-
@devtools_debug_panel_enabled = true
|
|
456
|
-
@devtools_allowed_environments = %w[development test]
|
|
457
|
-
@devtools_allowed_ips = ['127.0.0.1', '::1', '172.16.0.0/12', '192.168.0.0/16', '10.0.0.0/8']
|
|
458
|
-
@devtools_asset_path = '/__brainzlab__'
|
|
459
|
-
@devtools_panel_position = 'bottom-right'
|
|
460
|
-
@devtools_expand_by_default = false
|
|
461
|
-
|
|
462
|
-
# Rails instrumentation delegation
|
|
463
|
-
# When true, brainzlab-rails gem handles Rails-specific instrumentation
|
|
464
|
-
# SDK will only install non-Rails instrumentation (HTTP clients, Redis, etc.)
|
|
465
|
-
@rails_instrumentation_handled_externally = false
|
|
202
|
+
init_core_defaults
|
|
203
|
+
init_observability_defaults
|
|
204
|
+
init_platform_defaults
|
|
205
|
+
init_runtime_defaults
|
|
206
|
+
init_instrumentation_defaults
|
|
207
|
+
init_threshold_defaults
|
|
208
|
+
init_presentation_defaults
|
|
466
209
|
end
|
|
467
210
|
|
|
468
211
|
def recall_min_level=(level)
|
|
@@ -542,9 +285,7 @@ module BrainzLab
|
|
|
542
285
|
value = public_send(setting)
|
|
543
286
|
next if value.nil? # nil means "fall back to the tier default"
|
|
544
287
|
|
|
545
|
-
unless value.is_a?(Numeric) && value.between?(0, 1)
|
|
546
|
-
problems << "#{setting} must be a number between 0 and 1 (got #{value.inspect})"
|
|
547
|
-
end
|
|
288
|
+
problems << "#{setting} must be a number between 0 and 1 (got #{value.inspect})" unless value.is_a?(Numeric) && value.between?(0, 1)
|
|
548
289
|
end
|
|
549
290
|
|
|
550
291
|
POSITIVE_INTEGER_SETTINGS.each do |setting|
|
|
@@ -554,9 +295,7 @@ module BrainzLab
|
|
|
554
295
|
|
|
555
296
|
NON_NEGATIVE_NUMBER_SETTINGS.each do |setting|
|
|
556
297
|
value = public_send(setting)
|
|
557
|
-
unless value.is_a?(Numeric) && !value.negative?
|
|
558
|
-
problems << "#{setting} must be a non-negative number (got #{value.inspect})"
|
|
559
|
-
end
|
|
298
|
+
problems << "#{setting} must be a non-negative number (got #{value.inspect})" unless value.is_a?(Numeric) && !value.negative?
|
|
560
299
|
end
|
|
561
300
|
|
|
562
301
|
return self if problems.empty?
|
|
@@ -598,7 +337,7 @@ module BrainzLab
|
|
|
598
337
|
PULSE_TIER_SAMPLE_RATES = {
|
|
599
338
|
'internal' => 0.1,
|
|
600
339
|
'standard' => 0.5,
|
|
601
|
-
'client'
|
|
340
|
+
'client' => 1.0,
|
|
602
341
|
'critical' => 1.0
|
|
603
342
|
}.freeze
|
|
604
343
|
|
|
@@ -714,7 +453,11 @@ module BrainzLab
|
|
|
714
453
|
@synapse_url
|
|
715
454
|
].compact
|
|
716
455
|
|
|
717
|
-
urls.filter_map
|
|
456
|
+
urls.filter_map do |url|
|
|
457
|
+
URI.parse(url).host
|
|
458
|
+
rescue StandardError
|
|
459
|
+
nil
|
|
460
|
+
end.uniq
|
|
718
461
|
end
|
|
719
462
|
end
|
|
720
463
|
|
|
@@ -786,6 +529,292 @@ module BrainzLab
|
|
|
786
529
|
|
|
787
530
|
private
|
|
788
531
|
|
|
532
|
+
# Core identity: enablement, auth, environment, git context, SDK mode.
|
|
533
|
+
def init_core_defaults
|
|
534
|
+
# SDK enabled flag — set BRAINZLAB_SDK_ENABLED=false to completely disable
|
|
535
|
+
@enabled = ENV.fetch('BRAINZLAB_SDK_ENABLED', 'true') != 'false'
|
|
536
|
+
|
|
537
|
+
# Authentication
|
|
538
|
+
@secret_key = ENV.fetch('BRAINZLAB_SECRET_KEY', nil)
|
|
539
|
+
|
|
540
|
+
# Environment
|
|
541
|
+
@environment = ENV['BRAINZLAB_ENVIRONMENT'] || detect_environment
|
|
542
|
+
@service = ENV.fetch('BRAINZLAB_SERVICE', nil)
|
|
543
|
+
@host = ENV['BRAINZLAB_HOST'] || detect_host
|
|
544
|
+
|
|
545
|
+
# App name for auto-provisioning
|
|
546
|
+
@app_name = ENV.fetch('BRAINZLAB_APP_NAME', nil)
|
|
547
|
+
|
|
548
|
+
# Git context
|
|
549
|
+
@commit = ENV['GIT_COMMIT'] || ENV['COMMIT_SHA'] || detect_git_commit
|
|
550
|
+
@branch = ENV['GIT_BRANCH'] || ENV['BRANCH_NAME'] || detect_git_branch
|
|
551
|
+
|
|
552
|
+
# Debug mode - enables verbose logging
|
|
553
|
+
@debug = ENV['BRAINZLAB_DEBUG'] == 'true'
|
|
554
|
+
|
|
555
|
+
# SDK mode - :production (default) or :development (offline, local storage)
|
|
556
|
+
@mode = ENV['BRAINZLAB_MODE']&.to_sym || :production
|
|
557
|
+
|
|
558
|
+
# Development mode settings
|
|
559
|
+
@development_db_path = ENV['BRAINZLAB_DEV_DB_PATH'] || 'tmp/brainzlab.sqlite3'
|
|
560
|
+
@development_log_output = $stdout
|
|
561
|
+
|
|
562
|
+
# Disable self-tracking - prevents services from tracking to themselves
|
|
563
|
+
# e.g., Recall won't log to itself, Reflex won't track errors to itself
|
|
564
|
+
@disable_self_tracking = ENV.fetch('BRAINZLAB_DISABLE_SELF_TRACKING', 'true') == 'true'
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
# The five observability products: Recall, Reflex, Pulse, Flux, Signal.
|
|
568
|
+
def init_observability_defaults
|
|
569
|
+
# Recall settings
|
|
570
|
+
@recall_enabled = true
|
|
571
|
+
@recall_url = ENV['RECALL_URL'] || detect_product_url('recall')
|
|
572
|
+
@recall_min_level = :debug
|
|
573
|
+
@recall_buffer_size = 50
|
|
574
|
+
@recall_flush_interval = 5
|
|
575
|
+
@recall_master_key = ENV.fetch('RECALL_MASTER_KEY', nil)
|
|
576
|
+
@recall_auto_provision = true
|
|
577
|
+
|
|
578
|
+
# Reflex settings
|
|
579
|
+
@reflex_enabled = true
|
|
580
|
+
@reflex_url = ENV['REFLEX_URL'] || detect_product_url('reflex')
|
|
581
|
+
@reflex_api_key = ENV.fetch('REFLEX_API_KEY', nil)
|
|
582
|
+
@reflex_master_key = ENV.fetch('REFLEX_MASTER_KEY', nil)
|
|
583
|
+
@reflex_auto_provision = true
|
|
584
|
+
@reflex_excluded_exceptions = []
|
|
585
|
+
@reflex_before_send = nil
|
|
586
|
+
@reflex_sample_rate = nil
|
|
587
|
+
@reflex_fingerprint = nil # Custom fingerprint callback
|
|
588
|
+
|
|
589
|
+
# Pulse settings
|
|
590
|
+
@pulse_enabled = true
|
|
591
|
+
@pulse_url = ENV['PULSE_URL'] || detect_product_url('pulse')
|
|
592
|
+
@pulse_api_key = ENV.fetch('PULSE_API_KEY', nil)
|
|
593
|
+
@pulse_master_key = ENV.fetch('PULSE_MASTER_KEY', nil)
|
|
594
|
+
@pulse_auto_provision = true
|
|
595
|
+
@pulse_buffer_size = 50
|
|
596
|
+
@pulse_flush_interval = 5
|
|
597
|
+
# Trace sampling. Explicit rate (0.0–1.0) wins; otherwise derived from the
|
|
598
|
+
# tier. Defaults to the "internal" tier so the Brainz fleet samples ~10%
|
|
599
|
+
# (error traces are always kept). Client-facing apps set
|
|
600
|
+
# BRAINZLAB_PULSE_TIER=client (or PULSE_SAMPLE_RATE) to keep everything.
|
|
601
|
+
@pulse_sample_rate = (v = ENV['PULSE_SAMPLE_RATE'] || ENV.fetch('BRAINZLAB_PULSE_SAMPLE_RATE', nil)).nil? || v.to_s.strip.empty? ? nil : v.to_f
|
|
602
|
+
@pulse_sample_tier = (ENV['BRAINZLAB_PULSE_TIER'] || 'internal').to_s.strip.downcase
|
|
603
|
+
# Traces at/above this duration (ms) bypass sampling and are ALWAYS kept,
|
|
604
|
+
# so slow requests / N+1s are never sampled away (APM's whole purpose).
|
|
605
|
+
# Set to 0 to disable. Default 1000ms.
|
|
606
|
+
@pulse_always_keep_slow_ms = (ENV['BRAINZLAB_PULSE_ALWAYS_KEEP_SLOW_MS'] || 1000).to_i
|
|
607
|
+
@pulse_excluded_paths = %w[/health /ping /up /assets]
|
|
608
|
+
|
|
609
|
+
# Flux settings
|
|
610
|
+
@flux_enabled = true
|
|
611
|
+
@flux_url = ENV['FLUX_URL'] || 'https://flux.brainzlab.ai'
|
|
612
|
+
@flux_api_key = ENV.fetch('FLUX_API_KEY', nil)
|
|
613
|
+
@flux_ingest_key = ENV.fetch('FLUX_INGEST_KEY', nil)
|
|
614
|
+
@flux_master_key = ENV.fetch('FLUX_MASTER_KEY', nil)
|
|
615
|
+
@flux_auto_provision = true
|
|
616
|
+
@flux_buffer_size = 100
|
|
617
|
+
@flux_flush_interval = 5
|
|
618
|
+
|
|
619
|
+
# Signal settings
|
|
620
|
+
@signal_enabled = true
|
|
621
|
+
@signal_url = ENV['SIGNAL_URL'] || detect_product_url('signal')
|
|
622
|
+
@signal_api_key = ENV.fetch('SIGNAL_API_KEY', nil)
|
|
623
|
+
@signal_ingest_key = ENV.fetch('SIGNAL_INGEST_KEY', nil)
|
|
624
|
+
@signal_master_key = ENV.fetch('SIGNAL_MASTER_KEY', nil)
|
|
625
|
+
@signal_auto_provision = true
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
# The platform services: Vault, Vision, Cortex, Beacon, Nerve, Dendrite, Sentinel, Synapse.
|
|
629
|
+
def init_platform_defaults
|
|
630
|
+
# Vault settings
|
|
631
|
+
@vault_enabled = true
|
|
632
|
+
@vault_url = ENV['VAULT_URL'] || 'https://vault.brainzlab.ai'
|
|
633
|
+
@vault_api_key = ENV.fetch('VAULT_API_KEY', nil)
|
|
634
|
+
@vault_master_key = ENV.fetch('VAULT_MASTER_KEY', nil)
|
|
635
|
+
@vault_auto_provision = true
|
|
636
|
+
@vault_cache_enabled = true
|
|
637
|
+
@vault_cache_ttl = 300 # 5 minutes
|
|
638
|
+
@vault_auto_load = ENV.fetch('VAULT_AUTO_LOAD', 'false') == 'true' # Auto-load secrets into ENV
|
|
639
|
+
@vault_load_provider_keys = true # Also load provider keys (OpenAI, etc.)
|
|
640
|
+
|
|
641
|
+
# Vision settings (AI browser automation)
|
|
642
|
+
@vision_enabled = true
|
|
643
|
+
@vision_url = ENV['VISION_URL'] || 'https://vision.brainzlab.ai'
|
|
644
|
+
@vision_api_key = ENV.fetch('VISION_API_KEY', nil)
|
|
645
|
+
@vision_ingest_key = ENV.fetch('VISION_INGEST_KEY', nil)
|
|
646
|
+
@vision_master_key = ENV.fetch('VISION_MASTER_KEY', nil)
|
|
647
|
+
@vision_auto_provision = true
|
|
648
|
+
@vision_default_model = ENV['VISION_DEFAULT_MODEL'] || 'claude-sonnet-4'
|
|
649
|
+
@vision_default_browser_provider = ENV['VISION_DEFAULT_BROWSER_PROVIDER'] || 'local'
|
|
650
|
+
|
|
651
|
+
# Cortex settings (feature flags)
|
|
652
|
+
@cortex_enabled = true
|
|
653
|
+
@cortex_url = ENV['CORTEX_URL'] || 'https://cortex.brainzlab.ai'
|
|
654
|
+
@cortex_api_key = ENV.fetch('CORTEX_API_KEY', nil)
|
|
655
|
+
@cortex_master_key = ENV.fetch('CORTEX_MASTER_KEY', nil)
|
|
656
|
+
@cortex_auto_provision = true
|
|
657
|
+
@cortex_cache_enabled = true
|
|
658
|
+
@cortex_cache_ttl = 60 # 1 minute
|
|
659
|
+
@cortex_default_context = {}
|
|
660
|
+
|
|
661
|
+
# Beacon settings (uptime monitoring)
|
|
662
|
+
@beacon_enabled = true
|
|
663
|
+
@beacon_url = ENV['BEACON_URL'] || 'https://beacon.brainzlab.ai'
|
|
664
|
+
@beacon_api_key = ENV.fetch('BEACON_API_KEY', nil)
|
|
665
|
+
@beacon_master_key = ENV.fetch('BEACON_MASTER_KEY', nil)
|
|
666
|
+
@beacon_auto_provision = true
|
|
667
|
+
|
|
668
|
+
# Nerve settings (job monitoring)
|
|
669
|
+
@nerve_enabled = true
|
|
670
|
+
@nerve_url = ENV['NERVE_URL'] || 'https://nerve.brainzlab.ai'
|
|
671
|
+
@nerve_api_key = ENV.fetch('NERVE_API_KEY', nil)
|
|
672
|
+
@nerve_master_key = ENV.fetch('NERVE_MASTER_KEY', nil)
|
|
673
|
+
@nerve_auto_provision = true
|
|
674
|
+
|
|
675
|
+
# Dendrite settings (AI documentation)
|
|
676
|
+
@dendrite_enabled = true
|
|
677
|
+
@dendrite_url = ENV['DENDRITE_URL'] || 'https://dendrite.brainzlab.ai'
|
|
678
|
+
@dendrite_api_key = ENV.fetch('DENDRITE_API_KEY', nil)
|
|
679
|
+
@dendrite_master_key = ENV.fetch('DENDRITE_MASTER_KEY', nil)
|
|
680
|
+
@dendrite_auto_provision = true
|
|
681
|
+
|
|
682
|
+
# Sentinel settings (host monitoring)
|
|
683
|
+
@sentinel_enabled = true
|
|
684
|
+
@sentinel_url = ENV['SENTINEL_URL'] || 'https://sentinel.brainzlab.ai'
|
|
685
|
+
@sentinel_api_key = ENV.fetch('SENTINEL_API_KEY', nil)
|
|
686
|
+
@sentinel_agent_key = ENV.fetch('SENTINEL_AGENT_KEY', nil)
|
|
687
|
+
@sentinel_master_key = ENV.fetch('SENTINEL_MASTER_KEY', nil)
|
|
688
|
+
@sentinel_auto_provision = true
|
|
689
|
+
|
|
690
|
+
# Synapse settings (AI development orchestration)
|
|
691
|
+
@synapse_enabled = true
|
|
692
|
+
@synapse_url = ENV['SYNAPSE_URL'] || 'https://synapse.brainzlab.ai'
|
|
693
|
+
@synapse_api_key = ENV.fetch('SYNAPSE_API_KEY', nil)
|
|
694
|
+
@synapse_master_key = ENV.fetch('SYNAPSE_MASTER_KEY', nil)
|
|
695
|
+
@synapse_auto_provision = true
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
# Scrubbing, internal logger and debug callbacks.
|
|
699
|
+
def init_runtime_defaults
|
|
700
|
+
# Filtering
|
|
701
|
+
@scrub_fields = %i[password password_confirmation token api_key secret]
|
|
702
|
+
|
|
703
|
+
# Internal logger for debugging SDK issues
|
|
704
|
+
@logger = nil
|
|
705
|
+
|
|
706
|
+
# Debug callbacks
|
|
707
|
+
# Called when an SDK error occurs (lambda/proc receiving error object and context hash)
|
|
708
|
+
@on_error = nil
|
|
709
|
+
# Called before each API request (lambda/proc receiving service, method, path, and payload)
|
|
710
|
+
@on_send = nil
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
# Which integrations auto-instrument, and what they ignore.
|
|
714
|
+
def init_instrumentation_defaults
|
|
715
|
+
# Instrumentation
|
|
716
|
+
@instrument_http = true # Enable HTTP client instrumentation (Net::HTTP, Faraday, HTTParty)
|
|
717
|
+
@instrument_active_record = true # AR breadcrumbs for Reflex
|
|
718
|
+
@instrument_redis = true # Redis command instrumentation
|
|
719
|
+
@instrument_sidekiq = true # Sidekiq job instrumentation
|
|
720
|
+
@instrument_graphql = true # GraphQL query instrumentation
|
|
721
|
+
@instrument_mongodb = true # MongoDB/Mongoid instrumentation
|
|
722
|
+
@instrument_elasticsearch = true # Elasticsearch instrumentation
|
|
723
|
+
@instrument_action_controller = true # ActionController instrumentation (requests, redirects, filters)
|
|
724
|
+
@instrument_action_view = true # ActionView instrumentation (templates, partials, collections)
|
|
725
|
+
@instrument_action_mailer = true # ActionMailer instrumentation
|
|
726
|
+
@instrument_active_job = true # ActiveJob instrumentation (enqueue, perform, retry, discard)
|
|
727
|
+
@instrument_active_support_cache = true # ActiveSupport::Cache instrumentation (read, write, fetch)
|
|
728
|
+
@instrument_delayed_job = true # Delayed::Job instrumentation
|
|
729
|
+
@instrument_grape = true # Grape API instrumentation
|
|
730
|
+
@instrument_solid_queue = true # Solid Queue job instrumentation
|
|
731
|
+
@instrument_good_job = true # GoodJob instrumentation
|
|
732
|
+
@instrument_resque = true # Resque instrumentation
|
|
733
|
+
@instrument_excon = true # Excon HTTP client instrumentation
|
|
734
|
+
@instrument_typhoeus = true # Typhoeus HTTP client instrumentation
|
|
735
|
+
@instrument_dalli = true # Dalli/Memcached instrumentation
|
|
736
|
+
@instrument_aws = true # AWS SDK instrumentation
|
|
737
|
+
@instrument_stripe = true # Stripe API instrumentation
|
|
738
|
+
@instrument_active_storage = true # ActiveStorage instrumentation (uploads, downloads, transforms)
|
|
739
|
+
@instrument_action_cable = true # ActionCable WebSocket instrumentation
|
|
740
|
+
@instrument_action_dispatch = true # ActionDispatch instrumentation (middleware, redirects, requests)
|
|
741
|
+
@instrument_rails_deprecation = true # Rails deprecation warnings tracking
|
|
742
|
+
@instrument_action_mailbox = true # ActionMailbox inbound email processing instrumentation
|
|
743
|
+
@instrument_railties = true # Railties config initializer loading instrumentation
|
|
744
|
+
@http_ignore_hosts = %w[localhost 127.0.0.1]
|
|
745
|
+
@redis_ignore_commands = %w[ping info] # Commands to skip tracking
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
# Slow / very-slow thresholds and N+1 detection, all env-tunable.
|
|
749
|
+
def init_threshold_defaults
|
|
750
|
+
# ActiveRecord slow-query / N+1 detection — all tunable so a single chatty
|
|
751
|
+
# default can't flood Recall. Slow-query duration is APM data (Pulse already
|
|
752
|
+
# records it), so it defaults to a quiet level (:debug) and a higher threshold.
|
|
753
|
+
@slow_query_threshold = (ENV['BRAINZLAB_SLOW_QUERY_THRESHOLD'] || 500).to_i # ms (was hardcoded 100)
|
|
754
|
+
|
|
755
|
+
# Query plan capture. Off by default: it issues an extra (read-only)
|
|
756
|
+
# EXPLAIN against the app's own database, so an app opts in deliberately.
|
|
757
|
+
# Threshold defaults to the slow query threshold — a fast query has no
|
|
758
|
+
# plan worth looking at.
|
|
759
|
+
@pulse_explain_enabled = ENV['BRAINZLAB_PULSE_EXPLAIN_ENABLED'] == 'true'
|
|
760
|
+
@pulse_explain_threshold = (ENV['BRAINZLAB_PULSE_EXPLAIN_THRESHOLD'] || @slow_query_threshold).to_i
|
|
761
|
+
@pulse_explain_timeout = (ENV['BRAINZLAB_PULSE_EXPLAIN_TIMEOUT'] || 2).to_i
|
|
762
|
+
@very_slow_query_threshold = (ENV['BRAINZLAB_VERY_SLOW_QUERY_THRESHOLD'] || 2000).to_i # ms (was hardcoded 1000)
|
|
763
|
+
@slow_query_log_level = (ENV['BRAINZLAB_SLOW_QUERY_LOG_LEVEL'] || 'debug').to_sym # was :warn → floods
|
|
764
|
+
@very_slow_query_log_level = (ENV['BRAINZLAB_VERY_SLOW_QUERY_LOG_LEVEL'] || 'warn').to_sym
|
|
765
|
+
@n_plus_one_threshold = (ENV['BRAINZLAB_N_PLUS_ONE_THRESHOLD'] || 10).to_i # was hardcoded 5
|
|
766
|
+
@n_plus_one_log_level = (ENV['BRAINZLAB_N_PLUS_ONE_LOG_LEVEL'] || 'debug').to_sym # was :warning
|
|
767
|
+
|
|
768
|
+
# Per-instrumentation slow / very-slow thresholds (ms) — all env-tunable so a
|
|
769
|
+
# single low default can't flood Recall or wrongly escalate normal latency to
|
|
770
|
+
# :error. Defaults preserve prior behaviour EXCEPT cache, which is raised off
|
|
771
|
+
# DB-backed Solid Cache's normal write latency (~50ms paid a DB round-trip and
|
|
772
|
+
# tripped the old VERY_SLOW=50 → thousands of false :error logs/hour).
|
|
773
|
+
@slow_request_threshold = (ENV['BRAINZLAB_SLOW_REQUEST_THRESHOLD'] || 500).to_i
|
|
774
|
+
@very_slow_request_threshold = (ENV['BRAINZLAB_VERY_SLOW_REQUEST_THRESHOLD'] || 2000).to_i
|
|
775
|
+
@slow_cache_threshold = (ENV['BRAINZLAB_SLOW_CACHE_THRESHOLD'] || 100).to_i # was 10
|
|
776
|
+
@very_slow_cache_threshold = (ENV['BRAINZLAB_VERY_SLOW_CACHE_THRESHOLD'] || 500).to_i # was 50 → flooded :error
|
|
777
|
+
@slow_render_threshold = (ENV['BRAINZLAB_SLOW_RENDER_THRESHOLD'] || 50).to_i
|
|
778
|
+
@very_slow_render_threshold = (ENV['BRAINZLAB_VERY_SLOW_RENDER_THRESHOLD'] || 200).to_i
|
|
779
|
+
@slow_storage_threshold = (ENV['BRAINZLAB_SLOW_STORAGE_THRESHOLD'] || 500).to_i
|
|
780
|
+
@very_slow_storage_threshold = (ENV['BRAINZLAB_VERY_SLOW_STORAGE_THRESHOLD'] || 2000).to_i
|
|
781
|
+
@slow_cable_threshold = (ENV['BRAINZLAB_SLOW_CABLE_THRESHOLD'] || 100).to_i
|
|
782
|
+
@very_slow_cable_threshold = (ENV['BRAINZLAB_VERY_SLOW_CABLE_THRESHOLD'] || 500).to_i
|
|
783
|
+
@slow_initializer_threshold = (ENV['BRAINZLAB_SLOW_INITIALIZER_THRESHOLD'] || 100).to_i
|
|
784
|
+
@very_slow_initializer_threshold = (ENV['BRAINZLAB_VERY_SLOW_INITIALIZER_THRESHOLD'] || 500).to_i
|
|
785
|
+
@slow_middleware_threshold = (ENV['BRAINZLAB_SLOW_MIDDLEWARE_THRESHOLD'] || 50).to_i
|
|
786
|
+
@very_slow_middleware_threshold = (ENV['BRAINZLAB_VERY_SLOW_MIDDLEWARE_THRESHOLD'] || 200).to_i
|
|
787
|
+
@slow_mailbox_threshold = (ENV['BRAINZLAB_SLOW_MAILBOX_THRESHOLD'] || 1000).to_i
|
|
788
|
+
@very_slow_mailbox_threshold = (ENV['BRAINZLAB_VERY_SLOW_MAILBOX_THRESHOLD'] || 5000).to_i
|
|
789
|
+
@slow_job_threshold = (ENV['BRAINZLAB_SLOW_JOB_THRESHOLD'] || 5000).to_i
|
|
790
|
+
@very_slow_job_threshold = (ENV['BRAINZLAB_VERY_SLOW_JOB_THRESHOLD'] || 30_000).to_i
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
# Log formatter, DevTools and Rails delegation.
|
|
794
|
+
def init_presentation_defaults
|
|
795
|
+
# Log formatter settings
|
|
796
|
+
@log_formatter_enabled = true
|
|
797
|
+
@log_formatter_colors = nil # auto-detect TTY
|
|
798
|
+
@log_formatter_hide_assets = false
|
|
799
|
+
@log_formatter_compact_assets = true
|
|
800
|
+
@log_formatter_show_params = true
|
|
801
|
+
|
|
802
|
+
# DevTools settings (development error page and debug panel)
|
|
803
|
+
@devtools_enabled = true
|
|
804
|
+
@devtools_error_page_enabled = true
|
|
805
|
+
@devtools_debug_panel_enabled = true
|
|
806
|
+
@devtools_allowed_environments = %w[development test]
|
|
807
|
+
@devtools_allowed_ips = ['127.0.0.1', '::1', '172.16.0.0/12', '192.168.0.0/16', '10.0.0.0/8']
|
|
808
|
+
@devtools_asset_path = '/__brainzlab__'
|
|
809
|
+
@devtools_panel_position = 'bottom-right'
|
|
810
|
+
@devtools_expand_by_default = false
|
|
811
|
+
|
|
812
|
+
# Rails instrumentation delegation
|
|
813
|
+
# When true, brainzlab-rails gem handles Rails-specific instrumentation
|
|
814
|
+
# SDK will only install non-Rails instrumentation (HTTP clients, Redis, etc.)
|
|
815
|
+
@rails_instrumentation_handled_externally = false
|
|
816
|
+
end
|
|
817
|
+
|
|
789
818
|
def positive_number?(value)
|
|
790
819
|
value.is_a?(Numeric) && value.positive?
|
|
791
820
|
end
|