class Puma::ErrorLogger

The implementation of a detailed error logging. @version 5.0.0

Constants

LOG_QUEUE
REQUEST_FORMAT

Attributes

ioerr[R]

Public Class Methods

new(ioerr) click to toggle source
# File lib/puma/error_logger.rb, line 18
def initialize(ioerr)
  @ioerr = ioerr

  @debug = ENV.key? 'PUMA_DEBUG'
end
stdio() click to toggle source
# File lib/puma/error_logger.rb, line 24
def self.stdio
  new $stderr
end

Public Instance Methods

debug(options={}) click to toggle source

Print occurred error details only if environment variable PUMA_DEBUG is defined. options hash with additional options:

  • error is an exception object

  • req the http request

  • text (default nil) custom string to print in title and before all remaining info.

# File lib/puma/error_logger.rb, line 47
def debug(options={})
  return unless @debug

  error = options[:error]
  req = options[:req]

  string_block = []
  string_block << title(options)
  string_block << request_dump(req) if request_parsed?(req)
  string_block << error.backtrace if error

  internal_write string_block.join("\n")
end
info(options={}) click to toggle source

Print occurred error details. options hash with additional options:

  • error is an exception object

  • req the http request

  • text (default nil) custom string to print in title and before all remaining info.

# File lib/puma/error_logger.rb, line 35
def info(options={})
  internal_write title(options)
end
request_dump(req) click to toggle source
# File lib/puma/error_logger.rb, line 73
def request_dump(req)
  "Headers: #{request_headers(req)}\n" \
  "Body: #{req.body}"
end
request_headers(req) click to toggle source
# File lib/puma/error_logger.rb, line 89
def request_headers(req)
  headers = req.env.select { |key, _| key.start_with?('HTTP_') }
  headers.map { |key, value| [key[5..-1], value] }.to_h.inspect
end
request_parsed?(req) click to toggle source
# File lib/puma/error_logger.rb, line 94
def request_parsed?(req)
  req && req.env[REQUEST_METHOD]
end
request_title(req) click to toggle source
# File lib/puma/error_logger.rb, line 78
def request_title(req)
  env = req.env

  REQUEST_FORMAT % [
    env[REQUEST_METHOD],
    env[REQUEST_PATH] || env[PATH_INFO],
    env[QUERY_STRING] || "",
    env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-"
  ]
end
title(options={}) click to toggle source
# File lib/puma/error_logger.rb, line 61
def title(options={})
  text = options[:text]
  req = options[:req]
  error = options[:error]

  string_block = ["#{Time.now}"]
  string_block << " #{text}" if text
  string_block << " (#{request_title(req)})" if request_parsed?(req)
  string_block << ": #{error.inspect}" if error
  string_block.join('')
end

Private Instance Methods

internal_write(str) click to toggle source
# File lib/puma/error_logger.rb, line 98
def internal_write(str)
  LOG_QUEUE << str
  while (w_str = LOG_QUEUE.pop(true)) do
    begin
      @ioerr.is_a?(IO) and @ioerr.wait_writable(1)
      @ioerr.write "#{w_str}\n"
      @ioerr.flush unless @ioerr.sync
    rescue Errno::EPIPE, Errno::EBADF, IOError, Errno::EINVAL
    # 'Invalid argument' (Errno::EINVAL) may be raised by flush
    end
  end
rescue ThreadError
end