Module: Browserctl::Replay::Telemetry

Defined in:
lib/browserctl/replay/telemetry.rb

Overview

Append-only JSONL log of replay drift events for offline analysis. Local-only; nothing is uploaded. One line per event.

Constant Summary collapse

LOG_BASENAME =
"replay_drift.jsonl"

Class Method Summary collapse

Class Method Details

.emit(ctx, workflow:, path: log_path) ⇒ Integer

Write each drift event from a Replay::Context as its own JSONL line.

Parameters:

  • ctx (Browserctl::Replay::Context, nil)
  • workflow (String)

    workflow name for cross-reference

  • path (String) (defaults to: log_path)

    override the destination (testing)

Returns:

  • (Integer)

    number of events written



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

def emit(ctx, workflow:, path: log_path)
  events = ctx&.drift_events
  return 0 if events.nil? || events.empty?

  ensure_log_file(path)
  ts = Time.now.utc.iso8601
  File.open(path, "a") do |f|
    events.each do |e|
      f.puts JSON.generate(
        event: "replay_drift",
        ts: ts,
        workflow: workflow,
        command: e.command.to_s,
        selector: e.selector,
        matched_ref: e.matched_ref,
        score: e.score,
        reason: e.reason
      )
    end
  end
  events.size
rescue SystemCallError, IOError
  # Telemetry must never break a run.
  0
end

.ensure_log_file(path) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/browserctl/replay/telemetry.rb', line 51

def ensure_log_file(path)
  FileUtils.mkdir_p(File.dirname(path), mode: 0o700)
  return if File.exist?(path)

  FileUtils.touch(path)
  File.chmod(0o600, path)
end

.log_pathObject



16
17
18
# File 'lib/browserctl/replay/telemetry.rb', line 16

def log_path
  File.join(Browserctl::BROWSERCTL_DIR, LOG_BASENAME)
end