Class: HotCell::Log

Inherits:
Object
  • Object
show all
Defined in:
lib/hot_cell/log.rb

Overview

A cell has no network, so nothing inside it can dial a collector. That rules out less than it appears to, because stdout is not a network: it is a pipe to the container runtime, whose log driver runs in that daemon with the host's network. So logs ship normally under network: none, and a cell writes structured JSON lines with the standard library and gets a real log for free.

This is the channel for everything no response can carry: deadline kills, reaps that found a signal, boot checks, and queue high-water.

Lines follow docs/LOGS.md: ECS field names, domain fields under the hotcell namespace. The fleet's collector routes on service.name, takes the record timestamp from @timestamp, and severity from log.level, so those three are load-bearing: renaming any of them silently drops or mislabels every cell log line in production.

Constant Summary collapse

LEVELS =

Severity lives here rather than in the collector so that adding an event never needs a collector change. An event missing from this table logs as INFO rather than not at all.

{
  "cell.boot" => "INFO",
  "cell.stopping" => "INFO",
  "cell.stopped" => "INFO",
  "cell.ptrace_scope_unknown" => "ERROR",
  "request" => "INFO",
  "request.abandoned" => "WARN",
  "worker.forked" => "INFO",
  "worker.reaped" => "INFO",
  "worker.crashed" => "ERROR",
  "worker.killed" => "WARN",
  "worker.deadline" => "WARN",
  "worker.lingered" => "WARN",
  "worker.unforkable" => "ERROR",
  "worker.undispatchable" => "ERROR",
  "worker.unreadable_report" => "ERROR",
  "control.abandoned" => "WARN",
  "control.unanswerable" => "WARN",
  "slot.uncleaned" => "WARN",
  "slot.undiscarded" => "WARN",
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io = $stdout) ⇒ Log

Returns a new instance of Log.



48
49
50
51
# File 'lib/hot_cell/log.rb', line 48

def initialize(io = $stdout)
  @io = io
  @io.sync = true
end

Class Method Details

.nullObject



44
45
46
# File 'lib/hot_cell/log.rb', line 44

def self.null
  new File.open(File::NULL, "w")
end

Instance Method Details

#write(event, **fields) ⇒ Object

A log line is never worth the cell. This runs inside the loop that enforces every request's deadline, and the sink is a pipe to a runtime that can go away or stop draining. Losing the line is the correct trade against losing the process.



56
57
58
59
60
# File 'lib/hot_cell/log.rb', line 56

def write(event, **fields)
  emit line(event, fields)
rescue JSON::GeneratorError
  emit line(event, unloggable: fields.keys)
end