OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/lib/open_project/logging/log_delegator.rb

111 lines
2.9 KiB

module OpenProject
module Logging
class LogDelegator
class << self
##
# Consume a message and let it be handled
# by all handlers
def log(exception, context = {})
message =
if exception.is_a? Exception
context[:exception] = exception
"#{exception}: #{exception.message}"
else
exception.to_s
end
# Mark backtrace
if context[:exception]
context[:backtrace] = clean_backtrace(context[:exception])
end
# Set current contexts
context[:level] ||= context[:exception] ? :error : :info
context[:current_user] ||= User.current
registered_handlers.values.each do |handler|
handler.call message, context
rescue StandardError => e
Rails.logger.error "Failed to delegate log to #{handler.inspect}: #{e.inspect}"
end
nil
rescue StandardError => e
Rails.logger.error "Failed to process log message #{exception.inspect}: #{e.inspect}"
end
%i(debug info warn error fatal unknown).each do |level|
define_method(level) do |*args|
message = args.shift
context = args.shift || {}
log(message, context.merge(level: level))
end
end
##
# Get a clean backtrace
def clean_backtrace(exception)
return nil unless exception&.backtrace
Rails.backtrace_cleaner.clean exception.backtrace, :full
end
##
# The active set of error handlers
def registered_handlers
@handlers ||= default_handlers
end
##
# Register a new handler
def register(key, handler)
raise "#{key} already registered" if registered_handlers.key?(key)
raise "handler must respond_to #call" unless handler.respond_to?(:call)
@handlers[key] = handler
end
##
# Create a payload for lograge from a controller request line
def controller_payload_hash(_controller)
{
user: User.current.try(:id)
}
end
private
def default_handlers
{ rails_logger: method(:rails_logger_handler) }
end
##
# A lambda handler for logging the error
# to rails.
def rails_logger_handler(message, context = {})
Rails.logger.public_send(
context[:level],
"#{context_string(context)} #{message}"
)
end
##
# Create a context string
def context_string(context)
%i[current_user project reference]
.map do |key|
value = context[key]
if value
"[#{key}=#{value}]"
end
end
.compact
.join(' ')
end
end
end
end
end