Module: Browserctl::CrashReport

Defined in:
lib/browserctl/crash_report.rb

Overview

Writes a local crash report JSON file when the daemon panics. No telemetry, no upload — purely a local artifact users can attach to bug reports.

The writer is intentionally defensive: it must never raise. If anything goes wrong while writing the file, it falls back to a single ‘[crash-report-failed]` line on stderr and returns nil.

Constant Summary collapse

SCHEMA_VERSION =
1
LAST_EVENTS_LIMIT =
50

Class Method Summary collapse

Class Method Details

.write(error:, log_path: nil) ⇒ String?

Returns the path of the written crash file, or nil on failure.

Parameters:

  • error (Exception)

    the unhandled exception that took the daemon down

  • log_path (String, nil) (defaults to: nil)

    path to the daemon’s JSONL log; the last LAST_EVENTS_LIMIT valid records are tailed in

Returns:

  • (String, nil)

    the path of the written crash file, or nil on failure



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/browserctl/crash_report.rb', line 26

def self.write(error:, log_path: nil)
  ts = Time.now.utc
  filename = "crash-#{ts.iso8601(3).gsub(':', '-')}.json"
  dir = Browserctl.log_dir
  FileUtils.mkdir_p(dir, mode: 0o700)
  path = File.join(dir, filename)

  payload = {
    schema_version: SCHEMA_VERSION,
    ts: ts.iso8601(3),
    daemon_version: Browserctl::VERSION,
    ruby_version: RUBY_VERSION,
    os: os_info,
    error: error_info(error),
    backtrace: Array(error.backtrace),
    last_events: tail_events(log_path)
  }

  File.open(path, File::WRONLY | File::CREAT | File::TRUNC, 0o600) do |f|
    f.write(JSON.pretty_generate(payload))
  end
  path
rescue StandardError => e
  warn "[crash-report-failed] #{e.class}: #{e.message}"
  nil
end