我有一个工作的Rails 3.2应用程序(Windows Server 2008 R2上的Ruby 1.9.2p290),它为几个后台作业使用延迟作业。我最近用log4r取代了Rails的默认日志记录,它在Rails应用程序中工作得很好。然而,当我启动rake jobs:work
任务时,我得到一个错误,抱怨nil输出:
是否有人成功使用log4r处理延迟的作业?我可以使用一些指针;通过谷歌或DuckDuckGo搜索找不到任何东西。
下面是config/application.rb
代码片段:
require File.expand_path('../boot', __FILE__)
require 'erb'
require 'rails/all'
# log4r
require 'log4r'
require 'log4r/yamlconfigurator'
require 'log4r/outputter/datefileoutputter'
require 'log4r/outputter/consoleoutputters'
include Log4r
...
class Application < Rails::Application
...
# assign log4r's logger as rails' logger.
log4r_config = YAML.load(ERB.new(File.read(File.join(File.dirname(__FILE__), 'log4r.yml'))).result)
log4r_config['ENV'] = Rails.env
log4r_config['APPNAME'] = Rails.application.class.parent_name
YamlConfigurator.decode_yaml(log4r_config['log4r_config'])
config.logger = Log4r::Logger[Rails.env]
ActiveRecord::Base.logger = Log4r::Logger[Rails.env]
end
config/log4r.yml
文件:
log4r_config:
# define all loggers ...
loggers:
- name: production
level: WARN
trace: 'false'
outputters:
- datefile_production
- console_production
- name: development
level: DEBUG
trace: 'true'
outputters:
- datefile_development
- console_development
- name: test
level: DEBUG
trace: 'true'
outputters:
- datefile_test
- console_test
# define all outputters (incl. formatters)
outputters:
- type: DateFileOutputter
name: datefile_production
dirname: "<%= File.join(Rails.root, 'log') %>"
filename: "production.log"
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%pt%dt%X{:remote_ip}t%X{:user}t%X{:controller}t%X{:action}t%lt%m'
type: PatternFormatter
- type: DateFileOutputter
name: datefile_development
dirname: "<%= File.join(Rails.root, 'log') %>"
filename: "development.log"
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%pt%dt%X{:remote_ip}t%X{:user}t%X{:controller}t%X{:action}t%lt%m'
type: PatternFormatter
- type: DateFileOutputter
name: datefile_test
dirname: "<%= File.join(Rails.root, 'log') %>"
filename: "test.log"
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%pt%dt%X{:remote_ip}t%X{:user}t%X{:controller}t%X{:action}t%lt%m'
type: PatternFormatter
- type: StdoutOutputter
name: console_production
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%pt%dt%lt%m'
type: PatternFormatter
- type: StdoutOutputter
name: console_development
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%pt%dt%X{:remote_ip}t%X{:user}t%X{:controller}t%X{:action}t%lt%m'
type: PatternFormatter
- type: StdoutOutputter
name: console_test
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%pt%dt%X{:remote_ip}t%X{:user}t%X{:controller}t%X{:action}t%lt%m'
type: PatternFormatter
通过调试器运行rake任务后,我知道发生了什么。
Delayed::Worker
(delayed_job/lib/delayed/worker。(代码行248)正在通过日志记录器的add方法记录一条消息,如下所示:
logger.add level, "#{Time.now.strftime('%FT%T%z')}: #{text}" if logger
这对于Ruby的Logger
类是有效和正确的,参见Logger.html#method-i-add。但是,通过使用log4r,它解析为Log4r::Logger.add
(log4r/lib/log4r/logger)。(Rb第119行),它试图添加一个输出器。
我不知道为什么会发生这种情况,也不知道解决办法是什么。
你现在可以更新到delayed_jobs 4.0.1 gem,这将解决这个问题!
(有关此问题的原始评论,请参阅blog.mmlac.com)
问题是DelayedJob期望日志记录器为Rails:: logger,并调用log4r不支持的日志记录器。
在本文中,记录器变量被覆盖以使用Log4r:: logger,它不支持预期的.add调用。与Java不同,没有包来决定使用哪个记录器类,也没有slf4j将不同的记录器统一到一个标准接口。
这个问题没有简单的解决办法。一方面,您可以覆盖delayedJob的受影响部分。另一方面,您可以在delayedJob运行rails时防止加载log4r,即通过使用自定义环境:- 生产
- delayedJob
这也不能保证在任何地方都能工作(任何检查rails的env == "生产"的东西都会有问题)。
另一种方法是使用环境变量并在application.rb:
中检查它们。if (ENV["log4rlogger"] == "true") config.logger = Log4r::Logger["rails"]