Logger (Standard Library)

Ruby標準ライブラリのロギング機能。外部依存関係なしで基本的なロギング機能を提供。ログレベル、ローテーション、カスタムフォーマッターをサポート。シンプルなRubyアプリケーションやスクリプトに適している。

GitHub概要

ruby/logger

simple logging utility

スター134
ウォッチ34
フォーク69
作成日:2018年5月17日
言語:Ruby
ライセンス:Other

トピックス

hacktoberfestloggerruby

スター履歴

ruby/logger Star History
データ取得日時: 2025/10/22 10:04

logger

loggerは、Ruby標準ライブラリに含まれるロギングユーティリティです。シンプルながら洗練された機能を提供し、メッセージの重要度に応じたレベル管理、ログローテーション、カスタマイズ可能なフォーマッターなど、本格的なロギングに必要な機能を備えています。

主な特徴

  • 5段階のログレベル - DEBUG、INFO、WARN、ERROR、FATAL
  • 自動ログローテーション - サイズまたは期間ベースのローテーション
  • カスタマイズ可能なフォーマッター - 出力形式を柔軟に設定
  • スレッドセーフ - マルチスレッド環境で安全に使用可能
  • 標準ライブラリ - 追加のGemインストール不要

インストール

Rubyの標準ライブラリのため、追加のインストールは不要です。

require 'logger'

基本的な使い方

シンプルな例

require 'logger'

# 標準出力へのロガーを作成
logger = Logger.new(STDOUT)

# ログレベルを設定(デフォルトはDEBUG)
logger.level = Logger::INFO

# 各レベルでメッセージを記録
logger.debug("デバッグメッセージ")  # 表示されない
logger.info("アプリケーションが起動しました")
logger.warn("警告: メモリ使用量が高くなっています")
logger.error("エラーが発生しました")
logger.fatal("致命的なエラー: システムを停止します")

# ブロック構文も使用可能
logger.info { "処理完了: #{Time.now}" }

ログレベル

# 利用可能なログレベル(重要度順)
Logger::FATAL  # 致命的なエラー
Logger::ERROR  # エラー
Logger::WARN   # 警告
Logger::INFO   # 情報
Logger::DEBUG  # デバッグ
Logger::UNKNOWN # 不明なレベル

# レベルの設定方法
logger.level = Logger::WARN  # WARN以上のみ記録

# 文字列でも設定可能
logger.level = "INFO"

# 動的なレベル変更
if ENV['DEBUG']
  logger.level = Logger::DEBUG
else
  logger.level = Logger::INFO
end

ファイルへのロギング

基本的なファイル出力

# ファイルへのロガーを作成
logger = Logger.new('application.log')

# 複数の出力先を管理
file_logger = Logger.new('app.log')
stdout_logger = Logger.new(STDOUT)

class MultiLogger
  def initialize(*loggers)
    @loggers = loggers
  end
  
  [:debug, :info, :warn, :error, :fatal].each do |level|
    define_method(level) do |message = nil, &block|
      @loggers.each do |logger|
        if block_given?
          logger.send(level, &block)
        else
          logger.send(level, message)
        end
      end
    end
  end
end

# 使用例
multi_logger = MultiLogger.new(file_logger, stdout_logger)
multi_logger.info("両方のロガーに記録されます")

ログローテーション

サイズベースのローテーション

# 10MBを超えたらローテーション、最大5ファイル保持
logger = Logger.new('app.log', 5, 10 * 1024 * 1024)

# 1MBごとにローテーション、10ファイル保持
logger = Logger.new('small.log', 10, 1024 * 1024)

期間ベースのローテーション

# 毎日ローテーション
logger = Logger.new('daily.log', 'daily')

# 毎週ローテーション
logger = Logger.new('weekly.log', 'weekly')

# 毎月ローテーション
logger = Logger.new('monthly.log', 'monthly')

# カスタム期間(秒単位)
logger = Logger.new('custom.log', 3600)  # 1時間ごと

フォーマッターのカスタマイズ

基本的なフォーマット変更

# 日時フォーマットの変更
logger.datetime_format = '%Y-%m-%d %H:%M:%S'

# カスタムフォーマッター
logger.formatter = proc do |severity, datetime, progname, msg|
  "[#{datetime}] #{severity}: #{msg}\n"
end

# より詳細なフォーマッター
logger.formatter = proc do |severity, datetime, progname, msg|
  date_format = datetime.strftime('%Y-%m-%d %H:%M:%S.%L')
  if progname
    "[#{date_format}] #{severity.ljust(5)} (#{progname}): #{msg}\n"
  else
    "[#{date_format}] #{severity.ljust(5)}: #{msg}\n"
  end
end

構造化ログ(JSON形式)

require 'json'
require 'logger'

class JsonFormatter
  def call(severity, time, progname, msg)
    {
      timestamp: time.iso8601,
      level: severity,
      program: progname,
      message: msg,
      pid: Process.pid,
      hostname: Socket.gethostname
    }.to_json + "\n"
  end
end

logger = Logger.new(STDOUT)
logger.formatter = JsonFormatter.new

logger.info("ユーザーがログインしました")
# => {"timestamp":"2024-01-15T10:30:45+09:00","level":"INFO","program":null,"message":"ユーザーがログインしました","pid":12345,"hostname":"server01"}

高度な使い方

プログラム名の設定

logger = Logger.new(STDOUT)
logger.progname = 'MyApp'

logger.info("起動しました")
# => I, [2024-01-15T10:30:45.123456 #12345]  INFO -- MyApp: 起動しました

# 一時的なプログラム名の変更
logger.info('UserAuth') { 'ログイン成功' }
# => I, [2024-01-15T10:30:45.123456 #12345]  INFO -- UserAuth: ログイン成功

エラーとスタックトレースの記録

begin
  # 何かエラーが発生する処理
  raise StandardError, "何かが壊れました"
rescue => e
  logger.error("処理中にエラーが発生しました: #{e.message}")
  logger.error(e.backtrace.join("\n"))
  
  # または1行で
  logger.error { "エラー: #{e.message}\n#{e.backtrace.join("\n")}" }
end

条件付きロギング

class ConditionalLogger
  def initialize(logger, condition)
    @logger = logger
    @condition = condition
  end
  
  [:debug, :info, :warn, :error, :fatal].each do |level|
    define_method(level) do |message = nil, &block|
      return unless @condition.call
      
      if block_given?
        @logger.send(level, &block)
      else
        @logger.send(level, message)
      end
    end
  end
end

# 開発環境でのみログを出力
dev_logger = ConditionalLogger.new(
  Logger.new(STDOUT),
  -> { ENV['RACK_ENV'] == 'development' }
)

dev_logger.debug("この情報は開発環境でのみ表示されます")

パフォーマンスロギング

class PerformanceLogger
  def initialize(logger)
    @logger = logger
  end
  
  def measure(operation_name)
    start_time = Time.now
    result = nil
    
    begin
      result = yield
    rescue => e
      @logger.error("#{operation_name} failed: #{e.message}")
      raise
    ensure
      duration = Time.now - start_time
      @logger.info("#{operation_name} completed in #{(duration * 1000).round(2)}ms")
    end
    
    result
  end
end

perf_logger = PerformanceLogger.new(Logger.new(STDOUT))

perf_logger.measure("データベースクエリ") do
  # 重い処理
  sleep(0.1)
  "結果"
end
# => I, [...] INFO -- : データベースクエリ completed in 100.12ms

Railsでの使用

Rails.logger

# Railsではデフォルトでloggerが設定されている
Rails.logger.info "Railsアプリケーションからのログ"

# コントローラーやモデルでの使用
class UsersController < ApplicationController
  def create
    logger.info "新規ユーザー作成開始: #{params[:email]}"
    
    @user = User.new(user_params)
    
    if @user.save
      logger.info "ユーザー作成成功: ID=#{@user.id}"
      redirect_to @user
    else
      logger.error "ユーザー作成失敗: #{@user.errors.full_messages.join(', ')}"
      render :new
    end
  end
end

タグ付きロギング

# config/application.rb
config.logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))

# 使用例
class ApplicationController < ActionController::Base
  around_action :add_request_tags
  
  private
  
  def add_request_tags
    logger.tagged(request.uuid, current_user&.id) do
      yield
    end
  end
end

# ログ出力例
# [a1b2c3d4-e5f6-7890] [12345] Processing by UsersController#show as HTML

ベストプラクティス

1. 適切なログレベルの使用

# 良い例
logger.debug { "SQLクエリ: #{sql}" }  # 開発時の詳細情報
logger.info "ユーザー#{user_id}がログインしました"  # 通常の動作情報
logger.warn "API呼び出しがタイムアウトしました。リトライします"  # 警告
logger.error "支払い処理に失敗しました: #{error.message}"  # エラー
logger.fatal "データベース接続が切断されました"  # 致命的なエラー

2. 環境別設定

class AppLogger
  def self.create
    logger = Logger.new(log_destination)
    logger.level = log_level
    logger.formatter = formatter
    logger
  end
  
  private
  
  def self.log_destination
    case ENV['RACK_ENV']
    when 'production'
      'log/production.log'
    when 'test'
      'log/test.log'
    else
      STDOUT
    end
  end
  
  def self.log_level
    case ENV['RACK_ENV']
    when 'production'
      Logger::INFO
    when 'test'
      Logger::ERROR
    else
      Logger::DEBUG
    end
  end
  
  def self.formatter
    if ENV['RACK_ENV'] == 'production'
      JsonFormatter.new
    else
      Logger::Formatter.new
    end
  end
end

3. センシティブな情報の除外

class SafeLogger
  def initialize(logger)
    @logger = logger
    @filters = [/password/i, /token/i, /secret/i]
  end
  
  def info(message)
    @logger.info(filter_message(message))
  end
  
  private
  
  def filter_message(message)
    filtered = message.dup
    @filters.each do |pattern|
      filtered.gsub!(pattern, '[FILTERED]')
    end
    filtered
  end
end

他のロギングライブラリとの比較

semantic_logger

より高度な機能を提供する代替ライブラリ:

# semantic_loggerの特徴
# - 構造化ログのネイティブサポート
# - 高パフォーマンス
# - 豊富な出力先オプション

require 'semantic_logger'

SemanticLogger.add_appender(io: STDOUT, formatter: :json)
logger = SemanticLogger['MyApp']

logger.info('ユーザー登録', user_id: 123, email: '[email protected]')

選択の指針

  • logger - シンプルで標準的なロギングが必要な場合
  • semantic_logger - 高度な構造化ログや複数の出力先が必要な場合
  • Rails.logger - Railsアプリケーションの場合

まとめ

Ruby標準のloggerライブラリは、シンプルながら十分な機能を持つロギングソリューションです。標準ライブラリとして提供されているため追加の依存関係なしに使用でき、基本的なロギング要件を満たします。より高度な要件がある場合は、semantic_loggerなどの代替ライブラリを検討することもできますが、多くのアプリケーションではloggerで十分対応可能です。