Class: RailsErrorDashboard::Services::CoverageTracker
- Inherits:
-
Object
- Object
- RailsErrorDashboard::Services::CoverageTracker
- Defined in:
- lib/rails_error_dashboard/services/coverage_tracker.rb
Overview
Diagnostic-mode code path coverage using Ruby’s Coverage API.
Operator enables coverage via dashboard button, reproduces the error, views source code with executed-line overlay, then disables. Zero overhead when off. Uses oneshot_lines mode (each line fires once).
SAFETY:
-
Coverage is process-global (not thread-local) — data blends across threads
-
oneshot_lines mode has near-zero ongoing overhead
-
peek_result is read-only, does not mutate state
-
Every method rescue-wrapped (never raises)
-
Ruby 3.2+ required for Coverage.setup with oneshot_lines
Class Method Summary collapse
-
.active? ⇒ Boolean
Whether coverage is currently being collected.
-
.disable! ⇒ Object
Stop coverage collection and clear all data.
-
.enable! ⇒ Boolean
Start coverage collection in oneshot_lines mode.
-
.peek(file_path) ⇒ Hash{Integer => Boolean}
Get executed line numbers for a specific file.
-
.supported? ⇒ Boolean
Check if the current Ruby version supports Coverage with oneshot_lines.
Class Method Details
.active? ⇒ Boolean
Whether coverage is currently being collected
87 88 89 |
# File 'lib/rails_error_dashboard/services/coverage_tracker.rb', line 87 def active? @active end |
.disable! ⇒ Object
Stop coverage collection and clear all data
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/rails_error_dashboard/services/coverage_tracker.rb', line 63 def disable! return unless @active @mutex.synchronize do return unless @active # Only call Coverage.result if WE started the session # Don't kill another tool's coverage (e.g. SimpleCov) if @we_started begin Coverage.result rescue RuntimeError # Already stopped end end @active = false @we_started = false end rescue => e Rails.logger.error("[RailsErrorDashboard] CoverageTracker.disable! failed: #{e.class}: #{e.}") @active = false @we_started = false end |
.enable! ⇒ Boolean
Start coverage collection in oneshot_lines mode
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/rails_error_dashboard/services/coverage_tracker.rb', line 32 def enable! return false unless supported? return true if @active @mutex.synchronize do return true if @active Coverage.setup(oneshot_lines: true) Coverage.resume @we_started = true @active = true end true rescue => e # Coverage.setup raises RuntimeError if another session is active (e.g. SimpleCov). # In that case, we piggyback on the existing session for peek_result. if e.is_a?(RuntimeError) && coverage_running? @mutex.synchronize do @we_started = false @active = true end true else Rails.logger.error("[RailsErrorDashboard] CoverageTracker.enable! failed: #{e.class}: #{e.}") @active = false false end end |
.peek(file_path) ⇒ Hash{Integer => Boolean}
Get executed line numbers for a specific file
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/rails_error_dashboard/services/coverage_tracker.rb', line 94 def peek(file_path) return nil if file_path.nil? return nil unless @active result = Coverage.peek_result file_data = result[file_path] return {} unless file_data # Coverage result format varies by mode: # - oneshot_lines: { oneshot_lines: [nil, 0, nil, 1, ...] } # - lines (SimpleCov): { lines: [0, 1, nil, 2, ...] } or just [0, 1, nil, 2, ...] # where index = line_number - 1, nil = not executable, 0 = not hit, N>0 = hit lines_data = if file_data.is_a?(Hash) file_data[:oneshot_lines] || file_data[:lines] elsif file_data.is_a?(Array) file_data end return {} unless lines_data.is_a?(Array) executed = {} lines_data.each_with_index do |val, idx| next if val.nil? # not an executable line line_number = idx + 1 executed[line_number] = val > 0 end executed rescue => e Rails.logger.error("[RailsErrorDashboard] CoverageTracker.peek failed: #{e.class}: #{e.}") {} end |
.supported? ⇒ Boolean
Check if the current Ruby version supports Coverage with oneshot_lines
26 27 28 |
# File 'lib/rails_error_dashboard/services/coverage_tracker.rb', line 26 def supported? RUBY_VERSION >= "3.2" end |