如何使 rails 库中的登录像在模型和控制器中一样工作
How to make logging in rails libs works like in models and controllers
到目前为止,我一直使用“puts”将自定义日志记录信息添加到我的代码中。但现在有点痛苦。例如,当我 运行 rspec 时,我对用 puts 添加的所有冗长内容都不感兴趣。所以我安装了“logging and logging-rails gem”,因为它的安装速度非常快,令人满意。
当我从模型和控制器调用记录器时效果很好,但当我在库中使用记录器时效果不佳。我得到那个错误:NameError - undefined local variable or method `logger' for CustomLib:Class.
我成功的最简单的事情是调用 'Rails.logger' 而不是 'logger'。但是在我的日志文件中,引用该行的 class 将是 'Rails' 但我想要 'CustomLib'。对于模型和控制器,显示正确的 class 名称,无需我自己的任何干预。
# config/environnement/test.rb
# Set the logging destination(s)
config.log_to = %w[stdout]
config.log_level = :info
# Show the logging configuration on STDOUT
config.show_log_configuration = false
# lib/custom_lib.rb
class CustomLib
def initialize
Rails.logger.info 'foo'
end
end
当我使用或测试我的自定义库时 class 我会得到:
[2019-06-21T16:26:41] 信息 Rails : foo
相反,我希望看到:
[2019-06-21T16:26:41] 信息自定义库:foo
我有点迷失在 rails 中的所有日志法力 gem 中,我不知道接下来要尝试什么才能实现该目标...
编辑
当我在“logger.info 'foo'”行之前放置一个 byebug 并通过 'step' 进入它时,如果我是否在 model/controller 或自定义库。
# In custom lib, step enters this file "gems/logging-2.2.2/lib/logging/logger.rb"
# And Rails.logger returns an object like this one beloow
Logging::Logger:0x000055a2182f8f40
@name="Rails",
@parent=#<Logging::RootLogger:0x000055a2182e7ee8
@name="root",
@level=1>,
# In model/controller, step enters this file "gems/logging-rails-0.6.0/lib/logging/rails/mixin.rb"
# And Rails.logger returns an object like this one beloow
Logging::Logger:0x0000557aed75d7b8
@name="Controller",
@parent=#<Logging::RootLogger:0x0000557aedfcf630
@name="root",
@level=0>,
日志行中的 Rails
是 the progname
of the logger。您可以创建一个新的记录器,将 progname 设置为 'CustomLib'
with (say) Rails.logger.clone.tap {|l| l.progname = 'CustomLib' }
,但这并不是 progname
的真正目的,它是指定 程序,不是class.
的名称
您可以改为在日志行中包含 class 名称:
Rails.logger.info "[#{self.class}] - some message"
或者,您可以更努力地定义自己的格式化程序。这是一个包装现有记录器的便捷方法:
class ClassNameFormatter
def self.wrap_logger(klass, logger)
logger.clone.tap { |l| l.formatter = new(klass, logger.formatter) }
end
def initialize(klass, formatter=nil)
@klass = klass
@formatter = formatter ||= Logger::Formatter.new
end
def call(severity, timestamp, progname, msg)
@formatter.call severity, timestamp, progname, "[#{@klass.name}] - #{msg}"
end
end
使用方法:
class CustomLib
def initialize
@logger = ClassNameFormatter.wrap_logger self.class, Rails.logger
end
def call
@logger.info 'test log please ignore'
end
end
最后我找到了一个更好的方法,我只需要在我想要该行为的模块顶部包含 Logging.globally:
# lib/custom_lib.rb
class CustomLib
include Logging.globally
def initialize
logger.info 'foo'
end
end
到目前为止,我一直使用“puts”将自定义日志记录信息添加到我的代码中。但现在有点痛苦。例如,当我 运行 rspec 时,我对用 puts 添加的所有冗长内容都不感兴趣。所以我安装了“logging and logging-rails gem”,因为它的安装速度非常快,令人满意。
当我从模型和控制器调用记录器时效果很好,但当我在库中使用记录器时效果不佳。我得到那个错误:NameError - undefined local variable or method `logger' for CustomLib:Class.
我成功的最简单的事情是调用 'Rails.logger' 而不是 'logger'。但是在我的日志文件中,引用该行的 class 将是 'Rails' 但我想要 'CustomLib'。对于模型和控制器,显示正确的 class 名称,无需我自己的任何干预。
# config/environnement/test.rb
# Set the logging destination(s)
config.log_to = %w[stdout]
config.log_level = :info
# Show the logging configuration on STDOUT
config.show_log_configuration = false
# lib/custom_lib.rb
class CustomLib
def initialize
Rails.logger.info 'foo'
end
end
当我使用或测试我的自定义库时 class 我会得到: [2019-06-21T16:26:41] 信息 Rails : foo
相反,我希望看到: [2019-06-21T16:26:41] 信息自定义库:foo
我有点迷失在 rails 中的所有日志法力 gem 中,我不知道接下来要尝试什么才能实现该目标...
编辑
当我在“logger.info 'foo'”行之前放置一个 byebug 并通过 'step' 进入它时,如果我是否在 model/controller 或自定义库。
# In custom lib, step enters this file "gems/logging-2.2.2/lib/logging/logger.rb"
# And Rails.logger returns an object like this one beloow
Logging::Logger:0x000055a2182f8f40
@name="Rails",
@parent=#<Logging::RootLogger:0x000055a2182e7ee8
@name="root",
@level=1>,
# In model/controller, step enters this file "gems/logging-rails-0.6.0/lib/logging/rails/mixin.rb"
# And Rails.logger returns an object like this one beloow
Logging::Logger:0x0000557aed75d7b8
@name="Controller",
@parent=#<Logging::RootLogger:0x0000557aedfcf630
@name="root",
@level=0>,
日志行中的 Rails
是 the progname
of the logger。您可以创建一个新的记录器,将 progname 设置为 'CustomLib'
with (say) Rails.logger.clone.tap {|l| l.progname = 'CustomLib' }
,但这并不是 progname
的真正目的,它是指定 程序,不是class.
您可以改为在日志行中包含 class 名称:
Rails.logger.info "[#{self.class}] - some message"
或者,您可以更努力地定义自己的格式化程序。这是一个包装现有记录器的便捷方法:
class ClassNameFormatter
def self.wrap_logger(klass, logger)
logger.clone.tap { |l| l.formatter = new(klass, logger.formatter) }
end
def initialize(klass, formatter=nil)
@klass = klass
@formatter = formatter ||= Logger::Formatter.new
end
def call(severity, timestamp, progname, msg)
@formatter.call severity, timestamp, progname, "[#{@klass.name}] - #{msg}"
end
end
使用方法:
class CustomLib
def initialize
@logger = ClassNameFormatter.wrap_logger self.class, Rails.logger
end
def call
@logger.info 'test log please ignore'
end
end
最后我找到了一个更好的方法,我只需要在我想要该行为的模块顶部包含 Logging.globally:
# lib/custom_lib.rb
class CustomLib
include Logging.globally
def initialize
logger.info 'foo'
end
end