Module: RJack::SLF4J

Defined in:
lib/rjack-slf4j.rb,
lib/rjack-slf4j/mdc.rb,
lib/rjack-slf4j/base.rb

Overview

Wrapper and core Logger compatible adapter for the SLF4J logging interface.

Usage

require 'rjack-slf4j'

log = RJack::SLF4J[ "my.app.logger" ]
log.info "Hello World!"

Adapters

An output adapter must be required before the first log call. All of the following output adapters are available via require from the slf4j gem:

require 'rjack-slf4j/jcl'       # Output to Jakarta Commons Logging
require 'rjack-slf4j/jdk14'     # JDK java.util.logging (JUL)
require 'rjack-slf4j/log4j12'   # Log4j (provided elsewhere)
require 'rjack-slf4j/nop'       # NOP null logger (provided)
require 'rjack-slf4j/simple'    # Simple logger (provided)

The rjack-logback gem may also be be used as the output adapter:

require 'rjack-logback'

The first loaded output adapter wins (as with multiple adapters on the classpath). A warning will be logged to "slf4j" if an attempt is made to require a second output adapter.

The following input adapters will intercept JCL, java.util.logging (JUL), or log4j log output and direct it through SLF4J:

require 'rjack-slf4j/jcl-over-slf4j'   # Route Jakarta Commons Logging to SLF4J
require 'rjack-slf4j/log4j-over-slf4j' # Log4j to SLF4J

require 'rjack-slf4j/jul-to-slf4j'     # JDK java.util.logging (JUL) to SLF4J
RJack::SLF4J::JUL.replace_root_handlers # Special case setup for JUL

Multiple input adapters may be require'd. However, a RuntimeError will be raised in the attempt to require both an output adapter and input adapter from/to the same interface, for example 'rjack-slf4j/jcl-over-slf4j' and 'rjack-slf4j/jcl', which would otherwise cause a circular logging loop (and stack overflow.)

Adapter names match the corresponding SLF4J jars.

Defined Under Namespace

Modules: JUL, MDC Classes: Logger

Constant Summary collapse

LEVELS =

SLF4J severity levels

%w{ trace debug info warn error }
SLF4J_VERSION =

SLF4J-java version

'1.7.25'
VERSION =

SLF4J gem version

SLF4J_VERSION + '.0'
SLF4J_DIR =

:nodoc:

File.dirname(__FILE__)
ADAPTERS =

:input :output (jar with slf4j- prefix)

[ [ "jul-to-slf4j",     "jdk14"   ],
[ "jcl-over-slf4j",   "jcl"     ],
[ "log4j-over-slf4j", "log4j12" ],
[ nil,                "nop"     ],
[ nil,                "simple"  ] ]
@@api_loader =
org.slf4j.ILoggerFactory.java_class.class_loader
@@loaded =
{}
@@output_name =
nil
@@ruby_ex_format =
"%s %s: %s\n".freeze

Class Method Summary collapse

Class Method Details

.[](name) ⇒ Object

Synonym for Logger.new( name )



352
353
354
# File 'lib/rjack-slf4j.rb', line 352

def self.[]( name )
  Logger.new( name )
end

.linked_factory ⇒ Object

The ILoggerFactory instance if an output adapter has been loaded



357
358
359
# File 'lib/rjack-slf4j.rb', line 357

def self.linked_factory
   org.slf4j.LoggerFactory.getILoggerFactory
end

.logger(name = self.class.name) ⇒ Object

Get Logger by name



346
347
348
# File 'lib/rjack-slf4j.rb', line 346

def logger( name = self.class.name )
  Logger.new( name )
end

.output_name ⇒ Object

Output adapter name if one has been added, or nil.



129
130
131
# File 'lib/rjack-slf4j.rb', line 129

def self.output_name
  @@output_name
end

.require_adapter(name) ⇒ Object

Require an adapter by name (add the jar to classpath) This is normally done via require 'slf4j/name'



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/rjack-slf4j.rb', line 82

def self.require_adapter( name )
  row = ADAPTERS.assoc( name )
  if row
    name,ban = row
    output = false
  else
    row = ADAPTERS.rassoc( name )
    ban,name = row
    output = true
  end

  if @@loaded[ ban ]
    raise "Illegal attempt to load '#{name}' when '#{ban}' is loaded."
  end

  if output
    if ! @@output_name.nil? && name != @@output_name
      logger("slf4j").warn do
        "Ignoring attempt to load #{name} after #{@@output_name} already loaded."
      end
      return
    end
    if java.lang.Thread::current_thread.context_class_loader != @@api_loader
      $stderr.puts( "WARNING: Attempting to load #{name} in child class" +
                    " loader of slf4j-api.jar loader." )
    end
    require_jar( 'slf4j-' + name )
    @@output_name = name
  else
    require_jar( name )
  end

  @@loaded[ name ] = true
end

.require_jar(name) ⇒ Object

:nodoc:



117
118
119
# File 'lib/rjack-slf4j.rb', line 117

def self.require_jar( name ) # :nodoc:
  require File.join( SLF4J_DIR, "#{name}-#{ SLF4J_VERSION }.jar" )
end

.ruby_ex_format ⇒ Object

A (sprintf) format string to use when synthesizing a log message from a prefix message (msg) (i.e. "Exception:") and ruby exception (ex) using [ msg, ex.class.name, ex.cause ]. Since ruby exceptions aren't instances of java Throwable, they can't be passed directly. This can be globally set to match the formatting of the output adapter (i.e. for java exceptions), preferably in the same place it is required and configured.



140
141
142
# File 'lib/rjack-slf4j.rb', line 140

def self.ruby_ex_format
  @@ruby_ex_format
end

.ruby_ex_format=(f) ⇒ Object



144
145
146
# File 'lib/rjack-slf4j.rb', line 144

def self.ruby_ex_format=( f )
  @@ruby_ex_format = f.dup.freeze
end

.to_log_name(clz) ⇒ Object Also known as: ruby_to_java_logger_name

Return a java style class name, suitable as a logger name, from the given ruby class or module, i.e:

to_log_name( Foo::Bar::Baz ) --> "foo.bar.Baz"


156
157
158
# File 'lib/rjack-slf4j.rb', line 156

def self.to_log_name( clz )
  clz.name.gsub( /::/, '.' ).gsub( /([^\.]+)\./ ) { |m| m.downcase }
end