Module: Kino::Log

Defined in:
lib/kino/log.rb

Overview

Server log lines: the lifecycle notices, crash and respawn reports, hook failures, the failed-request report, and whatever apps write to rack.errors, all in one shape:

kino[4213] worker-3: after_worker_boot hook raised RuntimeError: boom

The label is syslog's ident[pid] tag plus the source that spoke: the worker ractor and/or thread by name, main for neither. On color terminals the label is dim, yellow, or red by level; the message stays plain. Notes go to stdout, warnings and errors to stderr.

Hooks may log through here too (Kino::Log.info "cache warm"). Every method is safe inside a worker ractor: the line is handed to the native layer, which owns the streams, so no ractor touches $stdout or $stderr itself.

Constant Summary collapse

FRAMES =

Frames shown in a failed-request report before the rest are folded.

12
WORKING_DIR =

The working directory at boot, stripped from backtrace frames so the app's own code reads app/controllers/x.rb:9 rather than an absolute path (frozen: worker ractors read it).

File.join(Dir.pwd, "").freeze

Class Method Summary collapse

Class Method Details

.error(message) ⇒ void

This method returns an undefined value.

Parameters:

  • message (#to_s)


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

def error(message)
  Native.log_line("error", source, message.to_s)
end

.exception(error, env, status: 500) ⇒ void

This method returns an undefined value.

The failed-request report: the request line, the error, and where it raised in the app, then the backtrace with the app's own frames first (relative to the working directory) and the rest folded.

500 GET /boom · RuntimeError: kaboom (app.rb:12:in 'explode')
  app.rb:12:in 'explode'
  /gems/rack-3.2.7/lib/rack/builder.rb:...
  … 38 more

Parameters:

  • error (Exception)
  • env (Hash)

    the Rack env of the failed request

  • status (Integer) (defaults to: 500)

    the status the client got



61
62
63
64
65
66
67
68
# File 'lib/kino/log.rb', line 61

def exception(error, env, status: 500)
  frames, depth = trace(error)
  site = frames.first ? " (#{frames.first})" : ""
  lines = ["#{status} #{env["REQUEST_METHOD"]} #{env["PATH_INFO"]} · #{error.class}: #{error.message}#{site}"]
  frames.each { |frame| lines << "    #{frame}" }
  lines << "#{depth - frames.size} more" if depth > frames.size
  error(lines.join("\n"))
end

.info(message) ⇒ void

This method returns an undefined value.

Parameters:

  • message (#to_s)


32
33
34
# File 'lib/kino/log.rb', line 32

def info(message)
  Native.log_line("info", source, message.to_s)
end

.labelString

The kino[<pid>] <source>: tag a line from here carries.

Returns:

  • (String)


72
73
74
# File 'lib/kino/log.rb', line 72

def label
  "kino[#{Process.pid}] #{source}:"
end

.sourceString

Who is speaking: the ractor's name, the thread's name, both joined with a slash, or main when neither is named. Kino names its worker ractors and threads worker-N.

Returns:

  • (String)


80
81
82
83
# File 'lib/kino/log.rb', line 80

def source
  parts = [Ractor.current.name, Thread.current.name].compact
  parts.empty? ? "main" : parts.join("/")
end

.warn(message) ⇒ void

This method returns an undefined value.

Parameters:

  • message (#to_s)


38
39
40
# File 'lib/kino/log.rb', line 38

def warn(message)
  Native.log_line("warn", source, message.to_s)
end