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.
Files changed (94) 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 +92 -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_mailer.rb +14 -13
  28. data/lib/brainzlab/instrumentation/active_record.rb +13 -15
  29. data/lib/brainzlab/instrumentation/aws.rb +43 -39
  30. data/lib/brainzlab/instrumentation/dalli.rb +20 -20
  31. data/lib/brainzlab/instrumentation/delayed_job.rb +27 -29
  32. data/lib/brainzlab/instrumentation/elasticsearch.rb +23 -24
  33. data/lib/brainzlab/instrumentation/excon.rb +27 -27
  34. data/lib/brainzlab/instrumentation/faraday.rb +3 -4
  35. data/lib/brainzlab/instrumentation/good_job.rb +28 -28
  36. data/lib/brainzlab/instrumentation/grape.rb +24 -24
  37. data/lib/brainzlab/instrumentation/graphql.rb +24 -23
  38. data/lib/brainzlab/instrumentation/httparty.rb +13 -14
  39. data/lib/brainzlab/instrumentation/mongodb.rb +7 -7
  40. data/lib/brainzlab/instrumentation/net_http.rb +6 -6
  41. data/lib/brainzlab/instrumentation/redis.rb +14 -21
  42. data/lib/brainzlab/instrumentation/resque.rb +23 -24
  43. data/lib/brainzlab/instrumentation/sidekiq.rb +29 -28
  44. data/lib/brainzlab/instrumentation/solid_queue.rb +37 -41
  45. data/lib/brainzlab/instrumentation/stripe.rb +36 -37
  46. data/lib/brainzlab/instrumentation/typhoeus.rb +19 -17
  47. data/lib/brainzlab/instrumentation.rb +20 -20
  48. data/lib/brainzlab/nerve/client.rb +38 -40
  49. data/lib/brainzlab/nerve/provisioner.rb +1 -1
  50. data/lib/brainzlab/nerve.rb +6 -6
  51. data/lib/brainzlab/pulse/client.rb +15 -11
  52. data/lib/brainzlab/pulse/instrumentation.rb +61 -57
  53. data/lib/brainzlab/pulse/propagation.rb +28 -28
  54. data/lib/brainzlab/pulse/provisioner.rb +12 -12
  55. data/lib/brainzlab/pulse/tracer.rb +3 -3
  56. data/lib/brainzlab/pulse.rb +13 -13
  57. data/lib/brainzlab/rails/log_formatter.rb +127 -121
  58. data/lib/brainzlab/rails/log_subscriber.rb +70 -76
  59. data/lib/brainzlab/rails/railtie.rb +66 -89
  60. data/lib/brainzlab/recall/buffer.rb +1 -1
  61. data/lib/brainzlab/recall/client.rb +14 -10
  62. data/lib/brainzlab/recall/logger.rb +16 -18
  63. data/lib/brainzlab/recall/provisioner.rb +16 -16
  64. data/lib/brainzlab/recall.rb +11 -13
  65. data/lib/brainzlab/reflex/breadcrumbs.rb +2 -2
  66. data/lib/brainzlab/reflex/client.rb +14 -10
  67. data/lib/brainzlab/reflex/provisioner.rb +12 -12
  68. data/lib/brainzlab/reflex.rb +29 -29
  69. data/lib/brainzlab/sentinel/client.rb +40 -42
  70. data/lib/brainzlab/sentinel/provisioner.rb +1 -1
  71. data/lib/brainzlab/sentinel.rb +5 -5
  72. data/lib/brainzlab/signal/client.rb +12 -14
  73. data/lib/brainzlab/signal/provisioner.rb +12 -12
  74. data/lib/brainzlab/signal.rb +7 -7
  75. data/lib/brainzlab/synapse/client.rb +42 -44
  76. data/lib/brainzlab/synapse/provisioner.rb +1 -1
  77. data/lib/brainzlab/synapse.rb +6 -6
  78. data/lib/brainzlab/utilities/circuit_breaker.rb +37 -41
  79. data/lib/brainzlab/utilities/health_check.rb +53 -55
  80. data/lib/brainzlab/utilities/log_formatter.rb +38 -40
  81. data/lib/brainzlab/utilities/rate_limiter.rb +5 -5
  82. data/lib/brainzlab/utilities.rb +4 -4
  83. data/lib/brainzlab/vault/cache.rb +1 -1
  84. data/lib/brainzlab/vault/client.rb +39 -41
  85. data/lib/brainzlab/vault/provisioner.rb +1 -1
  86. data/lib/brainzlab/vault.rb +19 -25
  87. data/lib/brainzlab/version.rb +1 -1
  88. data/lib/brainzlab/vision/client.rb +20 -20
  89. data/lib/brainzlab/vision/provisioner.rb +21 -21
  90. data/lib/brainzlab/vision.rb +17 -19
  91. data/lib/brainzlab-sdk.rb +1 -1
  92. data/lib/brainzlab.rb +22 -24
  93. data/lib/generators/brainzlab/install/install_generator.rb +29 -27
  94. metadata +1 -1
@@ -5,7 +5,8 @@ module BrainzLab
5
5
  class LogFormatter
6
6
  ASSET_PATHS = %w[/assets /packs /vite /images /fonts /stylesheets /javascripts].freeze
7
7
  ASSET_EXTENSIONS = %w[.css .js .map .png .jpg .jpeg .gif .svg .ico .woff .woff2 .ttf .eot].freeze
8
- SIMPLE_PATHS = %w[/up /health /healthz /ready /readiness /live /liveness /ping /favicon.ico /apple-touch-icon.png /apple-touch-icon-precomposed.png /robots.txt /sitemap.xml].freeze
8
+ SIMPLE_PATHS = %w[/up /health /healthz /ready /readiness /live /liveness /ping /favicon.ico /apple-touch-icon.png
9
+ /apple-touch-icon-precomposed.png /robots.txt /sitemap.xml].freeze
9
10
  IGNORED_PATHS = %w[/apple-touch-icon.png /apple-touch-icon-precomposed.png /favicon.ico].freeze
10
11
 
11
12
  # Thresholds for highlighting
@@ -29,12 +30,12 @@ module BrainzLab
29
30
 
30
31
  # Box drawing characters
31
32
  BOX = {
32
- top_left: "",
33
- top_right: "",
34
- bottom_left: "",
35
- bottom_right: "",
36
- vertical: "",
37
- horizontal: ""
33
+ top_left: '',
34
+ top_right: '',
35
+ bottom_left: '',
36
+ bottom_right: '',
37
+ vertical: '',
38
+ horizontal: ''
38
39
  }.freeze
39
40
 
40
41
  attr_reader :config
@@ -54,7 +55,7 @@ module BrainzLab
54
55
  show_params: true,
55
56
  show_sql_count: true,
56
57
  show_sql_details: true,
57
- show_sql_queries: true, # Show actual SQL queries
58
+ show_sql_queries: true, # Show actual SQL queries
58
59
  show_views: true,
59
60
  slow_query_threshold: SLOW_QUERY_MS,
60
61
  n_plus_one_threshold: N_PLUS_ONE_THRESHOLD,
@@ -64,16 +65,16 @@ module BrainzLab
64
65
 
65
66
  def detect_terminal_width
66
67
  # Try to get terminal width, fallback to 120
67
- width = ENV["COLUMNS"]&.to_i
68
- return width if width && width > 0
68
+ width = ENV['COLUMNS']&.to_i
69
+ return width if width&.positive?
69
70
 
70
71
  if $stdout.tty? && IO.respond_to?(:console) && IO.console
71
72
  _rows, cols = IO.console.winsize
72
- return cols if cols > 0
73
+ return cols if cols.positive?
73
74
  end
74
75
 
75
76
  120 # Default to 120 for wider output
76
- rescue
77
+ rescue StandardError
77
78
  120
78
79
  end
79
80
 
@@ -231,12 +232,12 @@ module BrainzLab
231
232
  colorize(time, :gray),
232
233
  method,
233
234
  colorize(path, :white),
234
- colorize("", :gray),
235
+ colorize('', :gray),
235
236
  status,
236
237
  duration
237
238
  ]
238
239
 
239
- parts.join(" ") + "\n"
240
+ "#{parts.join(' ')}\n"
240
241
  end
241
242
 
242
243
  # Format full block output
@@ -250,40 +251,36 @@ module BrainzLab
250
251
  lines << header
251
252
 
252
253
  # Status line
253
- status_text = data[:status] ? "#{data[:status]} #{status_phrase(data[:status])}" : "---"
254
- lines << build_line("status", format_status_value(data[:status], status_text))
254
+ status_text = data[:status] ? "#{data[:status]} #{status_phrase(data[:status])}" : '---'
255
+ lines << build_line('status', format_status_value(data[:status], status_text))
255
256
 
256
257
  # Duration line
257
- if data[:duration]
258
- lines << build_line("duration", format_duration_full(data[:duration]))
259
- end
258
+ lines << build_line('duration', format_duration_full(data[:duration])) if data[:duration]
260
259
 
261
260
  # Database line with query analysis
262
261
  if data[:db_runtime] || data[:sql_queries].any?
263
262
  db_info = format_db_info(data)
264
- lines << build_line("db", db_info)
263
+ lines << build_line('db', db_info)
265
264
  end
266
265
 
267
266
  # Views line
268
- if data[:view_runtime]
269
- lines << build_line("views", "#{data[:view_runtime].round(1)}ms")
270
- end
267
+ lines << build_line('views', "#{data[:view_runtime].round(1)}ms") if data[:view_runtime]
271
268
 
272
269
  # Params section (if enabled and present) - TOML style
273
270
  if config[:show_params] && data[:params].present?
274
271
  params_str = format_params(data[:params])
275
272
  if params_str
276
- lines << build_line("", colorize("[params]", :gray))
273
+ lines << build_line('', colorize('[params]', :gray))
277
274
  lines << params_str
278
275
  end
279
276
  end
280
277
 
281
278
  # Error lines
282
279
  if data[:error]
283
- lines << build_line("error", colorize(data[:error], :red))
280
+ lines << build_line('error', colorize(data[:error], :red))
284
281
  if data[:error_message]
285
282
  msg = truncate(data[:error_message], width - 15)
286
- lines << build_line("message", colorize("\"#{msg}\"", :red))
283
+ lines << build_line('message', colorize("\"#{msg}\"", :red))
287
284
  end
288
285
  end
289
286
 
@@ -308,7 +305,7 @@ module BrainzLab
308
305
  # Footer line
309
306
  lines << build_footer(width)
310
307
 
311
- lines.join("\n") + "\n\n"
308
+ "#{lines.join("\n")}\n\n"
312
309
  end
313
310
 
314
311
  def analyze_sql_queries(queries)
@@ -325,21 +322,20 @@ module BrainzLab
325
322
 
326
323
  # This is a potential N+1
327
324
  sample = matching_queries.first
328
- source = sample[:source] || "unknown"
329
- name = sample[:name] || "Query"
325
+ source = sample[:source] || 'unknown'
326
+ name = sample[:name] || 'Query'
330
327
 
331
328
  # Extract table name from pattern
332
329
  table_match = pattern.match(/FROM "?(\w+)"?/i)
333
330
  table = table_match ? table_match[1] : name
334
331
 
335
- issues << build_line("", colorize("N+1", :red) + " " +
336
- colorize("#{table} × #{matching_queries.size}", :yellow) +
337
- colorize(" (#{source})", :gray))
332
+ issues << build_line('',
333
+ "#{colorize('N+1',
334
+ :red)} #{colorize("#{table} × #{matching_queries.size}",
335
+ :yellow)}#{colorize(" (#{source})", :gray)}")
338
336
 
339
337
  # Show the query SQL in TOML-like format
340
- if config[:show_sql_queries] && sample[:sql]
341
- issues << format_sql_toml(sample[:sql], sample[:duration])
342
- end
338
+ issues << format_sql_toml(sample[:sql], sample[:duration]) if config[:show_sql_queries] && sample[:sql]
343
339
  end
344
340
 
345
341
  # Find slow queries (not cached, not already reported as N+1)
@@ -350,18 +346,17 @@ module BrainzLab
350
346
  .first(3)
351
347
 
352
348
  slow_queries.each do |query|
353
- source = query[:source] || "unknown"
354
- name = query[:name] || "Query"
349
+ source = query[:source] || 'unknown'
350
+ name = query[:name] || 'Query'
355
351
  duration = query[:duration].round(1)
356
352
 
357
- issues << build_line("", colorize("Slow", :yellow) + " " +
358
- colorize("#{name} #{duration}ms", :white) +
359
- colorize(" (#{source})", :gray))
353
+ issues << build_line('',
354
+ "#{colorize('Slow',
355
+ :yellow)} #{colorize("#{name} #{duration}ms",
356
+ :white)}#{colorize(" (#{source})", :gray)}")
360
357
 
361
358
  # Show the query SQL in TOML-like format
362
- if config[:show_sql_queries] && query[:sql]
363
- issues << format_sql_toml(query[:sql], query[:duration])
364
- end
359
+ issues << format_sql_toml(query[:sql], query[:duration]) if config[:show_sql_queries] && query[:sql]
365
360
  end
366
361
 
367
362
  issues
@@ -370,7 +365,7 @@ module BrainzLab
370
365
  def format_sql_toml(sql, duration = nil)
371
366
  lines = []
372
367
  prefix = colorize("#{BOX[:vertical]} ", :cyan)
373
- indent = " "
368
+ indent = ' '
374
369
 
375
370
  # Parse SQL to extract key components
376
371
  parsed = parse_sql(sql)
@@ -379,16 +374,15 @@ module BrainzLab
379
374
  lines << "#{prefix}#{indent}#{colorize('[query]', :gray)}"
380
375
 
381
376
  if parsed[:operation]
382
- lines << "#{prefix}#{indent}#{colorize('operation', :gray)} = #{colorize("\"#{parsed[:operation]}\"", :green)}"
377
+ lines << "#{prefix}#{indent}#{colorize('operation',
378
+ :gray)} = #{colorize("\"#{parsed[:operation]}\"", :green)}"
383
379
  end
384
380
 
385
- if parsed[:table]
386
- lines << "#{prefix}#{indent}#{colorize('table', :gray)} = #{colorize("\"#{parsed[:table]}\"", :green)}"
387
- end
381
+ lines << "#{prefix}#{indent}#{colorize('table', :gray)} = #{colorize("\"#{parsed[:table]}\"", :green)}" if parsed[:table]
388
382
 
389
383
  if parsed[:columns].any?
390
- cols = parsed[:columns].first(5).map { |c| "\"#{c}\"" }.join(", ")
391
- cols += ", ..." if parsed[:columns].size > 5
384
+ cols = parsed[:columns].first(5).map { |c| "\"#{c}\"" }.join(', ')
385
+ cols += ', ...' if parsed[:columns].size > 5
392
386
  lines << "#{prefix}#{indent}#{colorize('columns', :gray)} = [#{colorize(cols, :cyan)}]"
393
387
  end
394
388
 
@@ -399,17 +393,11 @@ module BrainzLab
399
393
  end
400
394
  end
401
395
 
402
- if parsed[:order]
403
- lines << "#{prefix}#{indent}#{colorize('order', :gray)} = #{colorize("\"#{parsed[:order]}\"", :green)}"
404
- end
396
+ lines << "#{prefix}#{indent}#{colorize('order', :gray)} = #{colorize("\"#{parsed[:order]}\"", :green)}" if parsed[:order]
405
397
 
406
- if parsed[:limit]
407
- lines << "#{prefix}#{indent}#{colorize('limit', :gray)} = #{colorize(parsed[:limit].to_s, :magenta)}"
408
- end
398
+ lines << "#{prefix}#{indent}#{colorize('limit', :gray)} = #{colorize(parsed[:limit].to_s, :magenta)}" if parsed[:limit]
409
399
 
410
- if duration
411
- lines << "#{prefix}#{indent}#{colorize('duration_ms', :gray)} = #{colorize(duration.round(2).to_s, :magenta)}"
412
- end
400
+ lines << "#{prefix}#{indent}#{colorize('duration_ms', :gray)} = #{colorize(duration.round(2).to_s, :magenta)}" if duration
413
401
 
414
402
  lines.join("\n")
415
403
  end
@@ -428,10 +416,10 @@ module BrainzLab
428
416
 
429
417
  # Detect operation
430
418
  result[:operation] = case sql
431
- when /^\s*SELECT/i then "SELECT"
432
- when /^\s*INSERT/i then "INSERT"
433
- when /^\s*UPDATE/i then "UPDATE"
434
- when /^\s*DELETE/i then "DELETE"
419
+ when /^\s*SELECT/i then 'SELECT'
420
+ when /^\s*INSERT/i then 'INSERT'
421
+ when /^\s*UPDATE/i then 'UPDATE'
422
+ when /^\s*DELETE/i then 'DELETE'
435
423
  else sql.split.first&.upcase
436
424
  end
437
425
 
@@ -447,9 +435,7 @@ module BrainzLab
447
435
  # Extract selected columns (for SELECT)
448
436
  if (match = sql.match(/SELECT\s+(.+?)\s+FROM/i))
449
437
  cols = match[1]
450
- if cols.strip != "*"
451
- result[:columns] = cols.split(",").map { |c| c.strip.gsub(/"/, "").split(".").last }
452
- end
438
+ result[:columns] = cols.split(',').map { |c| c.strip.gsub('"', '').split('.').last } if cols.strip != '*'
453
439
  end
454
440
 
455
441
  # Extract WHERE conditions
@@ -485,10 +471,10 @@ module BrainzLab
485
471
  partial_counts = partials.group_by { |p| p[:template] }
486
472
 
487
473
  templates.each do |template|
488
- duration = template[:duration] ? " (#{template[:duration].round(1)}ms)" : ""
489
- lines << build_line("", colorize("View", :cyan) + " " +
490
- colorize(template[:template], :white) +
491
- colorize(duration, :gray))
474
+ duration = template[:duration] ? " (#{template[:duration].round(1)}ms)" : ''
475
+ lines << build_line('',
476
+ "#{colorize('View',
477
+ :cyan)} #{colorize(template[:template], :white)}#{colorize(duration, :gray)}")
492
478
  end
493
479
 
494
480
  # Show partials that were rendered multiple times (potential issue)
@@ -496,9 +482,12 @@ module BrainzLab
496
482
  next if renders.size < 3 # Only show if rendered 3+ times
497
483
 
498
484
  total_duration = renders.sum { |r| r[:duration] || 0 }
499
- lines << build_line("", colorize("Partial", :yellow) + " " +
500
- colorize("#{name} × #{renders.size}", :white) +
501
- colorize(" (#{total_duration.round(1)}ms total)", :gray))
485
+ lines << build_line('',
486
+ "#{colorize('Partial',
487
+ :yellow)} #{colorize("#{name} × #{renders.size}",
488
+ :white)}#{colorize(
489
+ " (#{total_duration.round(1)}ms total)", :gray
490
+ )}")
502
491
  end
503
492
 
504
493
  lines
@@ -506,7 +495,7 @@ module BrainzLab
506
495
 
507
496
  def build_header(text, has_error, width)
508
497
  prefix = "#{BOX[:top_left]}#{BOX[:horizontal]} "
509
- suffix = has_error ? " #{BOX[:horizontal]} ERROR #{BOX[:horizontal]}" : " "
498
+ suffix = has_error ? " #{BOX[:horizontal]} ERROR #{BOX[:horizontal]}" : ' '
510
499
 
511
500
  available = width - prefix.length - suffix.length
512
501
  text = truncate(text, available)
@@ -542,25 +531,25 @@ module BrainzLab
542
531
  end
543
532
 
544
533
  def format_time(time)
545
- return "--:--:--" unless time
534
+ return '--:--:--' unless time
546
535
 
547
- time.strftime("%H:%M:%S")
536
+ time.strftime('%H:%M:%S')
548
537
  end
549
538
 
550
539
  def format_method(method)
551
540
  method = method.to_s.upcase
552
541
  color = case method
553
- when "GET" then :green
554
- when "POST" then :blue
555
- when "PUT", "PATCH" then :yellow
556
- when "DELETE" then :red
542
+ when 'GET' then :green
543
+ when 'POST' then :blue
544
+ when 'PUT', 'PATCH' then :yellow
545
+ when 'DELETE' then :red
557
546
  else :white
558
547
  end
559
548
  colorize(method.ljust(6), color)
560
549
  end
561
550
 
562
551
  def format_status(status)
563
- return colorize("---", :gray) unless status
552
+ return colorize('---', :gray) unless status
564
553
 
565
554
  color = case status
566
555
  when 200..299 then :green
@@ -584,10 +573,10 @@ module BrainzLab
584
573
  end
585
574
 
586
575
  def format_duration(ms)
587
- return colorize("--", :gray) unless ms
576
+ return colorize('--', :gray) unless ms
588
577
 
589
578
  formatted = if ms < 1
590
- "<1ms"
579
+ '<1ms'
591
580
  elsif ms < 1000
592
581
  "#{ms.round}ms"
593
582
  else
@@ -620,9 +609,7 @@ module BrainzLab
620
609
  def format_db_info(data)
621
610
  parts = []
622
611
 
623
- if data[:db_runtime]
624
- parts << "#{data[:db_runtime].round(1)}ms"
625
- end
612
+ parts << "#{data[:db_runtime].round(1)}ms" if data[:db_runtime]
626
613
 
627
614
  if config[:show_sql_count]
628
615
  queries = data[:sql_queries] || []
@@ -631,25 +618,21 @@ module BrainzLab
631
618
  non_cached = total - cached
632
619
 
633
620
  query_text = "#{non_cached} #{non_cached == 1 ? 'query' : 'queries'}"
634
- if cached.positive?
635
- query_text += ", #{cached} cached"
636
- end
621
+ query_text += ", #{cached} cached" if cached.positive?
637
622
  parts << "(#{query_text})"
638
623
  end
639
624
 
640
- parts.join(" ")
625
+ parts.join(' ')
641
626
  end
642
627
 
643
628
  def format_params(params)
644
629
  return nil if params.empty?
645
630
 
646
631
  # Filter out controller, action, and duplicate keys
647
- filtered = params.except("controller", "action", :controller, :action)
632
+ filtered = params.except('controller', 'action', :controller, :action)
648
633
 
649
634
  # Skip 'ingest' if 'logs' exists (they're the same data)
650
- if filtered.key?("logs") || filtered.key?(:logs)
651
- filtered = filtered.except("ingest", :ingest)
652
- end
635
+ filtered = filtered.except('ingest', :ingest) if filtered.key?('logs') || filtered.key?(:logs)
653
636
 
654
637
  return nil if filtered.empty?
655
638
 
@@ -658,23 +641,27 @@ module BrainzLab
658
641
  end
659
642
 
660
643
  def hash_like?(obj)
661
- obj.is_a?(Hash) || obj.respond_to?(:to_h) && obj.respond_to?(:each)
644
+ obj.is_a?(Hash) || (obj.respond_to?(:to_h) && obj.respond_to?(:each))
662
645
  end
663
646
 
664
- def format_params_toml(params, prefix = "", depth = 0)
647
+ def format_params_toml(params, prefix = '', depth = 0)
665
648
  lines = []
666
649
  line_prefix = colorize("#{BOX[:vertical]} ", :cyan)
667
- indent = " " + (" " * depth)
650
+ indent = " #{' ' * depth}"
668
651
 
669
652
  params.each do |key, value|
670
653
  full_key = prefix.empty? ? key.to_s : "#{prefix}.#{key}"
671
654
 
672
655
  case value
673
656
  when Hash, ActionController::Parameters
674
- value_hash = value.to_h rescue value
657
+ value_hash = begin
658
+ value.to_h
659
+ rescue StandardError
660
+ value
661
+ end
675
662
  if value_hash.keys.length <= 3 && value_hash.values.all? { |v| !hash_like?(v) && !v.is_a?(Array) }
676
663
  # Compact inline hash for simple cases
677
- inline = value_hash.map { |k, v| "#{k} = #{format_value(v)}" }.join(", ")
664
+ inline = value_hash.map { |k, v| "#{k} = #{format_value(v)}" }.join(', ')
678
665
  lines << "#{line_prefix}#{indent}#{colorize(full_key, :white)} = { #{inline} }"
679
666
  else
680
667
  # Nested section - expand fully
@@ -684,9 +671,14 @@ module BrainzLab
684
671
  # Recursively format nested hashes
685
672
  lines << format_hash_nested(v.to_h, "#{full_key}.#{k}", depth + 1)
686
673
  elsif v.is_a?(Array) && hash_like?(v.first)
687
- lines << "#{line_prefix}#{indent} #{colorize("[[#{full_key}.#{k}]]", :gray)} #{colorize("# #{v.length} items", :gray)}"
674
+ lines << "#{line_prefix}#{indent} #{colorize("[[#{full_key}.#{k}]]",
675
+ :gray)} #{colorize("# #{v.length} items", :gray)}"
688
676
  if v.first
689
- first_hash = v.first.to_h rescue v.first
677
+ first_hash = begin
678
+ v.first.to_h
679
+ rescue StandardError
680
+ v.first
681
+ end
690
682
  first_hash.each do |nested_k, nested_v|
691
683
  lines << "#{line_prefix}#{indent} #{colorize(nested_k.to_s, :white)} = #{format_value(nested_v)}"
692
684
  end
@@ -699,21 +691,31 @@ module BrainzLab
699
691
  when Array
700
692
  if value.length <= 5 && value.all? { |v| !hash_like?(v) && !v.is_a?(Array) }
701
693
  # Compact inline array
702
- arr = value.map { |v| format_value(v) }.join(", ")
694
+ arr = value.map { |v| format_value(v) }.join(', ')
703
695
  lines << "#{line_prefix}#{indent}#{colorize(full_key, :white)} = [#{arr}]"
704
696
  elsif hash_like?(value.first)
705
697
  # Array of hashes (like logs array) - show each item
706
- lines << "#{line_prefix}#{indent}#{colorize("[[#{full_key}]]", :gray)} #{colorize("# #{value.length} items", :gray)}"
698
+ lines << "#{line_prefix}#{indent}#{colorize("[[#{full_key}]]",
699
+ :gray)} #{colorize("# #{value.length} items", :gray)}"
707
700
  # Show first item fully expanded
708
701
  if value.first
709
- first_item = value.first.to_h rescue value.first
702
+ first_item = begin
703
+ value.first.to_h
704
+ rescue StandardError
705
+ value.first
706
+ end
710
707
  first_item.each do |k, v|
711
708
  if hash_like?(v)
712
709
  # Expand nested hash fully
713
- nested_hash = v.to_h rescue v
710
+ nested_hash = begin
711
+ v.to_h
712
+ rescue StandardError
713
+ v
714
+ end
714
715
  lines << "#{line_prefix}#{indent} #{colorize("[#{k}]", :gray)}"
715
716
  nested_hash.each do |nested_k, nested_v|
716
- lines << "#{line_prefix}#{indent} #{colorize(nested_k.to_s, :white)} = #{format_value(nested_v)}"
717
+ lines << "#{line_prefix}#{indent} #{colorize(nested_k.to_s,
718
+ :white)} = #{format_value(nested_v)}"
717
719
  end
718
720
  else
719
721
  lines << "#{line_prefix}#{indent} #{colorize(k.to_s, :white)} = #{format_value(v)}"
@@ -722,9 +724,11 @@ module BrainzLab
722
724
  end
723
725
  else
724
726
  # Large array of primitives
725
- arr = value.first(5).map { |v| format_value(v) }.join(", ")
726
- arr += ", ..." if value.length > 5
727
- lines << "#{line_prefix}#{indent}#{colorize(full_key, :white)} = [#{arr}] #{colorize("# #{value.length} items", :gray)}"
727
+ arr = value.first(5).map { |v| format_value(v) }.join(', ')
728
+ arr += ', ...' if value.length > 5
729
+ lines << "#{line_prefix}#{indent}#{colorize(full_key,
730
+ :white)} = [#{arr}] #{colorize("# #{value.length} items",
731
+ :gray)}"
728
732
  end
729
733
  else
730
734
  lines << "#{line_prefix}#{indent}#{colorize(full_key, :white)} = #{format_value(value)}"
@@ -737,15 +741,15 @@ module BrainzLab
737
741
  def format_hash_nested(hash, prefix, depth)
738
742
  lines = []
739
743
  line_prefix = colorize("#{BOX[:vertical]} ", :cyan)
740
- indent = " " + (" " * depth)
744
+ indent = " #{' ' * depth}"
741
745
 
742
746
  lines << "#{line_prefix}#{indent}#{colorize("[#{prefix}]", :gray)}"
743
747
  hash.each do |k, v|
744
- if v.is_a?(Hash)
745
- lines << format_hash_nested(v, "#{prefix}.#{k}", depth + 1)
746
- else
747
- lines << "#{line_prefix}#{indent} #{colorize(k.to_s, :white)} = #{format_value(v)}"
748
- end
748
+ lines << if v.is_a?(Hash)
749
+ format_hash_nested(v, "#{prefix}.#{k}", depth + 1)
750
+ else
751
+ "#{line_prefix}#{indent} #{colorize(k.to_s, :white)} = #{format_value(v)}"
752
+ end
749
753
  end
750
754
 
751
755
  lines.join("\n")
@@ -764,16 +768,18 @@ module BrainzLab
764
768
  when TrueClass, FalseClass
765
769
  colorize(value.to_s, :cyan)
766
770
  when NilClass
767
- colorize("null", :gray)
771
+ colorize('null', :gray)
768
772
  when Hash
769
- items = value.first(3).map { |k, v| "#{k} = #{format_value(v)}" }.join(", ")
770
- items += ", ..." if value.keys.length > 3
773
+ items = value.first(3).map { |k, v| "#{k} = #{format_value(v)}" }.join(', ')
774
+ items += ', ...' if value.keys.length > 3
771
775
  "{ #{items} }"
772
776
  when Array
773
777
  if value.length <= 3
774
- "[#{value.map { |v| format_value(v) }.join(", ")}]"
778
+ "[#{value.map { |v| format_value(v) }.join(', ')}]"
775
779
  else
776
- "[#{value.first(3).map { |v| format_value(v) }.join(", ")}, ...] #{colorize("# #{value.length} items", :gray)}"
780
+ "[#{value.first(3).map do |v|
781
+ format_value(v)
782
+ end.join(', ')}, ...] #{colorize("# #{value.length} items", :gray)}"
777
783
  end
778
784
  else
779
785
  colorize(value.to_s, :white)
@@ -781,7 +787,7 @@ module BrainzLab
781
787
  end
782
788
 
783
789
  def status_phrase(status)
784
- Rack::Utils::HTTP_STATUS_CODES[status] || "Unknown"
790
+ Rack::Utils::HTTP_STATUS_CODES[status] || 'Unknown'
785
791
  end
786
792
 
787
793
  def truncate(text, length)