simplify logging setup
* use Syslog::Logger instead of writing our own * extract and share the log formatting between Syslog and file logging Change-Id: I266713e4c390f11d1650afcf9005059995aca922 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/341759 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Jacob Burroughs <jburroughs@instructure.com> QA-Review: Cody Cutrer <cody@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
parent
c29d816cd5
commit
474233f086
|
@ -79,16 +79,13 @@ module CanvasRails
|
|||
|
||||
log_config = Rails.root.join("config/logging.yml").file? && Rails.application.config_for(:logging).with_indifferent_access
|
||||
log_config = { "logger" => "rails", "log_level" => "debug" }.merge(log_config || {})
|
||||
opts = {}
|
||||
require "canvas_logger"
|
||||
|
||||
config.log_level = log_config["log_level"]
|
||||
log_level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase)
|
||||
opts[:skip_thread_context] = true if log_config["log_context"] == false
|
||||
log_level = Logger.const_get(config.log_level.to_s.upcase)
|
||||
|
||||
case log_config["logger"]
|
||||
when "syslog"
|
||||
require "syslog_wrapper"
|
||||
require "syslog/logger"
|
||||
log_config["app_ident"] ||= "canvas-lms"
|
||||
log_config["daemon_ident"] ||= "canvas-lms-daemon"
|
||||
facilities = 0
|
||||
|
@ -96,17 +93,43 @@ module CanvasRails
|
|||
facilities |= Syslog.const_get :"LOG_#{facility.to_s.upcase}"
|
||||
end
|
||||
ident = (ENV["RUNNING_AS_DAEMON"] == "true") ? log_config["daemon_ident"] : log_config["app_ident"]
|
||||
opts[:include_pid] = true if log_config["include_pid"] == true
|
||||
config.logger = SyslogWrapper.new(ident, facilities, opts)
|
||||
config.logger.level = log_level
|
||||
|
||||
config.logger = Syslog::Logger.new(ident, facilities)
|
||||
|
||||
syslog_options = (log_config["include_pid"] == true) ? Syslog::LOG_PID : 0
|
||||
if (Syslog.instance.options & Syslog::LOG_PID) != syslog_options
|
||||
config.logger.syslog = Syslog.reopen(Syslog.instance.ident,
|
||||
(Syslog.instance.options & ~Syslog::LOG_PID) | syslog_options,
|
||||
Syslog.instance.facility)
|
||||
end
|
||||
else
|
||||
require "canvas_logger"
|
||||
log_path = config.paths["log"].first
|
||||
|
||||
if ENV["RUNNING_AS_DAEMON"] == "true"
|
||||
log_path = Rails.root.join("log/delayed_job.log")
|
||||
end
|
||||
|
||||
config.logger = CanvasLogger.new(log_path, log_level, opts)
|
||||
FileUtils.mkdir_p(File.dirname(log_path))
|
||||
config.logger = CanvasLogger.new(log_path, log_level)
|
||||
end
|
||||
config.logger.level = log_level
|
||||
unless log_config["log_context"] == false
|
||||
class ContextFormatter < Logger::Formatter
|
||||
def initialize(parent_formatter)
|
||||
super()
|
||||
|
||||
@parent_formatter = parent_formatter
|
||||
end
|
||||
|
||||
def call(severity, time, progname, msg)
|
||||
msg = @parent_formatter.call(severity, time, progname, msg)
|
||||
context = Thread.current[:context] || {}
|
||||
"[#{context[:session_id] || "-"} #{context[:request_id] || "-"}] #{msg}"
|
||||
end
|
||||
end
|
||||
|
||||
config.logger.formatter = ContextFormatter.new(config.logger.formatter)
|
||||
end
|
||||
|
||||
# Activate observers that should always be running
|
||||
|
|
|
@ -18,42 +18,6 @@
|
|||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class CanvasLogger < ActiveSupport::Logger
|
||||
attr_reader :log_path
|
||||
|
||||
def initialize(log_path, level = DEBUG, options = {})
|
||||
unless File.exist?(log_path)
|
||||
FileUtils.mkdir_p(File.dirname(log_path))
|
||||
end
|
||||
super(log_path, level)
|
||||
@log_path = log_path
|
||||
@skip_thread_context = options[:skip_thread_context]
|
||||
end
|
||||
|
||||
def add(severity, message = nil, progname = nil)
|
||||
return if level > severity
|
||||
|
||||
message = (message || (block_given? && yield) || progname).to_s
|
||||
# If a newline is necessary then create a new message ending with a newline.
|
||||
# Ensures that the original message is not mutated.
|
||||
unless @skip_thread_context
|
||||
context = Thread.current[:context] || {}
|
||||
message = "[#{context[:session_id] || "-"} #{context[:request_id] || "-"}] #{message}"
|
||||
end
|
||||
|
||||
super(severity, message, progname)
|
||||
end
|
||||
|
||||
def reopen(log_path)
|
||||
unless File.exist?(log_path)
|
||||
FileUtils.mkdir_p(File.dirname(log_path))
|
||||
end
|
||||
@log_path = log_path
|
||||
|
||||
old_logdev = @logdev
|
||||
@logdev = ::Logger::LogDevice.new(log_path, shift_age: 0, shift_size: 1_048_576)
|
||||
old_logdev.close
|
||||
end
|
||||
|
||||
def capture_messages(&)
|
||||
CanvasLogger.prepend Capture unless CanvasLogger.include?(Capture)
|
||||
capture_messages(&)
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2011 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require "syslog"
|
||||
|
||||
class SyslogWrapper
|
||||
attr_accessor :level, :datetime_format, :formatter
|
||||
|
||||
@@silencer = true
|
||||
def self.silencer
|
||||
@@silencer
|
||||
end
|
||||
|
||||
def silencer
|
||||
@@silencer
|
||||
end
|
||||
|
||||
def self.silencer=(obj)
|
||||
@@silencer = obj
|
||||
end
|
||||
|
||||
def silencer=(obj)
|
||||
@@silencer = obj
|
||||
end
|
||||
|
||||
def silence(temporary_level = Logger::ERROR)
|
||||
if silencer
|
||||
begin
|
||||
old_logger_level, @level = @level, temporary_level
|
||||
yield self
|
||||
ensure
|
||||
@level = old_logger_level
|
||||
end
|
||||
else
|
||||
yield self
|
||||
end
|
||||
end
|
||||
alias_method :quietly, :silence
|
||||
|
||||
# facility is a logical-or-ed collection of the following constants in Syslog
|
||||
# LOG_AUTHPRIV - security or authorization messages which should be kept private
|
||||
# LOG_CONSOLE - system console message
|
||||
# LOG_CRON - system task scheduler (cron or at)
|
||||
# LOG_DAEMON - a system daemon which has no facility value of its own
|
||||
# LOG_FTP - an ftp server
|
||||
# LOG_LRP - line printer subsystem
|
||||
# LOG_MAIL - mail delivery or transport subsystem
|
||||
# LOG_NEWS - usenet news system
|
||||
# LOG_NTP - network time protocol server
|
||||
# LOG_SECURITY - general security message
|
||||
# LOG_SYSLOG - messages generated internally by syslog
|
||||
# LOG_USER - generic user-level message
|
||||
# LOG_UUCP - uucp subsystem
|
||||
# LOG_LOCAL0 through LOG_LOCAL7 - locally defined facilities
|
||||
# example: SyslogWrapper.new("canvas", Syslog::LOG_USER, :include_pid => true)
|
||||
def initialize(ident, facility = 0, options = {})
|
||||
unless $syslog
|
||||
flags = 0
|
||||
flags |= Syslog::LOG_CONS if options[:bail_to_console]
|
||||
flags |= Syslog::LOG_NDELAY if options[:ndelay]
|
||||
flags |= Syslog::LOG_PERROR if options[:perror]
|
||||
flags |= Syslog::LOG_PID if options[:include_pid]
|
||||
$syslog = Syslog.open(ident, flags, facility)
|
||||
end
|
||||
@level = 0
|
||||
@skip_thread_context = options[:skip_thread_context]
|
||||
@datetime_format = nil # ignored completely
|
||||
end
|
||||
|
||||
def close; end
|
||||
|
||||
SEVERITY_MAP = {
|
||||
Logger::DEBUG => :debug,
|
||||
Logger::INFO => :info,
|
||||
Logger::WARN => :warning,
|
||||
Logger::ERROR => :err,
|
||||
Logger::FATAL => :crit,
|
||||
Logger::UNKNOWN => :notice
|
||||
}.freeze
|
||||
|
||||
def add(severity, message = nil, progname = nil)
|
||||
severity ||= Logger::UNKNOWN
|
||||
return if @level > severity
|
||||
|
||||
if message.nil?
|
||||
message = if block_given?
|
||||
yield
|
||||
else
|
||||
progname
|
||||
end
|
||||
end
|
||||
message = message.to_s.strip.gsub(/\e\[([0-9]+(;|))+m/, "")
|
||||
unless @skip_thread_context
|
||||
context = Thread.current[:context] || {}
|
||||
message = "[#{context[:session_id] || "-"} #{context[:request_id] || "-"}] #{message}"
|
||||
end
|
||||
$syslog.send(SEVERITY_MAP[severity], "%s", message)
|
||||
end
|
||||
alias_method :log, :add
|
||||
|
||||
def <<(msg)
|
||||
add(@level, msg)
|
||||
end
|
||||
|
||||
def debug(progname = nil, &)
|
||||
add(Logger::DEBUG, nil, progname, &)
|
||||
end
|
||||
|
||||
def info(progname = nil, &)
|
||||
add(Logger::INFO, nil, progname, &)
|
||||
end
|
||||
|
||||
def warn(progname = nil, &)
|
||||
add(Logger::WARN, nil, progname, &)
|
||||
end
|
||||
|
||||
def error(progname = nil, &)
|
||||
add(Logger::ERROR, nil, progname, &)
|
||||
end
|
||||
|
||||
def fatal(progname = nil, &)
|
||||
add(Logger::FATAL, nil, progname, &)
|
||||
end
|
||||
|
||||
def unknown(progname = nil, &)
|
||||
add(Logger::UNKNOWN, nil, progname, &)
|
||||
end
|
||||
|
||||
def debug?
|
||||
@level <= Logger::DEBUG
|
||||
end
|
||||
|
||||
def info?
|
||||
@level <= Logger::INFO
|
||||
end
|
||||
|
||||
def warn?
|
||||
@level <= Logger::WARN
|
||||
end
|
||||
|
||||
def error?
|
||||
@level <= Logger::ERROR
|
||||
end
|
||||
|
||||
def fatal?
|
||||
@level <= Logger::FATAL
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue