log4j2_logger_bridge

This gem is a bridge between Apache log4j-2 and the Ruby logger gem.

It attempts to provide a single unified interface for both logging technologies, so that switching between either backend can be accomplished without much effort.

Below are usage examples for log4j2_logger_bridge, based on the gem's public API (notably Log4j2LoggerBridge.log_level=, the injected log/logger proxy, and Log4j2LoggerBridge.configure_destination for log file + rollover).

Install

Install the gem.

Gemfile

Specify the gem inclusion in your project's Ruby Gemfile.

gem 'log4j2_logger_bridge'

Require

Load the gem in a Ruby code module.

require 'log4j2_logger_bridge'

Quick-start

Gotta go fast.

1) Log to stdout

Example of simply logging to stdout with default configuration.

#! /usr/bin/env ruby
# frozen_string_literal: true

require 'log4j2_logger_bridge'

module Example
  module_function

  def main
    log.info("Hello from the bridge.")
    log.warn("This is a warning!")
    log.error("This is an error!")
  end
end

Example.main

For example:

$ bundle exec ruby scripts/example.rb
18:13:28,236 INFO  [Example] Hello from the bridge.
18:13:28,238 WARN  [Example] This is a warning!
18:13:28,238 ERROR [Example] This is an error!

Levels include: trace, debug, info, warn, error, fatal.

2) Categories (optional)

Categories are set automatically from the receiver/callsite, but you can also force one:

#!/usr/bin/env ruby
# frozen_string_literal: true

require 'log4j2_logger_bridge'

Log4j2LoggerBridge.with_category("MyCategory") do
  log.info("this line is tagged with MyCategory")
end

In a project with OptionParser

Say your project supports:

module MyProject
  def main(args = parse_arguments)
    # Your app code here.
  end
end

Here is a minimal end-to-end example that matches that pattern:

# frozen_string_literal: true

require 'optparse'
require 'log4j2_logger_bridge'

module MyProject
  class ArgumentsParser
    attr_reader :parser, :options

    def initialize(option_parser = OptionParser.new)
      @parser = option_parser
      @options = { log_level: 0 }
      @parser.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options]"
      @parser.on_tail("-v", "--verbose", "Increase verbosity") do
        @options[:log_level] = @options[:log_level] - 1
      end
    end
  end

  module_function

  def parse_arguments(arguments_parser = ArgumentsParser.new)
    arguments_parser.parser.parse!(ARGV)
    arguments_parser.options
  rescue OptionParser::ParseError => e
    abort e.message
  end

  def main(args = parse_arguments)
    Log4j2LoggerBridge.log_level = args[:log_level]

    log.info("server starting")
    log.debug("debug details here")
  end
end

MyProject.main

Notes:

  • The gem accepts log_level= as an Integer descending from 0 (0, -1, -2, ...) or as a Symbol/String (like :info, "debug").
  • With a -v flag decreasing the integer, you get more verbosity (for example 0 -> debug, -1 -> trace, etc.).

Advanced usage: configure rolling log files and log directory

The gem exposes a destination configuration entrypoint that creates the logs directory + log file if missing, and (on JRuby) wires Log4j2 rolling file behavior.

Example

Setting logs directory under your project, and rollover configuration.

# frozen_string_literal: true

require 'log4j2_logger_bridge'

Log4j2LoggerBridge.configure_destination do |c|
  c.project_dir_path = File.expand_path('..', __dir__) # repo/app root
  c.logs_dir_name = 'logs'
  c.app_name = 'my_project'
  c.log_file_name = 'my_project.log'

  # Rolling policy knobs:
  c.rollover_size = '250M'
  c.rollover_schedule = '0 0 0 * * ?' # cron-style schedule used by Log4j2
  # Optional: override pattern for rolled files
  c.rolling_file_name_template = 'my_project-%d{yyyy-MM-dd}.log.gz'
end

Log4j2LoggerBridge.log_level = :info
log.info("logging to file (and rolling per settings)")

How to think about it:

  • Call configure_destination once at process startup (before heavy logging).
  • Keep the config close to your app's boot path (for example, in config/boot.rb or similar).

Practical integration pattern

A common layout:

# lib/my_app/boot.rb
# frozen_string_literal: true

require 'log4j2_logger_bridge'

module MyApp
  module Boot
    module_function

    def setup_logging!(args)
      Log4j2LoggerBridge.configure_destination do |c|
        c.project_dir_path = args.fetch(:project_dir_path, Dir.pwd)
        c.logs_dir_name = args.fetch(:logs_dir_name, 'logs')
        c.app_name = args.fetch(:app_name, 'my_app')
        c.rollover_size = args.fetch(:rollover_size, '100M')
      end

      Log4j2LoggerBridge.log_level = args.fetch(:log_level, :info)
    end
  end
end

Then call MyApp::Boot.setup_logging!(args) from main right after parsing options.