RubyにはLoggerクラスが組み込みライブラリとして提供されていて、ログをいい感じに出力することができます。
しかし、複数のロガーに対してログを出力することはLoggerクラスだけでは出来ません。RailsであればActiveSupport::Logger.broadcast
が使えるそうですが、ピュアなRubyでも同じことがやりたいです。
利用シーンとしてはライブラリや自作gemを想定しています。
またピュアなRubyだけで実装することで配布時のファイルサイズを削減することが可能です。
できたもの
ということで...複数ロガーを管理するクラスを定義しました。
ただロガーの一覧を配列で管理しつつ、全てのロガーのメソッドを順に呼び出すという作りになっています。
呼び出し順は重要ではないため、この方法を採用しました。
require 'logger' class MultiLogger def initialize file = File.open('application.log', 'a') @loggers = [ Logger.new($stdout), Logger.new(file, 'daily'), ] end [:debug, :info, :warn, :error, :fatal, :unknown].each do |level| define_method(level) do |progname| @loggers.each { |logger| logger.send(level, progname) } end end end
1つ1つメソッドを定義するのが嫌だったので、ログレベルの一覧からdefine_method
を使って動的に定義するようにしました。内部ではLoggerクラスに定義された同名のメソッドを呼び出しています。
使い方
インスタンスを作成後、Loggerクラスと同じようにログを出力することが可能です。
loggers = MultiLogger.new loggers.debug(":::debug") loggers.info(":::info") loggers.warn(":::warn") loggers.error(":::error") loggers.fatal(":::fatal") loggers.unknown(":::unknown") # D, [2023-08-13T12:51:43.457365 #61639] DEBUG -- : :::debug # I, [2023-08-13T12:51:43.457486 #61639] INFO -- : :::info # :
D, [2023-08-13T12:52:39.254382 #61724] DEBUG -- : :::debug I, [2023-08-13T12:52:39.254424 #61724] INFO -- : :::info :
標準出力とファイルへの出力の両方に成功しました。
他にロガーを追加したければ@loggers
に別途、ロガーを追加すればOKです。
現時点ではあえてリッチな実装はしていないですが、途中でロガーを追加・削除したいなどの要望があれば、ロガーの一覧を動的に管理する実装をするか、別クラスを定義するれば良いかなと思います。
少しでも「ええな〜」と思ったらはてなスター・はてなブックマーク・シェアを頂けると励みになります。