mirror of
https://github.com/mperham/sidekiq.git
synced 2022-11-09 13:52:34 -05:00
165 lines
3.6 KiB
Ruby
165 lines
3.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "logger"
|
|
require "time"
|
|
|
|
module Sidekiq
|
|
module Context
|
|
def self.with(hash)
|
|
current.merge!(hash)
|
|
yield
|
|
ensure
|
|
hash.each_key { |key| current.delete(key) }
|
|
end
|
|
|
|
def self.current
|
|
Thread.current[:sidekiq_context] ||= {}
|
|
end
|
|
end
|
|
|
|
module LoggingUtils
|
|
LEVELS = {
|
|
"debug" => 0,
|
|
"info" => 1,
|
|
"warn" => 2,
|
|
"error" => 3,
|
|
"fatal" => 4
|
|
}
|
|
LEVELS.default_proc = proc do |_, level|
|
|
Sidekiq.logger.warn("Invalid log level: #{level.inspect}")
|
|
nil
|
|
end
|
|
|
|
def debug?
|
|
level <= 0
|
|
end
|
|
|
|
def info?
|
|
level <= 1
|
|
end
|
|
|
|
def warn?
|
|
level <= 2
|
|
end
|
|
|
|
def error?
|
|
level <= 3
|
|
end
|
|
|
|
def fatal?
|
|
level <= 4
|
|
end
|
|
|
|
def local_level
|
|
Thread.current[:sidekiq_log_level]
|
|
end
|
|
|
|
def local_level=(level)
|
|
case level
|
|
when Integer
|
|
Thread.current[:sidekiq_log_level] = level
|
|
when Symbol, String
|
|
Thread.current[:sidekiq_log_level] = LEVELS[level.to_s]
|
|
when nil
|
|
Thread.current[:sidekiq_log_level] = nil
|
|
else
|
|
raise ArgumentError, "Invalid log level: #{level.inspect}"
|
|
end
|
|
end
|
|
|
|
def level
|
|
local_level || super
|
|
end
|
|
|
|
# Change the thread-local level for the duration of the given block.
|
|
def log_at(level)
|
|
old_local_level = local_level
|
|
self.local_level = level
|
|
yield
|
|
ensure
|
|
self.local_level = old_local_level
|
|
end
|
|
|
|
# Redefined to check severity against #level, and thus the thread-local level, rather than +@level+.
|
|
# FIXME: Remove when the minimum Ruby version supports overriding Logger#level.
|
|
def add(severity, message = nil, progname = nil, &block)
|
|
severity ||= ::Logger::UNKNOWN
|
|
progname ||= @progname
|
|
|
|
return true if @logdev.nil? || severity < level
|
|
|
|
if message.nil?
|
|
if block_given?
|
|
message = yield
|
|
else
|
|
message = progname
|
|
progname = @progname
|
|
end
|
|
end
|
|
|
|
@logdev.write format_message(format_severity(severity), Time.now, progname, message)
|
|
end
|
|
end
|
|
|
|
class Logger < ::Logger
|
|
include LoggingUtils
|
|
|
|
def initialize(*args, **kwargs)
|
|
super
|
|
self.formatter = Sidekiq.log_formatter
|
|
end
|
|
|
|
module Formatters
|
|
class Base < ::Logger::Formatter
|
|
def tid
|
|
Thread.current["sidekiq_tid"] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
|
|
end
|
|
|
|
def ctx
|
|
Sidekiq::Context.current
|
|
end
|
|
|
|
def format_context
|
|
if ctx.any?
|
|
" " + ctx.compact.map { |k, v|
|
|
case v
|
|
when Array
|
|
"#{k}=#{v.join(",")}"
|
|
else
|
|
"#{k}=#{v}"
|
|
end
|
|
}.join(" ")
|
|
end
|
|
end
|
|
end
|
|
|
|
class Pretty < Base
|
|
def call(severity, time, program_name, message)
|
|
"#{time.utc.iso8601(3)} pid=#{::Process.pid} tid=#{tid}#{format_context} #{severity}: #{message}\n"
|
|
end
|
|
end
|
|
|
|
class WithoutTimestamp < Pretty
|
|
def call(severity, time, program_name, message)
|
|
"pid=#{::Process.pid} tid=#{tid}#{format_context} #{severity}: #{message}\n"
|
|
end
|
|
end
|
|
|
|
class JSON < Base
|
|
def call(severity, time, program_name, message)
|
|
hash = {
|
|
ts: time.utc.iso8601(3),
|
|
pid: ::Process.pid,
|
|
tid: tid,
|
|
lvl: severity,
|
|
msg: message
|
|
}
|
|
c = ctx
|
|
hash["ctx"] = c unless c.empty?
|
|
|
|
Sidekiq.dump_json(hash) << "\n"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|