log4jruby 2.0.1-java → 3.0.0.rc1-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8355e0417b5b8fa90580b2b5d47380ed4c70d634
4
- data.tar.gz: 1a981572aafc5d7350c2aa0c2975bcec80a39976
2
+ SHA256:
3
+ metadata.gz: 63ae3e7cb5a390af7767e58ce30270c32cc3c770ba877ce0932627e3efab1607
4
+ data.tar.gz: d80186abc03df7b0a2b10befcdda3084eef5cffeb4e1960ce957930d6be1e850
5
5
  SHA512:
6
- metadata.gz: 2100d066da86f23d7a5a7d818d5e46bbb6811630d853def7c869acb0930e2c23e913039e8b5e63a56aba7fa0683c21d8f97f3310b788988a151dceb7b9af9442
7
- data.tar.gz: abe6cbfceb161761850e867c5f9df6d339f7e3807ba9bb104822fca7db2b380c9fdd147c22f713e1678b6a1c919936ba5b04f9ce71980e1da7154b1f0c61be85
6
+ metadata.gz: bbc3e978c3d27fe325b135ff988b063f928daadec1a3608d8cfd891766ab2eefa3e0dc08c60ae3dae9835760236fbcb6e84152bcc2cef8faebfb7d8f2b407bf9
7
+ data.tar.gz: 61d52687aa0b3d1658fb29c0c543e0e7ba45789799ebaabc640fa4f2570ea1d395972c856118bfb2e34e45d3c4780dd3e1e45285c609ae7c8c26455a4a9595ad
data/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # log4jruby Changelog
2
2
 
3
+ ## v3.0.0.rc1
4
+
5
+ * JRuby 9.3.x/Ruby 2.6 support - Ruby >= 2.6.8 now required
6
+ * Updated for Log4j2
7
+ Note:
8
+ > In Log4j 1.x the Logger Hierarchy was maintained through a relationship between Loggers.
9
+ In Log4j 2 this relationship no longer exists. Instead, the hierarchy is maintained in the
10
+ relationship between LoggerConfig objects.
11
+ from the [Log4j 2 Architecture page](https://logging.apache.org/log4j/2.x/manual/architecture.html)
12
+ * Formatters and logging output
13
+ * Consistent treatment for Ruby and Java exceptions - Previously, ruby exception backtraces were
14
+ not passed directly to Log4j. Instead a backtrace string was generated and included in the exception
15
+ message. JRuby now handles mapping Ruby exceptions/errors to Java exceptions that can be
16
+ passed directly as the `Throwable` parameter to Log4j.
17
+ * Formatter parity with the standard Ruby Logger - Custom formatters
18
+ (see [formatter in the
19
+ Ruby Logger docs](https://ruby-doc.org/stdlib-2.7.0/libdoc/logger/rdoc/Logger.html)
20
+ now receive the same arguments from Log4Jruby as they would from the standard Ruby Logger
21
+ given the same logging invocation.
22
+ * Default formatter - The [standard Ruby Logger](https://ruby-doc.org/stdlib-2.7.0/libdoc/logger/rdoc/Logger.html)
23
+ uses a default formatter that outputs backtraces (without nested causes). Log4jruby now uses
24
+ a default formatter that outputs `progname` and `msg` only. Severity and timestamp are output
25
+ according to your Log4j configuration. E.g. [PatternLayout](https://logging.apache.org/log4j/2.x/manual/layouts.html)
26
+ * The output of the `formatter` is passed as the `message` parameter of the
27
+ [Log4j log methods](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Category.html)
28
+ * Nested ruby exceptions are now handled - E.g. The backtrace output from `logger.error { ruby_error_with_nested_causes }` will
29
+ include nested causes for both Ruby and Java exceptions.
30
+ * Log4jruby no longer utilizes deprecated [JRuby Persistence](https://github.com/jruby/jruby/wiki/Persistence)
31
+ * Development
32
+ * Rubocop introduced and violations squashed
33
+ * Mavenized log4j development dependency, added `dev:java_deps` Rake task, and removed bundled log4j jar
34
+
3
35
  ## v2.0.1
4
36
 
5
37
  * JRuby 9K compatibility - https://github.com/lenny/log4jruby/issues/14
data/README.md CHANGED
@@ -1,94 +1,176 @@
1
+ # Log4jruby
1
2
 
3
+ `Log4jruby` provides an interface mostly compatible with the standard ruby [Logger](http://ruby-doc.org/core/classes/Logger.html) but backed by [Log4j 2](https://logging.apache.org/log4j/2.x/).
4
+ This makes the granular log output configuration, stacktrace output, and other facilities of `log4j` available to Java and Ruby code alike. For projects that extend/integrate Java already dependent on `log4j`, it allows log configuration for Java and Ruby code in one spot.
2
5
 
3
- # Log4jruby
6
+ * Automatic stacktrace output (including nested causes) for logged Java and Ruby exceptions
7
+ * Configure Java and Ruby logging together (e.g a single `log4j2.properties` file) and gain `log4j` features such as runtime output targets for Ruby code.
8
+ * Ability to configure logging per distinct logger name (typically a class)
9
+ * Supports inclusion of filename, line number, and method name in log messages via [ThreadContext](https://logging.apache.org/log4j/2.x/manual/thread-context.html). Note: `tracing` must be enabled.
10
+ * High level support for class based logging via the `enable_logger` macro.
11
+ * Compatible with the `Rails` logging.
4
12
 
5
- * https://github.com/lenny/log4jruby
6
13
 
7
- ## Description:
14
+ ## Usage and examples
8
15
 
9
- Log4jruby is a thin wrapper around the {Log4j Logger}[http://logging.apache.org/log4j/1.2/apidocs/index.html].
10
- It is geared more toward those who are using JRuby to integrate with and build on top of Java code that uses Log4j.
11
- The ```Log4jruby::Logger``` provides an interface much like the standard ruby [Logger](http://ruby-doc.org/core/classes/Logger.html).
12
- Logging is configured via traditional Log4j methods.
16
+ Enable class level logging via `enable_logger`
13
17
 
14
- The primary use case (i.e., mine) for this library is that you are already up and running with Log4j and now you want
15
- to use it for your Ruby code too. There is not much help here for configuration. In our environment, we deploy Rails
16
- apps that call and extend Java code into Tomcat as WARs and use a log4j.properties to configure. For the most part,
17
- all there is to using log4jruby is making sure the log4j jar is <tt>required</tt> and that Log4j is at least minimally
18
- configured (e.g., log4j.properties in the CLASSPATH). The examples should give you the idea.
18
+ ```ruby
19
+ require 'log4jruby'
19
20
 
20
- ### Features
21
+ class MyClass
22
+ enable_logger
21
23
 
22
- * Filename, line number, and method name are available (if tracing is on) to your appender layout via [MDC](http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html).
23
- * Exceptions can be logged directly and are output with backtraces. Java Exceptions (i.e., NativeExceptions)
24
- are logged with full java backtrace(including nested exceptions).
25
- * Logging config for your ruby code can be added to your existing configuration. Ruby logger names are mapped to dot separated names prefixed with <tt>.jruby</tt>
24
+ class << self
25
+ def my_class_method
26
+ logger.info("hello from class method")
27
+ end
28
+ end
26
29
 
27
- log4j.appender.Ruby=org.apache.log4j.ConsoleAppender
28
- log4j.appender.Ruby.layout=org.apache.log4j.PatternLayout
29
- log4j.appender.Ruby.layout.ConversionPattern=%5p %.50X{fileName} %X{methodName}:%X{lineNumber} - %m%n
30
+ def my_method
31
+ logger.info("hello from instance method")
32
+ end
33
+ end
34
+ ```
30
35
 
31
- log4j.logger.jruby=info,Ruby
32
- log4j.logger.jruby.MyClass=debug
36
+ Custom logger name
33
37
 
34
- ### Configuration
38
+ ```ruby
39
+ logger = Log4jruby::Logger.get('my.logger')
40
+ logger.debug('something')
41
+ ```
35
42
 
36
- As noted above, configuring log4j is left to the client. **You must load and configure log4j before requiring log4jruby**.
37
- There are multiple ways to do so.
38
- In our environment, we deploy Rails apps that call and extend Java code to Tomcat as WAR files.
39
- We provision our app servers with ```log4j.jar``` and a ```log4j.properties``` file in in ```$TOMCAT_HOME/lib```.
40
- You may also add log4j.jar and path to config file into CLASSPATH via environment variables, JAVA_OPTS, JAVA_OPTS, etc...
41
- Or add them into ```$CLASSPATH``` at runtime before loading log4jruby. See [examples/setup.rb](examples/setup.rb).
42
-
43
- Note: If you're using bundler, you can specify ```gem 'log4jruby', require: false``` in your Gemfile to delay loading the gem too early.
43
+ Log4jruby logger names are prefixed with `.jruby`.
44
+
45
+ e.g. `log4j2.properties`
46
+
47
+ See [examples/log4j2.properties](examples/log4j2.properties) for complete example
48
+
49
+ ```ini
50
+ ...
51
+ # JRuby logger
52
+ logger.jruby.name = jruby
53
+ logger.jruby.level = debug
54
+ logger.jruby.additivity = false
55
+ logger.jruby.appenderRef.stdout.ref = JRuby
56
+ ```
57
+
58
+ Inclusion of filename, line number, and method name in log messages via [ThreadContext](https://logging.apache.org/log4j/2.x/manual/thread-context.html)
59
+
60
+ e.g.
61
+
62
+ ```ini
63
+ appender.jruby.layout.pattern = %d %5p %c %X{methodName}:%X{lineNumber} %m%throwable%n
64
+ ```
65
+
66
+ enable tracing globally
67
+
68
+ ```
69
+ Log4jruby::Logger.root.tracing = true
70
+ ```
71
+
72
+ or for specific logger
73
+
74
+ ```
75
+ Log4jruby::Logger.get('MyClass', tracing: true)
76
+ ```
77
+
78
+ produces log statements like:
79
+
80
+ ```
81
+ 2022-08-12 17:36:05,819 DEBUG jruby.MyClass foo:20 -- : hello from foo
82
+ ```
83
+
84
+ Exceptions are logged with backtraces
85
+
86
+ ```bash
87
+ > ruby ./examples/nested_ruby_exceptions.rb
88
+ 2022-08-25 19:50:47,050 ERROR jruby.test <main>:31 -- : raised from foo org.jruby.exceptions.RuntimeError: (RuntimeError) raised from foo
89
+ at $_dot_.examples.nested_ruby_exceptions.foo(./examples/nested_ruby_exceptions.rb:15)
90
+ at $_dot_.examples.nested_ruby_exceptions.<main>(./examples/nested_ruby_exceptions.rb:29)
91
+ Caused by: org.jruby.exceptions.RuntimeError: (RuntimeError) raised from bar
92
+ at $_dot_.examples.nested_ruby_exceptions.bar(./examples/nested_ruby_exceptions.rb:21)
93
+ at $_dot_.examples.nested_ruby_exceptions.foo(./examples/nested_ruby_exceptions.rb:13)
94
+ ... 1 more
95
+ Caused by: org.jruby.exceptions.RuntimeError: (RuntimeError) raised from baz
96
+ at $_dot_.examples.nested_ruby_exceptions.baz(./examples/nested_ruby_exceptions.rb:25)
97
+ at $_dot_.examples.nested_ruby_exceptions.bar(./examples/nested_ruby_exceptions.rb:19)
98
+ ... 2 more
99
+
100
+
101
+ ```
102
+
103
+ ```
104
+ logger.warn(exception)
105
+ ```
106
+
107
+ ```
108
+ logger.warn { exception }
109
+ ```
110
+
111
+ ```
112
+ logger.error(msg) { exception)
113
+ ```
114
+
115
+ See additional examples in [log4jruby/examples](examples).
116
+
117
+
118
+ ## Configuration
119
+
120
+ Configuring log4j is left to the client via the [standard log4j configuration process](https://logging.apache.org/log4j/2.x/manual/configuration.html).
121
+
122
+ E.g.
123
+
124
+ Create a `log4j2.properties` file and make sure it is available in your classpath.
125
+
126
+ The log4j-api-2.n.jar and log4j-core-2.n.jars must be found in your classpath when `log4jruby` is loaded.
127
+
128
+ * Place files somewhere already in your classpath such as `$TOMCAT/lib` for Tomcat.
129
+ * Configure classpath via `JAVA_OPTS`
130
+ * Amend `$CLASSPATH` at runtime before loading log4jruby. See [examples/setup.rb](examples/setup.rb).
44
131
 
45
- In a Rails application, add the following in ```config/application.rb``` or the appropriate ```config/environments``` file.
46
-
47
- config.logger = ActiveSupport::TaggedLogging.new(Log4jruby::Logger.get('MyApp'))
48
-
132
+ Note: If you're using bundler, you can specify `gem 'log4jruby', require: false` in your Gemfile to delay loading the gem too early.
133
+
134
+ In a Rails application, add the following in `config/application.rb` or the appropriate `config/environments` file.
135
+ ```ini
136
+ config.logger = ActiveSupport::TaggedLogging.new(Log4jruby::Logger.get('MyApp'))
137
+ ```
49
138
  or older versions of Rails
139
+ ```ini
140
+ config.logger = Log4jruby::Logger.get('MyApp')
141
+ ```
142
+
143
+ ## Formatters
50
144
 
51
- config.logger = Log4jruby::Logger.get('MyApp')
52
-
53
- ### Examples
145
+ See [`formatter` in the
146
+ Ruby ::Logger docs](https://ruby-doc.org/stdlib-2.7.0/libdoc/logger/rdoc/Logger.html)
54
147
 
55
- def foo
56
- logger.debug("hello from foo")
57
- bar
58
- rescue => e
59
- logger.error(e)
60
- end
148
+ Log4jruby passes the same arguments to a `formatter` as would be passed using the standard Ruby Logger given the same logging invocations.
61
149
 
62
- DEBUG jruby.MyClass foo:17 - hello from foo
63
- DEBUG jruby.MyClass bar:24 - hello from bar
64
- DEBUG jruby.MyClass baz:29 - hello from baz
65
- ERROR jruby.MyClass foo:20 - error from baz
66
- examples/simple.rb:30:in `baz'
67
- examples/simple.rb:25:in `bar'
68
- examples/simple.rb:18:in `foo'
69
- examples/simple.rb:35:in `(root)'
150
+ The default Log4jruby formatter outputs `progname` and `msg` only (as opposed to the default formatter of the Ruby Logger).
151
+ Severity, timestamp, and backtraces are handed according to your `Log4j` configuration.
152
+ E.g. [PatternLayout](https://logging.apache.org/log4j/2.x/manual/layouts.html).
70
153
 
71
- See more in [log4jruby/examples](examples).
154
+ The output of the `formatter` is passed as the `message` parameter of the [Log4j log methods](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Category.html#log(org.apache.log4j.Priority,%20java.lang.Object).
72
155
 
73
- ### Usage
156
+ ## Development
74
157
 
75
- class MyClass
76
- enable_logger
158
+ Install log4j for tests and examples
77
159
 
78
- class << self
79
- def my_class_method
80
- logger.info("hello from class method")
81
- end
82
- end
160
+ `rake dev:java_deps`
83
161
 
84
- def my_method
85
- logger.info("hello from instance method")
86
- end
87
- end
162
+ ```
163
+ e.g.
88
164
 
89
- INFO jruby.MyModule.A my_class_method:14 - hello from class method
90
- INFO jruby.MyModule.A my_method:19 - hello from instance method
165
+ ruby ./examples/simple.rb
166
+ ```
91
167
 
92
- See more in [log4jruby/examples](examples)..
93
- They should be runnable from the source.
168
+ ### IRB
94
169
 
170
+ ```
171
+ bundle exec irb
172
+ irb(main):002:0> require './examples/setup.rb'
173
+ irb(main):003:0> require 'log4jruby'
174
+ irb(main):006:0> Log4jruby::Logger.root.debug('test')
175
+ DEBUG jruby : - test
176
+ ```
@@ -1,37 +1,27 @@
1
- require 'log4jruby/support/log4j_args'
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'log4jruby/support/log4j_args'
4
+ require 'log4jruby/support/levels'
5
+ require 'log4jruby/support/location'
6
+ require 'log4jruby/support/log_manager'
3
7
  require 'logger'
4
8
 
5
9
  module Log4jruby
6
-
7
10
  # Author:: Lenny Marks
8
11
  #
9
- # Wrapper around org.apache.log4j.Logger with interface similar to standard ruby Logger.
12
+ # Wrapper around org.apache.logging.log4j.Logger with interface similar to standard ruby Logger.
10
13
  #
11
14
  # * Ruby and Java exceptions are logged with backtraces.
12
- # * fileName, lineNumber, methodName available to appender layouts via MDC variables(e.g. %X{lineNumber})
15
+ # * fileName, lineNumber, methodName available to appender layouts via
16
+ # * MDC variables(e.g. %X{lineNumber})
13
17
  class Logger
14
- LOG4J_LEVELS = {
15
- Java::org.apache.log4j.Level::DEBUG => ::Logger::DEBUG,
16
- Java::org.apache.log4j.Level::INFO => ::Logger::INFO,
17
- Java::org.apache.log4j.Level::WARN => ::Logger::WARN,
18
- Java::org.apache.log4j.Level::ERROR => ::Logger::ERROR,
19
- Java::org.apache.log4j.Level::FATAL => ::Logger::FATAL,
20
- }
21
-
22
- # turn tracing on to make fileName, lineNumber, and methodName available to
23
- # appender layout through MDC(ie. %X{fileName} %X{lineNumber} %X{methodName})
24
- attr_accessor :tracing
25
-
26
- # ::Logger::Formatter
27
- attr_accessor :formatter
18
+ Support::LogManager.configure(logger_class: self)
28
19
 
29
20
  class << self
30
21
  # get Logger for name
31
22
  def[](name)
32
- name = name.nil? ? 'jruby' : "jruby.#{name.gsub('::', '.')}"
33
- log4j = Java::org.apache.log4j.Logger.getLogger(name)
34
- fetch_logger(log4j)
23
+ name = name.nil? ? root.name : "#{root.name}.#{name.gsub('::', '.')}"
24
+ Support::LogManager.get_or_create(name)
35
25
  end
36
26
 
37
27
  # same as [] but accepts attributes
@@ -43,193 +33,139 @@ module Log4jruby
43
33
 
44
34
  # Return root Logger(i.e. jruby)
45
35
  def root
46
- log4j = Java::org.apache.log4j.Logger.getLogger('jruby')
47
- fetch_logger(log4j)
48
- end
49
-
50
- def reset # :nodoc:
51
- Java::org.apache.log4j.LogManager.getCurrentLoggers.each do |l|
52
- l.ruby_logger = nil
53
- end
54
- end
55
-
56
- private
57
-
58
- def fetch_logger(log4j_logger)
59
- Java::org.apache.log4j.Logger.getLogger(log4j_logger.getName).ruby_logger
36
+ Support::LogManager.root
60
37
  end
61
38
  end
62
39
 
63
40
  def attributes=(values)
64
- if values
65
- values.each_pair do |k, v|
66
- setter = "#{k}="
67
- send(setter, v) if respond_to?(setter)
68
- end
41
+ values&.each_pair do |k, v|
42
+ setter = "#{k}="
43
+ send(setter, v) if respond_to?(setter)
69
44
  end
70
45
  end
71
46
 
47
+ def name
48
+ log4j_logger.name
49
+ end
50
+
72
51
  # Shortcut for setting log levels. (:debug, :info, :warn, :error, :fatal)
73
52
  def level=(level)
74
- @logger.level = case level
75
- when :debug, ::Logger::DEBUG
76
- Java::org.apache.log4j.Level::DEBUG
77
- when :info, ::Logger::INFO
78
- Java::org.apache.log4j.Level::INFO
79
- when :warn, ::Logger::WARN
80
- Java::org.apache.log4j.Level::WARN
81
- when :error, ::Logger::ERROR
82
- Java::org.apache.log4j.Level::ERROR
83
- when :fatal, ::Logger::FATAL
84
- Java::org.apache.log4j.Level::FATAL
85
- else
86
- raise NotImplementedError
87
- end
53
+ @log4j_logger.level = Support::Levels.log4j_level(level)
88
54
  end
89
55
 
90
56
  def level
91
- LOG4J_LEVELS[@logger.effectiveLevel]
57
+ Support::Levels.ruby_logger_level(@log4j_logger.level)
92
58
  end
93
59
 
94
60
  def flush
95
- #rails compatability
61
+ # rails compatability
96
62
  end
97
63
 
98
64
  def debug(object = nil, &block)
99
- if debug?
100
- send_to_log4j(:debug, object, nil, &block)
101
- end
65
+ send_to_log4j(:debug, object, &block) if debug?
102
66
  end
103
67
 
104
68
  def info(object = nil, &block)
105
- if info?
106
- send_to_log4j(:info, object, nil, &block)
107
- end
69
+ send_to_log4j(:info, object, &block) if info?
108
70
  end
109
71
 
110
72
  def warn(object = nil, &block)
111
- if warn?
112
- send_to_log4j(:warn, object, nil, &block)
113
- end
73
+ send_to_log4j(:warn, object, &block) if warn?
114
74
  end
115
75
 
116
76
  def error(object = nil, &block)
117
- send_to_log4j(:error, object, nil, &block)
77
+ send_to_log4j(:error, object, &block)
118
78
  end
119
79
 
120
80
  def log_error(msg, error)
121
- send_to_log4j(:error, msg, error)
81
+ send_to_log4j(:error, msg) { error }
122
82
  end
123
83
 
124
84
  def fatal(object = nil, &block)
125
- send_to_log4j(:fatal, object, nil, &block)
85
+ send_to_log4j(:fatal, object, &block)
126
86
  end
127
87
 
128
88
  def log_fatal(msg, error)
129
- send_to_log4j(:fatal, msg, error)
89
+ send_to_log4j(:fatal, msg) { error }
130
90
  end
131
91
 
132
- # return org.apache.log4j.Logger instance backing this Logger
133
- def log4j_logger
134
- @logger
135
- end
92
+ # return org.apache.logging.log4j.Logger instance backing this Logger
93
+ attr_reader :log4j_logger
136
94
 
137
95
  def debug?
138
- @logger.isEnabledFor(Java::org.apache.log4j.Priority::DEBUG)
96
+ @log4j_logger.isEnabled(Java::org.apache.logging.log4j.Level::DEBUG)
139
97
  end
140
98
 
141
99
  def info?
142
- @logger.isEnabledFor(Java::org.apache.log4j.Priority::INFO)
100
+ @log4j_logger.isEnabled(Java::org.apache.logging.log4j.Level::INFO)
143
101
  end
144
102
 
145
103
  def warn?
146
- @logger.isEnabledFor(Java::org.apache.log4j.Priority::WARN)
104
+ @log4j_logger.isEnabled(Java::org.apache.logging.log4j.Level::WARN)
147
105
  end
148
106
 
149
107
  def tracing?
150
- return @cached_tracing if defined?(@cached_tracing)
151
- @cached_tracing = begin
152
- if tracing.nil? && self != Logger.root
153
- parent.tracing?
154
- else
155
- tracing == true
156
- end
157
- end
108
+ return @tracing if defined?(@tracing)
109
+
110
+ @tracing = self == Logger.root ? false : parent.tracing?
111
+ end
112
+ alias tracing tracing?
113
+
114
+ # turn tracing on to make fileName, lineNumber, and methodName available to
115
+ # appender layout through MDC(ie. %X{fileName} %X{lineNumber} %X{methodName})
116
+ def tracing=(bool)
117
+ @tracing = !!bool
158
118
  end
159
119
 
160
- def effective_formatter
120
+ def formatter
161
121
  return @formatter if defined?(@formatter)
162
- @formatter = begin
163
- if @formatter.nil? && self != Logger.root
164
- parent.formatter
165
- else
166
- @formatter
167
- end
168
- end
122
+
123
+ @formatter = if self == Logger.root
124
+ ->(_severity, _datetime, progname, msg) { "-- #{progname}: #{msg}" }
125
+ else
126
+ parent.formatter
127
+ end
169
128
  end
170
129
 
130
+ # @param [::Logger::Formatter]
131
+ attr_writer :formatter
132
+
171
133
  def parent
172
- fetch_logger(log4j_logger.parent)
134
+ Support::LogManager.parent(log4j_logger.name)
173
135
  end
174
136
 
175
137
  # Compatibility with ActiveSupport::Logger
176
138
  # needed to use a Log4jruby::Logger as an ActiveRecord::Base.logger
177
- def silence(temporary_level = ::Logger::ERROR)
178
- begin
179
- old_logger_level, self.level = level, temporary_level
180
- yield self
181
- ensure
182
- self.level = old_logger_level
183
- end
139
+ def silence(temporary_level = ::Logger::ERROR, &blk)
140
+ with_level(temporary_level, &blk)
184
141
  end
185
142
 
186
- private
143
+ def with_level(temporary_level = ::Logger::ERROR)
144
+ old_logger_level = level
145
+ self.level = temporary_level
146
+ yield self
147
+ ensure
148
+ self.level = old_logger_level
149
+ end
187
150
 
188
151
  def initialize(logger) # :nodoc:
189
- @logger = logger
152
+ @log4j_logger = logger
190
153
  end
191
154
 
192
- def with_context # :nodoc:
193
- file_line_method = parse_caller(caller(3).first)
194
-
195
- mdc.put('fileName', file_line_method[0])
196
- mdc.put('lineNumber', file_line_method[1])
197
- mdc.put('methodName', file_line_method[2].to_s)
198
-
199
- begin
200
- yield
201
- ensure
202
- mdc.remove('fileName')
203
- mdc.remove('lineNumber')
204
- mdc.remove('methodName')
205
- end
206
- end
155
+ private
207
156
 
208
- def send_to_log4j(level, object, error, &block)
209
- msg, throwable = Support::Log4jArgs.convert(object, error, &block)
210
- if (f = effective_formatter)
211
- msg = f.call(level, Time.now, @logger.getName, msg)
157
+ def send_to_log4j(level, object, &block)
158
+ progname, msg, throwable = Support::Log4jArgs.convert(object, &block)
159
+ if (f = formatter)
160
+ msg = f.call(level, Time.now, progname, msg)
212
161
  end
213
162
  if tracing?
214
- with_context do
215
- @logger.send(level, msg, throwable)
163
+ Support::Location.with_location do
164
+ @log4j_logger.send(level, msg, throwable)
216
165
  end
217
166
  else
218
- @logger.send(level, msg, throwable)
167
+ @log4j_logger.send(level, msg, throwable)
219
168
  end
220
169
  end
221
-
222
- def parse_caller(at) # :nodoc:
223
- at.match(/^(.+?):(\d+)(?::in `(.*)')?/).captures
224
- end
225
-
226
- def mdc
227
- Java::org.apache.log4j.MDC
228
- end
229
-
230
- def fetch_logger(log4j_logger)
231
- self.class.send(:fetch_logger, log4j_logger)
232
- end
233
170
  end
234
171
  end
235
-
@@ -1,19 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'log4jruby'
2
4
 
3
5
  module Log4jruby
4
-
5
- # Gives class its own Logger and makes it available via class and instance method.
6
+ # Gives class its own Logger and makes it available via class and instance method.
6
7
  module LoggerForClass
7
-
8
8
  def self.included(klass)
9
9
  def klass.logger
10
10
  @logger ||= Logger.get(name)
11
11
  end
12
-
12
+
13
13
  def klass.logger=(logger)
14
14
  @logger = logger
15
15
  end
16
-
16
+
17
17
  def klass.set_logger(name, options = {})
18
18
  @logger = Logger.get(name, options)
19
19
  end
@@ -23,4 +23,4 @@ module Log4jruby
23
23
  self.class.logger
24
24
  end
25
25
  end
26
- end
26
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module Log4jruby
6
+ module Support
7
+ # Utility methods for dealing with log levels
8
+ class Levels
9
+ LOG4J_LEVELS = {
10
+ Java::org.apache.logging.log4j.Level::DEBUG => ::Logger::DEBUG,
11
+ Java::org.apache.logging.log4j.Level::INFO => ::Logger::INFO,
12
+ Java::org.apache.logging.log4j.Level::WARN => ::Logger::WARN,
13
+ Java::org.apache.logging.log4j.Level::ERROR => ::Logger::ERROR,
14
+ Java::org.apache.logging.log4j.Level::FATAL => ::Logger::FATAL
15
+ }.freeze
16
+
17
+ class << self
18
+ def ruby_logger_level(log4j_level)
19
+ LOG4J_LEVELS[log4j_level]
20
+ end
21
+
22
+ # rubocop:disable Metrics/AbcSize
23
+ def log4j_level(ruby_logger_level)
24
+ case ruby_logger_level
25
+ when :debug, ::Logger::DEBUG
26
+ Java::org.apache.logging.log4j.Level::DEBUG
27
+ when :info, ::Logger::INFO
28
+ Java::org.apache.logging.log4j.Level::INFO
29
+ when :warn, ::Logger::WARN
30
+ Java::org.apache.logging.log4j.Level::WARN
31
+ when :error, ::Logger::ERROR
32
+ Java::org.apache.logging.log4j.Level::ERROR
33
+ when :fatal, ::Logger::FATAL
34
+ Java::org.apache.logging.log4j.Level::FATAL
35
+ when nil
36
+ # noop
37
+ else
38
+ raise NotImplementedError
39
+ end
40
+ end
41
+ # rubocop:enable Metrics/AbcSize
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Log4jruby
4
+ module Support
5
+ # Utility methods for interacting with Log4j
6
+ # MDC (mapped diagnostic contexts)
7
+ # https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html
8
+ class Location
9
+ class << self
10
+ def with_location # :nodoc:
11
+ file_line_method = parse_caller(caller(3).first)
12
+ context_put(file_line_method)
13
+ begin
14
+ yield
15
+ ensure
16
+ context_remove
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def context_put((file, line, method))
23
+ thread_context.put('fileName', file)
24
+ thread_context.put('lineNumber', line)
25
+ thread_context.put('methodName', method.to_s)
26
+ end
27
+
28
+ def context_remove
29
+ thread_context.remove('fileName')
30
+ thread_context.remove('lineNumber')
31
+ thread_context.remove('methodName')
32
+ end
33
+
34
+ def parse_caller(at) # :nodoc:
35
+ at.match(/^(.+?):(\d+)(?::in `(.*)')?/).captures
36
+ end
37
+
38
+ def thread_context
39
+ Java::org.apache.logging.log4j.ThreadContext
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,40 +1,43 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Log4jruby
2
4
  module Support
5
+ # Translate logger args for use by Ruby Logger formatter and log4j.
6
+ # Intention is to matches the Ruby Logger for common parameters
3
7
  class Log4jArgs
4
8
  class << self
5
- def convert(object = nil, exception = nil)
6
- msg = ''
7
-
8
- if exception
9
- msg << object.to_s
10
- else
11
- exception = block_given? ? yield : object
12
- end
13
-
14
- if exception.is_a?(NativeException)
15
- append_ruby_error(msg, exception)
16
- msg << "\nNativeException:"
17
- exception = exception.cause
18
- elsif exception.is_a?(::Exception)
19
- append_ruby_error(msg, exception)
20
- exception = nil
21
- elsif !exception.is_a?(java.lang.Throwable)
22
- msg << exception.to_s
23
- exception = nil
24
- end
9
+ # Adapt permutations of ruby Logger arguments into arguments
10
+ # for Log4j Logger with explicit throwable when possible.
11
+ #
12
+ # The :progname and :msg returned by this method matches
13
+ # the arguments that would be passed to a
14
+ # Ruby Logger#formatter
15
+ #
16
+ # @param object [String | Exception] - Correlates to the `progname` param of the
17
+ # ruby Logger. Exception passed to Log4j as throwable when no other
18
+ # arguments are provided.
19
+ # @yield [] Return object to be used as the :msg (See Ruby ::Logger). Exceptions
20
+ # will be used as Throwable arg to log4j.
21
+ #
22
+ # @return [Array<Object, Object, Java::Throwable>] -
23
+ # Ruby Logger progname, Ruby Logger msg, throwable for log4j
24
+ def convert(object = nil)
25
+ # This implementation is very complex in order to support
26
+ yielded_val = block_given? ? yield : nil
25
27
 
26
- [msg, exception]
28
+ exception = exception(yielded_val) || exception(object)
29
+ msg = yielded_val || object || exception
30
+ [progname(object, yielded_val), msg, exception&.to_java]
27
31
  end
28
32
 
29
33
  private
30
34
 
31
- def append_ruby_error(msg, error)
32
- append(msg, "#{error}\n " + error.backtrace.join("\n "))
35
+ def progname(object, yielded_val)
36
+ object && yielded_val ? object : nil
33
37
  end
34
38
 
35
- def append(msg, s)
36
- msg << "\n#{s}"
37
- msg.lstrip!
39
+ def exception(obj)
40
+ obj.is_a?(::Exception) || obj.is_a?(Java::java.lang.Throwable) ? obj : nil
38
41
  end
39
42
  end
40
43
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module Log4jruby
6
+ module Support
7
+ # Internal class for tracking loggers in a thread safe manor
8
+ class LogManager
9
+ @loggers = {}
10
+ @mutex = Mutex.new.freeze
11
+
12
+ class << self
13
+ attr_reader :logger_class
14
+
15
+ def configure(logger_class:)
16
+ @logger_class = logger_class
17
+ end
18
+
19
+ def get_or_create(name)
20
+ raise 'name required' if name.to_s.match?(/^\s+$/)
21
+
22
+ @mutex.synchronize do
23
+ @loggers[name] ||= new_logger(name)
24
+ end
25
+ end
26
+
27
+ def get(name)
28
+ @mutex.synchronize { @loggers[name] }
29
+ end
30
+
31
+ # nodoc: testing only
32
+ def reset
33
+ @mutex.synchronize { @loggers.clear }
34
+ Java::org.apache.logging.log4j.LogManager.rootLogger.context.stop
35
+ end
36
+
37
+ def root
38
+ get_or_create('jruby')
39
+ end
40
+
41
+ def parent(name)
42
+ _parent(name.split('.'))
43
+ end
44
+
45
+ private
46
+
47
+ def new_logger(name)
48
+ log4j_logger = Java::org.apache.logging.log4j.LogManager.getLogger(name)
49
+ @logger_class.new(log4j_logger)
50
+ end
51
+
52
+ def _parent(name_path)
53
+ return root if name_path.empty?
54
+
55
+ parent_path = name_path[0, name_path.size - 1]
56
+ parent_name = parent_path.join('.')
57
+
58
+ get(parent_name) || _parent(parent_path)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Log4jruby
2
- VERSION = '2.0.1'
4
+ VERSION = '3.0.0.rc1'
3
5
  end
data/lib/log4jruby.rb CHANGED
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Log4jruby
4
+ # Support namespace
2
5
  module Support
3
6
  end
4
7
  end
5
8
 
6
- require 'log4jruby/support/bootstrap'
7
9
  require 'log4jruby/logger'
8
10
  require 'log4jruby/logger_for_class'
9
11
 
metadata CHANGED
@@ -1,16 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: log4jruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.0.rc1
5
5
  platform: java
6
6
  authors:
7
7
  - Lenny Marks
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-10 00:00:00.000000000 Z
11
+ date: 2022-09-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Ruby Logger using Log4j, geared toward those who use JRuby to write Ruby code using/extending Java code. Ruby and Java are configured together using traditional Log4j methods.
13
+ description: Ruby Logger using Log4j, geared toward those who use JRuby to write Ruby
14
+ code using/extending Java code. Ruby and Java are configured together using traditional
15
+ Log4j methods.
14
16
  email:
15
17
  - lenny@aps.org
16
18
  executables: []
@@ -22,31 +24,37 @@ files:
22
24
  - lib/log4jruby.rb
23
25
  - lib/log4jruby/logger.rb
24
26
  - lib/log4jruby/logger_for_class.rb
25
- - lib/log4jruby/support/bootstrap.rb
27
+ - lib/log4jruby/support/levels.rb
28
+ - lib/log4jruby/support/location.rb
26
29
  - lib/log4jruby/support/log4j_args.rb
30
+ - lib/log4jruby/support/log_manager.rb
27
31
  - lib/log4jruby/version.rb
28
32
  homepage: https://github.com/lenny/log4jruby
29
33
  licenses:
30
34
  - MIT
31
- metadata: {}
35
+ metadata:
36
+ rubygems_mfa_required: 'true'
32
37
  post_install_message:
33
38
  rdoc_options: []
34
39
  require_paths:
35
40
  - lib
36
41
  required_ruby_version: !ruby/object:Gem::Requirement
37
42
  requirements:
38
- - - ">="
43
+ - - "~>"
39
44
  - !ruby/object:Gem::Version
40
- version: '0'
45
+ version: 2.6.8
41
46
  required_rubygems_version: !ruby/object:Gem::Requirement
42
47
  requirements:
43
- - - ">="
48
+ - - ">"
44
49
  - !ruby/object:Gem::Version
45
- version: '0'
50
+ version: 1.3.1
46
51
  requirements: []
47
- rubyforge_project:
48
- rubygems_version: 2.4.8
52
+ rubygems_version: 3.2.29
49
53
  signing_key:
50
54
  specification_version: 4
51
- summary: Log4jruby is a thin wrapper around the Log4j Logger. It is geared more toward those who are using JRuby to integrate with and build on top of Java code that uses Log4j. The Log4jruby::Logger provides an interface much like the standard ruby Logger. Your ruby loggers are given a .jruby prefix and can be configured along with the loggers for your Java code.
55
+ summary: Log4jruby is a thin wrapper around the Log4j Logger. It is geared more toward those
56
+ who are using JRuby to integrate with and build on top of Java code that uses Log4j.
57
+ The Log4jruby::Logger provides an interface much like the standard ruby Logger.
58
+ Your ruby loggers are given a .jruby prefix and can be configured along with the
59
+ loggers for your Java code.
52
60
  test_files: []
@@ -1,25 +0,0 @@
1
- require 'thread'
2
-
3
- Java::org.apache.log4j.Logger.class_eval do
4
- attr_accessor :ruby_logger
5
- @ruby_logger_lock = Mutex.new
6
-
7
- class << self
8
- def ruby_logger_lock
9
- @ruby_logger_lock
10
- end
11
- end
12
-
13
- def ruby_logger
14
- self.class.ruby_logger_lock.synchronize do
15
- @ruby_logger ||= Log4jruby::Logger.new(self)
16
- end
17
- end
18
- end
19
-
20
- # https://github.com/lenny/log4jruby/issues/14
21
- # https://github.com/jruby/jruby/wiki/Persistence
22
- if Java::org.apache.log4j.Logger.respond_to?(:__persistent__)
23
- Java::org.apache.log4j.Logger.__persistent__ = true
24
- end
25
-