Module: Kumi::Core::Analyzer::Debug
- Defined in:
- lib/kumi/core/analyzer/debug.rb
Defined Under Namespace
Modules: Loggable
Constant Summary collapse
- KEY =
:kumi_debug_log
Class Method Summary collapse
- .debug(id, **fields) ⇒ Object
-
.diff_state(before, after) ⇒ Object
State diffing.
- .drain_log ⇒ Object
-
.emit(pass:, diff:, elapsed_ms:, logs:) ⇒ Object
Emit debug event.
- .enabled? ⇒ Boolean
- .info(id, **fields) ⇒ Object
- .log(level:, id:, method: nil, **fields) ⇒ Object
- .max_depth ⇒ Object
- .max_items ⇒ Object
- .output_path ⇒ Object
-
.reset_log(pass:) ⇒ Object
Log buffer management.
- .trace(id, **start_fields) ⇒ Object
Class Method Details
.debug(id, **fields) ⇒ Object
62 63 64 |
# File 'lib/kumi/core/analyzer/debug.rb', line 62 def debug(id, **fields) log(level: :debug, id: id, **fields) end |
.diff_state(before, after) ⇒ Object
State diffing
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/kumi/core/analyzer/debug.rb', line 79 def diff_state(before, after) changes = {} all_keys = (before.keys + after.keys).uniq all_keys.each do |key| if !before.key?(key) changes[key] = { type: :added, value: truncate(after[key]) } elsif !after.key?(key) changes[key] = { type: :removed, value: truncate(before[key]) } elsif before[key] != after[key] changes[key] = { type: :changed, before: truncate(before[key]), after: truncate(after[key]) } end end changes end |
.drain_log ⇒ Object
34 35 36 37 38 |
# File 'lib/kumi/core/analyzer/debug.rb', line 34 def drain_log stash = Thread.current[KEY] Thread.current[KEY] = nil (stash && stash[:events]) || [] end |
.emit(pass:, diff:, elapsed_ms:, logs:) ⇒ Object
Emit debug event
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/kumi/core/analyzer/debug.rb', line 101 def emit(pass:, diff:, elapsed_ms:, logs:) payload = { ts: Time.now.utc.iso8601, pass: pass, elapsed_ms: elapsed_ms, diff: diff, logs: logs } if output_path && !output_path.empty? File.open(output_path, "a") { |f| f.puts(JSON.dump(payload)) } else $stdout.puts "\n=== STATE #{pass} (#{elapsed_ms}ms) ===" $stdout.puts JSON.pretty_generate(payload) end end |
.enabled? ⇒ Boolean
13 14 15 |
# File 'lib/kumi/core/analyzer/debug.rb', line 13 def enabled? ENV["KUMI_DEBUG_STATE"] == "1" end |
.info(id, **fields) ⇒ Object
58 59 60 |
# File 'lib/kumi/core/analyzer/debug.rb', line 58 def info(id, **fields) log(level: :info, id: id, **fields) end |
.log(level:, id:, method: nil, **fields) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/kumi/core/analyzer/debug.rb', line 40 def log(level:, id:, method: nil, **fields) buf = Thread.current[KEY] return unless buf loc = caller_locations(1, 1)&.first meth = method || loc&.base_label buf[:events] << { ts: Time.now.utc.iso8601, pass: buf[:pass], level: level, id: id, method: meth, file: loc&.path, line: loc&.lineno, **fields } end |
.max_depth ⇒ Object
21 22 23 |
# File 'lib/kumi/core/analyzer/debug.rb', line 21 def max_depth (ENV["KUMI_DEBUG_MAX_DEPTH"] || "5").to_i end |
.max_items ⇒ Object
25 26 27 |
# File 'lib/kumi/core/analyzer/debug.rb', line 25 def max_items (ENV["KUMI_DEBUG_MAX_ITEMS"] || "100").to_i end |
.output_path ⇒ Object
17 18 19 |
# File 'lib/kumi/core/analyzer/debug.rb', line 17 def output_path ENV.fetch("KUMI_DEBUG_OUTPUT_PATH", nil) end |
.reset_log(pass:) ⇒ Object
Log buffer management
30 31 32 |
# File 'lib/kumi/core/analyzer/debug.rb', line 30 def reset_log(pass:) Thread.current[KEY] = { pass: pass, events: [] } end |
.trace(id, **start_fields) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/kumi/core/analyzer/debug.rb', line 66 def trace(id, **start_fields) t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC) info(:"#{id}_start", **start_fields) yield.tap do |_ret| dt = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0) * 1000).round(2) info(:"#{id}_finish", ms: dt) end rescue StandardError => e log(level: :error, id: :"#{id}_error", error: e.class.name, message: e.) raise end |