おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

ci_loggerのv0.9.0をリリースしました

Release v0.9.0 · willnet/ci_logger

次の二点の変更が入っています。

  • Rails6.0以上のサポートを終了して、Ruby3.3のサポートを追加しました
  • Rails7.1で追加されたActiveSupport::BroadcastLoggerの対応を入れました

ActiveSupport::BroadcastLoggerとは?

Add a public API for broadcasting logs by Edouard-chin · Pull Request #48615 · rails/rails で入った、Railsで複数のLoggerを扱いやすくするための仕組みです。

Rails7.0までのRails.loggerのデフォルトはActiveSupport::Loggerでした。このLoggerには一つのLoggerに書き込んだときに複数の出力先を設定できる機能があります。例えば端末でrails sすると端末とlog/development.rbの両方に同じ内容が出力されるはずです。これはこの機能を利用して実現されていました。

しかし、複数の出力を設定するためには次のようにActiveSupport::Logger.broadcastで作成したModuleをextendする必要がありました。これはだいぶおまじない感が強いですね…。しかもこれはprivate APIでした。

console = ActiveSupport::Logger.new(STDERR)
Rails.logger.extend ActiveSupport::Logger.broadcast console

これをもっとスッキリした形に変更してpublicにしたのがActiveSupport::BroadcastLoggerです。次のような書き方で使います。ActiveSupport::BroadcastLoggerが出力先のLoggerを持つという、だいぶ直感的な構造になっています。

stdout_logger = Logger.new(STDOUT)
file_logger = Logger.new("development.log")
broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger, file_logger)

broadcast.info("Hello!") # The "Hello!" message is written on STDOUT and in the log file.

ci_loggerの対応

ci_loggerはLoggerをラップして、テストに失敗したときだけ出力するLoggerを作るライブラリです。Loggerをラップしているという点ではActiveSupport::BroadcastLoggerと同じですね😃。ActiveSupport::BroadcastLoggerをCiLoggerでラップしても普通に動くのですが、今回ActiveSupport::BroadcastLoggerが持つLoggerを個別にラップする方式に変更しました。

これにより、成功したログも失敗したログも全部出力しつつ、別途失敗したログだけを出力するぞこともできるようになります。

# config/environments/test.rb

config.after_initialize do
  all_logger = Logger.new("all.log")
  Rails.logger.broadcast_to(all_logger)
end

また、特定のgemの型検査でRails.loggerがActiveSupport::BroadcastLoggerのインスタンスであることを期待しているものがあって*1CiLoggerを導入する障害になっていたのも解決しています。

どうぞご利用ください。