Module: Browserctl::Commands::Trace

Defined in:
lib/browserctl/commands/trace.rb

Overview

‘browserctl trace [<session>] [–no-redact]` — pretty timeline of structured log events across cli.log + daemon.log. Thin CLI dispatcher; parsing lives in `Browserctl::Trace::EventStream`, rendering in `Browserctl::Trace::Renderer`, redaction in `Browserctl::Redactor`.

Constant Summary collapse

USAGE =
"Usage: browserctl trace [<session>] [--no-redact]"
NO_REDACT_WARNING =
"[browserctl] traces include unredacted secret values; " \
"do not paste this output publicly."

Class Method Summary collapse

Class Method Details

.build_redactorObject



63
64
65
66
67
68
# File 'lib/browserctl/commands/trace.rb', line 63

def self.build_redactor
  extra = defined?(Browserctl::SecretResolverRegistry) ? Browserctl::SecretResolverRegistry.resolved_values : []
  Browserctl::Redactor.from_env(extra: extra)
rescue StandardError
  Browserctl::Redactor.new(secrets: [])
end

.emit(stream, redactor, out) ⇒ Object



38
39
40
41
42
43
44
45
# File 'lib/browserctl/commands/trace.rb', line 38

def self.emit(stream, redactor, out)
  fmt = OutputFormat.current
  if fmt.json?
    fmt.emit({ records: stream.records.map { |r| redact_record(r, redactor) } }, io: out)
  elsif !fmt.silent?
    Browserctl::Trace::Renderer.new(io: out, redactor: redactor).render(stream)
  end
end

.emit_empty(message, out) ⇒ Object



51
52
53
# File 'lib/browserctl/commands/trace.rb', line 51

def self.emit_empty(message, out)
  OutputFormat.current.emit({ records: [], message: message }, message, io: out)
end

.empty_message(log_dir, session_filter) ⇒ Object



47
48
49
# File 'lib/browserctl/commands/trace.rb', line 47

def self.empty_message(log_dir, session_filter)
  session_filter ? "No entries match session=#{session_filter}" : "No log entries found in #{log_dir}"
end

.redact_record(record, redactor) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/browserctl/commands/trace.rb', line 55

def self.redact_record(record, redactor)
  return record unless redactor

  JSON.parse(redactor.redact(JSON.generate(record)))
rescue JSON::ParserError
  record
end

.run(args, log_dir: Browserctl.log_dir, out: $stdout, err: $stderr) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/browserctl/commands/trace.rb', line 22

def self.run(args, log_dir: Browserctl.log_dir, out: $stdout, err: $stderr)
  abort USAGE if args.include?("-h") || args.include?("--help")
  args = args.dup
  redact = !args.delete("--no-redact")
  session_filter = args.shift
  redactor = redact ? build_redactor : (warn_no_redact(err) || nil)

  stream = Browserctl::Trace::EventStream.new(log_dir, session_filter: session_filter)
  if stream.empty?
    emit_empty(empty_message(log_dir, session_filter), out)
    return
  end

  emit(stream, redactor, out)
end

.warn_no_redact(err) ⇒ Object



70
71
72
73
# File 'lib/browserctl/commands/trace.rb', line 70

def self.warn_no_redact(err)
  err&.puts NO_REDACT_WARNING
  nil
end