Получение ошибки при использовании log4r с отложенной работой
У меня есть рабочее приложение Rails 3.2 (Ruby 1.9.2p290 на Windows Server 2008 R2), которое использует отложенные задания для нескольких фоновых заданий. Я недавно заменил ведение журнала Rails по умолчанию на log4r, и он прекрасно работает для приложения Rails. Тем не менее, когда я запускаю rake jobs:work
задача я получаю сообщение об ошибке с нулевым выходом:
Стартовая работа рабочих граблей отменена! TypeError: Ожидаемый тип Outputter, полученный NilClass F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/log4r-1.1.10/lib/log4r/logger.rb:120: в `each' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/log4r-1.1.10/lib/log4r/logger.rb:120: в `add' F:/web-shared/Ruby192/lib/ruby /gems/1.9.1/gems/delayed_job-4.0.0/lib/delayed/worker.rb:248: в `скажем ' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/delayed_job-4.0.0/lib/delayed/worker.rb:147:in `start' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/delayed_job-4.0.0/lib/delayed/tasks.rb:9: в блоке `(2 уровня) в ' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/task.rb:240: в `call' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/task.rb:240: в` блоке в "F" /web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/task.rb:235: в "каждом" F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/task.rb:235:in `execute' F:/web-shared/Ruby192/lib/ruby / gems / 1.9.1 / камни / рек-10.2.2 / Библиотека / рейка / та sk.rb:179: в `block in invoke_with_call_chain' F:/web-shared/Ruby192/lib/ruby/1.9.1/monitor.rb:201: в`mon_synchronize' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/task.rb:172: в `invoke_with_call_chain' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/task.rb:165:in `invoke' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/application.rb:150:in invoke_task F: /web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/application.rb: 106: in `блок (2 уровня) на верхнем уровне ' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/application.rb:106: в` каждом' F: /web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/application.rb: 106: в блоке на верхнем уровне F: / web-shared / Ruby192 / lib / ruby / gems / 1.9.1 / gems / rake-10.2.2 / lib / rake / application.rb: 115: в `run_with_threads 'F: /web-shared/Ruby192/lib/ruby/gems/1.9.1 / gems / rake-10.2.2 / lib / rake / application.rb: 100: в `top_level ' F:/web-shared/Ruby192/lib/ruby /gems/1.9.1/gems/rake-10.2.2/lib/rake/application.rb:78: в `block in run' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/application.rb:176:in `standard_exception_handling' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/lib/rake/application.rb:75: в `run' F:/web-shared/Ruby192/lib/ruby/gems/1.9.1/gems/rake-10.2.2/bin/rake:33: в`' F:/web-shared/Ruby192/bin/rake:19: в `load' F:/web-shared/Ruby192/bin/rake:19:in `' Задачи: TOP => работа: работа
Кто-нибудь еще успешно использует log4r с отложенной работой? Я мог бы использовать несколько указателей; Не удалось найти что-либо с помощью поиска Google или 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: '%p\t%d\t%X{:remote_ip}\t%X{:user}\t%X{:controller}\t%X{:action}\t%l\t%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: '%p\t%d\t%X{:remote_ip}\t%X{:user}\t%X{:controller}\t%X{:action}\t%l\t%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: '%p\t%d\t%X{:remote_ip}\t%X{:user}\t%X{:controller}\t%X{:action}\t%l\t%m'
type: PatternFormatter
- type: StdoutOutputter
name: console_production
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%p\t%d\t%l\t%m'
type: PatternFormatter
- type: StdoutOutputter
name: console_development
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%p\t%d\t%X{:remote_ip}\t%X{:user}\t%X{:controller}\t%X{:action}\t%l\t%m'
type: PatternFormatter
- type: StdoutOutputter
name: console_test
formatter:
date_pattern: '%H:%M:%S.%L'
pattern: '%p\t%d\t%X{:remote_ip}\t%X{:user}\t%X{:controller}\t%X{:action}\t%l\t%m'
type: PatternFormatter
ОБНОВИТЬ
Что ж, после запуска граблей через отладчик я понял, что происходит.
Delayed::Worker
( delayed_job / lib / delayed / worker.rb строка 248) записывает сообщение с помощью метода add в логгере так:
logger.add level, "#{Time.now.strftime('%FT%T%z')}: #{text}" if logger
Это верно и правильно для Ruby's Logger
класс, см. Logger.html # method-i-add. Однако, используя log4r, он разрешает Log4r::Logger.add
( log4r / lib / log4r / logger.rb строка 119), которая пытается добавить выходной файл.
Я не уверен, почему это происходит, или какое решение будет.
2 ответа
(см. blog.mmlac.com для оригинального комментария к этой проблеме.)
Проблема заключается в том, что DelayedJob ожидает, что логгером будет Rails::Logger, и делает вызовы, которые log4r не поддерживает.
В этой статье переменная logger перезаписывается для использования Log4r::Logger, который не поддерживает вызов.add, как предполагалось. В отличие от Java, нет пакетов для определения, какой класс logger использовать, или slf4j, который объединяет различные регистраторы в стандартный интерфейс.
Простого решения этой проблемы не существует. С одной стороны, вы можете переписать затронутые части delayedJob. С другой стороны, вы можете предотвратить загрузку log4r, когда delayedJob запускает рельсы, т. Е. Используя пользовательскую среду:
- развитие
- производство
- delayedJob
Это также не гарантируется для работы везде (все, что проверяет рельсы env == "production", будет иметь проблемы).
Другой способ - использовать переменные окружения и проверить их в application.rb:
if (ENV["log4rlogger"] == "true") config.logger = Log4r::Logger["rails"]
Теперь вы можете обновить до гема delayed_jobs 4.0.1, и это решит эту проблему!