Web に出てさまざまなサービスをクロールする小さな Ruby スクリプトに取り組んでいます。内部にいくつかのクラスを含むモジュールがあります。
module Crawler
class Runner
class Options
class Engine
end
これらのクラスのすべてのロガーで 1 つのロガーを共有したいと考えています。通常、これをモジュールの定数に入れて、次のように参照します。
Crawler::LOGGER.info("Hello, world")
問題は、出力先がわかるまでロガー インスタンスを作成できないことです。コマンド ラインからクローラーを開始し、その時点で、開発 (ログ出力は STDOUT に出力) または実稼働 (ログ出力はファイル、crawler.log に出力) で実行することを指定できます。
crawler --environment=production
Options
コマンドラインから渡されたオプションを解析するクラスがあります。その時点で初めて、正しい出力場所でロガーをインスタンス化する方法を知ることができます。
だから、私の質問は、どのように/どこにロガーオブジェクトを配置して、すべてのクラスがそれにアクセスできるようにするのですか?
作成するすべてのクラス インスタンスの各呼び出しにロガー インスタンスを渡すこともできますnew()
が、それを行うためのより優れた Ruby 的な方法が必要であることはわかっています。私は、class << self
他の魔法と共有するモジュール上の奇妙なクラス変数を想像しています。:)
もう少し詳しく:Runner
コマンド ライン オプションをOptions
クラスに渡すことですべてを開始し、いくつかのインスタンス変数を持つオブジェクトを取得します。
module Crawler
class Runner
def initialize(argv)
@options = Options.new(argv)
# feels like logger initialization should go here
# @options.log_output => STDOUT or string (log file name)
# @options.log_level => Logger::DEBUG or Logger::INFO
@engine = Engine.new()
end
def run
@engine.go
end
end
end
runner = Runner.new(ARGV)
runner.run
ロガー オブジェクトにアクセスできるようにするためのコードが必要ですEngine
(内部で初期化されるいくつかのクラスと共にEngine
)。ヘルプ!
すでにインスタンス化されている Logger の出力場所を動的に変更できれば (ログ レベルを変更する方法と同様に)、このすべてを回避できます。私はそれを STDOUT にインスタンス化してから、本番環境であればファイルに切り替えます。Ruby の $stdout グローバル変数を変更して、出力を STDOUT 以外の場所にリダイレクトするという提案をどこかで見ましたが、これはかなりハッキリしているようです。
ありがとう!