log4j2_logger_bridge 1.0.1-java → 1.1.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f03bc99125d4e93d9c2b50ffa1e105881bf26d933faeb179caa55cda476bf0c0
4
- data.tar.gz: 6d2de401a6ea49ca9f932edfc2852da7152c5eb86c52fe27d0626e945b4826ac
3
+ metadata.gz: 0ed8508f36743d2f912be5d41a6d6acbc7cf408aa823c6e93627b12ac1a19bbf
4
+ data.tar.gz: 6aea8a650f7076ed1e648cf74281b40bad6ec8e58bc69de7f5d406ec0f531524
5
5
  SHA512:
6
- metadata.gz: 544eb01b920127d42859a28a96b3e31da2091e589735de2d8ebedb9999e580fbf5c3d318b456890b885aabe1c709a3942f1250e48a041d0562b00238ae1005da
7
- data.tar.gz: cb8ddfbd3ae21e86376a89695d14dbff8b4e137fb38039238d4f8e2004623b4e2f24fa1d691484d9a82f73c72daea8a73aafeedf8802777c522142ee0acd18f3
6
+ metadata.gz: e816e54807be7a57e9ecc9da2bc658eef0481cbdebe79b3bb818d004f36ed90be2a4c1f58f592288f64a8cd9bb2683285d26ec41b2c46f65f22f15ad77b1d8ee
7
+ data.tar.gz: 1b935f796dee964f6f1b8d42f2b58d9d9fdd882fe380faecbafa0d173dcca8e54aadb52fa09e3c2fbf2427eb36825716a2e36985be6df2345c2b2c99634a51a1
data/README.md CHANGED
@@ -6,3 +6,211 @@ It attempts to provide a single unified interface for both logging
6
6
  technologies, so that switching between either backend can be accomplished
7
7
  without much effort.
8
8
 
9
+ 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).
10
+
11
+
12
+ ## Install
13
+
14
+ Install the gem.
15
+
16
+
17
+ ### Gemfile
18
+
19
+ Specify the gem inclusion in your project's Ruby Gemfile.
20
+
21
+ ```ruby
22
+ gem 'log4j2_logger_bridge'
23
+ ```
24
+
25
+
26
+ ### Require
27
+
28
+ Load the gem in a Ruby code module.
29
+
30
+ ```ruby
31
+ require 'log4j2_logger_bridge'
32
+ ```
33
+
34
+
35
+ ## Quick-start
36
+
37
+ Gotta go fast.
38
+
39
+
40
+ ### 1) Log to stdout
41
+
42
+ Example of simply logging to stdout with default configuration.
43
+
44
+ ```ruby
45
+ #! /usr/bin/env ruby
46
+ # frozen_string_literal: true
47
+
48
+ require 'log4j2_logger_bridge'
49
+
50
+ module Example
51
+ module_function
52
+
53
+ def main
54
+ log.info("Hello from the bridge.")
55
+ log.warn("This is a warning!")
56
+ log.error("This is an error!")
57
+ end
58
+ end
59
+
60
+ Example.main
61
+ ```
62
+
63
+ For example:
64
+
65
+ ```
66
+ $ bundle exec ruby scripts/example.rb
67
+ 18:13:28,236 INFO [Example] Hello from the bridge.
68
+ 18:13:28,238 WARN [Example] This is a warning!
69
+ 18:13:28,238 ERROR [Example] This is an error!
70
+ ```
71
+
72
+ Levels include: `trace`, `debug`, `info`, `warn`, `error`, `fatal`.
73
+
74
+
75
+ ### 2) Categories (optional)
76
+
77
+ Categories are set automatically from the receiver/callsite, but you can also force one:
78
+
79
+ ```ruby
80
+ #!/usr/bin/env ruby
81
+ # frozen_string_literal: true
82
+
83
+ require 'log4j2_logger_bridge'
84
+
85
+ Log4j2LoggerBridge.with_category("MyCategory") do
86
+ log.info("this line is tagged with MyCategory")
87
+ end
88
+ ```
89
+
90
+
91
+ ## In a project with OptionParser
92
+
93
+ Say your project supports:
94
+
95
+ ```ruby
96
+ module MyProject
97
+ def main(args = parse_arguments)
98
+ # Your app code here.
99
+ end
100
+ end
101
+ ```
102
+
103
+ Here is a minimal end-to-end example that matches that pattern:
104
+
105
+ ```ruby
106
+ # frozen_string_literal: true
107
+
108
+ require 'optparse'
109
+ require 'log4j2_logger_bridge'
110
+
111
+ module MyProject
112
+ class ArgumentsParser
113
+ attr_reader :parser, :options
114
+
115
+ def initialize(option_parser = OptionParser.new)
116
+ @parser = option_parser
117
+ @options = { log_level: 0 }
118
+ @parser.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options]"
119
+ @parser.on_tail("-v", "--verbose", "Increase verbosity") do
120
+ @options[:log_level] = @options[:log_level] - 1
121
+ end
122
+ end
123
+ end
124
+
125
+ module_function
126
+
127
+ def parse_arguments(arguments_parser = ArgumentsParser.new)
128
+ arguments_parser.parser.parse!(ARGV)
129
+ arguments_parser.options
130
+ rescue OptionParser::ParseError => e
131
+ abort e.message
132
+ end
133
+
134
+ def main(args = parse_arguments)
135
+ Log4j2LoggerBridge.log_level = args[:log_level]
136
+
137
+ log.info("server starting")
138
+ log.debug("debug details here")
139
+ end
140
+ end
141
+
142
+ MyProject.main
143
+ ```
144
+
145
+ Notes:
146
+
147
+ * The gem accepts `log_level=` as an Integer descending from 0 (`0, -1, -2, ...`) or as a Symbol/String (like `:info`, `"debug"`).
148
+ * With a `-v` flag decreasing the integer, you get more verbosity (for example `0` -> debug, `-1` -> trace, etc.).
149
+
150
+
151
+ ## Advanced usage: configure rolling log files and log directory
152
+
153
+ The gem exposes a destination configuration entrypoint that creates the logs directory + log file if missing, and (on JRuby) wires Log4j2 rolling file behavior.
154
+
155
+
156
+ ### Example
157
+
158
+ Setting logs directory under your project, and rollover configuration.
159
+
160
+ ```ruby
161
+ # frozen_string_literal: true
162
+
163
+ require 'log4j2_logger_bridge'
164
+
165
+ Log4j2LoggerBridge.configure_destination do |c|
166
+ c.project_dir_path = File.expand_path('..', __dir__) # repo/app root
167
+ c.logs_dir_name = 'logs'
168
+ c.app_name = 'my_project'
169
+ c.log_file_name = 'my_project.log'
170
+
171
+ # Rolling policy knobs:
172
+ c.rollover_size = '250M'
173
+ c.rollover_schedule = '0 0 0 * * ?' # cron-style schedule used by Log4j2
174
+ # Optional: override pattern for rolled files
175
+ c.rolling_file_name_template = 'my_project-%d{yyyy-MM-dd}.log.gz'
176
+ end
177
+
178
+ Log4j2LoggerBridge.log_level = :info
179
+ log.info("logging to file (and rolling per settings)")
180
+ ```
181
+
182
+ How to think about it:
183
+
184
+ * Call `configure_destination` once at process startup (before heavy logging).
185
+ * Keep the config close to your app's boot path (for example, in `config/boot.rb` or similar).
186
+
187
+
188
+ ## Practical integration pattern
189
+
190
+ A common layout:
191
+
192
+ ```ruby
193
+ # lib/my_app/boot.rb
194
+ # frozen_string_literal: true
195
+
196
+ require 'log4j2_logger_bridge'
197
+
198
+ module MyApp
199
+ module Boot
200
+ module_function
201
+
202
+ def setup_logging!(args)
203
+ Log4j2LoggerBridge.configure_destination do |c|
204
+ c.project_dir_path = args.fetch(:project_dir_path, Dir.pwd)
205
+ c.logs_dir_name = args.fetch(:logs_dir_name, 'logs')
206
+ c.app_name = args.fetch(:app_name, 'my_app')
207
+ c.rollover_size = args.fetch(:rollover_size, '100M')
208
+ end
209
+
210
+ Log4j2LoggerBridge.log_level = args.fetch(:log_level, :info)
211
+ end
212
+ end
213
+ end
214
+ ```
215
+
216
+ Then call `MyApp::Boot.setup_logging!(args)` from `main` right after parsing options.
@@ -22,11 +22,12 @@ if Log4j2LoggerBridge::Utils.jruby?
22
22
  end
23
23
 
24
24
  require 'fileutils'
25
- require 'logger'
26
25
 
26
+ require_relative 'destination'
27
27
  require_relative 'helpers'
28
28
  require_relative 'injection'
29
29
  require_relative 'log4j2_initialization_methods'
30
+ require_relative 'log4j2_rolling_file'
30
31
  require_relative 'ruby_logger_initialization_methods'
31
32
  require_relative 'proxy'
32
33
 
@@ -50,6 +51,29 @@ module Log4j2LoggerBridge
50
51
  init_ruby_logger_backend
51
52
  end
52
53
 
54
+ # Public API: configure file destination + rollover.
55
+ # Example:
56
+ # Log4j2LoggerBridge.configure_destination do |c|
57
+ # c.project_dir_path = File.realpath(__dir__)
58
+ # c.rollover_size = '100M'
59
+ # end
60
+ def configure_destination(&block)
61
+ Log4j2LoggerBridge::Destination.configure(&block)
62
+ end
63
+
64
+ # Convenience: direct access to rollover settings.
65
+ def rollover
66
+ Log4j2LoggerBridge::Destination.rollover
67
+ end
68
+
69
+ def logs_dir_path
70
+ Log4j2LoggerBridge::Destination.logs_dir_path
71
+ end
72
+
73
+ def log_file_path
74
+ Log4j2LoggerBridge::Destination.log_file_path
75
+ end
76
+
53
77
  def dispatch(level, *args, &block)
54
78
  return backend.public_send(level, *args, &block) if Utils.jruby?
55
79
 
@@ -4,15 +4,20 @@
4
4
  # -*- mode: ruby -*-
5
5
  # vi: set ft=ruby :
6
6
 
7
+ require 'logger'
8
+
7
9
  # The Log4j2LoggerBridge module
8
10
  module Log4j2LoggerBridge
9
11
  # The Constants module
10
12
  module Constants
11
- DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'.freeze
13
+ DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'.freeze
12
14
  DEFAULT_APP_NAME = 'app'.freeze
13
15
  DEFAULT_LOG_PATTERN = '%d{ABSOLUTE} %-5p [%X{category}] %m%n'.freeze
14
16
  DEFAULT_RUBY_LOG_FORMAT =
15
17
  "%<timestamp>s %-5<severity>s [%<category>s] %<msg>s\n".freeze
18
+ DEFAULT_ROLLOVER_SCHEDULE = '0 0 0 * * ?'.freeze
19
+ DEFAULT_ROLLOVER_SIZE = '100M'.freeze
20
+ DEFAULT_LOGS_DIR_NAME = 'logs'.freeze
16
21
  EMPTY_STRING = ''.freeze
17
22
 
18
23
  NUMERIC_TO_SYMBOL = {
@@ -0,0 +1,107 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+
4
+ # -*- mode: ruby -*-
5
+ # vi: set ft=ruby :
6
+
7
+ require 'fileutils'
8
+
9
+ require_relative 'constants'
10
+
11
+ module Log4j2LoggerBridge
12
+ # Centralized destination config for both CRuby Logger and JRuby Log4j2.
13
+ module Destination
14
+ # The Configuration class for the Destination module
15
+ class Configuration
16
+ include Constants
17
+
18
+ attr_accessor :project_dir_path, :app_name, :logs_dir_name,
19
+ :log_file_name, :timestamp_format, :rollover_schedule,
20
+ :rollover_size, :rolling_file_name_template
21
+
22
+ def initialize
23
+ @project_dir_path = Dir.pwd
24
+ @app_name = File.basename(@project_dir_path.to_s)
25
+ @logs_dir_name = DEFAULT_LOGS_DIR_NAME
26
+ @log_file_name = "#{@app_name}.log"
27
+ @timestamp_format = DEFAULT_TIMESTAMP_FORMAT
28
+ @rollover_schedule = DEFAULT_ROLLOVER_SCHEDULE
29
+ @rollover_size = DEFAULT_ROLLOVER_SIZE
30
+ @rolling_file_name_template = nil
31
+ end
32
+
33
+ def logs_dir_path
34
+ File.expand_path(File.join(project_dir_path, logs_dir_name))
35
+ end
36
+
37
+ def log_file_path
38
+ File.expand_path(File.join(logs_dir_path, log_file_name))
39
+ end
40
+
41
+ def resolved_rolling_file_name_template
42
+ template = rolling_file_name_template
43
+ return File.expand_path(template) if template && !template.strip.empty?
44
+
45
+ File.expand_path(
46
+ File.join(logs_dir_path, "#{app_name}-%d{yyyy-MM-dd}.log.gz")
47
+ )
48
+ end
49
+
50
+ def ensure_paths!
51
+ FileUtils.mkdir_p(logs_dir_path)
52
+ FileUtils.touch(log_file_path)
53
+ end
54
+
55
+ def rollover
56
+ {
57
+ schedule: rollover_schedule,
58
+ size: rollover_size,
59
+ file_pattern: resolved_rolling_file_name_template
60
+ }
61
+ end
62
+ end
63
+ # class Configuration
64
+
65
+ class << self
66
+ def config
67
+ @config ||= Configuration.new
68
+ end
69
+
70
+ # Example:
71
+ # Log4j2LoggerBridge::Destination.configure do |c|
72
+ # c.project_dir_path = '/srv/myapp'
73
+ # c.rollover_size = '250M'
74
+ # end
75
+ def configure
76
+ yield(config)
77
+ config.ensure_paths!
78
+ config
79
+ end
80
+
81
+ def logs_dir_path
82
+ config.logs_dir_path
83
+ end
84
+
85
+ def log_file_path
86
+ config.log_file_path
87
+ end
88
+
89
+ def rollover
90
+ config.rollover
91
+ end
92
+
93
+ def rollover_schedule=(value)
94
+ config.rollover_schedule = value
95
+ end
96
+
97
+ def rollover_size=(value)
98
+ config.rollover_size = value
99
+ end
100
+
101
+ def rolling_file_name_template=(value)
102
+ config.rolling_file_name_template = value
103
+ end
104
+ end
105
+ # class << self
106
+ end
107
+ end
@@ -22,8 +22,8 @@ module Log4j2LoggerBridge
22
22
  DEFAULT_APP_NAME
23
23
  end
24
24
 
25
- def time_format
26
- DEFAULT_TIME_FORMAT
25
+ def timestamp_format
26
+ DEFAULT_TIMESTAMP_FORMAT
27
27
  end
28
28
 
29
29
  def ruby_log_format
@@ -24,6 +24,12 @@ module Log4j2LoggerBridge
24
24
 
25
25
  configure_log4j
26
26
 
27
+ Log4j2LoggerBridge::Log4j2RollingFile.apply!(
28
+ builder: @log4j_configuration,
29
+ root_logger: @root_logger,
30
+ layout: @layout
31
+ )
32
+
27
33
  @log4j2_initialized = true
28
34
  end
29
35
 
@@ -32,18 +38,21 @@ module Log4j2LoggerBridge
32
38
  @log4j2_context.updateLoggers
33
39
  end
34
40
 
41
+ def log4j_configuration
42
+ @log4j_configuration ||= init_config
43
+ end
44
+
35
45
  # rubocop: disable Metrics/AbcSize
36
46
  # rubocop: disable Metrics/MethodLength
37
- def log4j_configuration(
38
- config = ConfigurationBuilderFactory.newConfigurationBuilder)
39
- layout = config.newLayout('PatternLayout')
47
+ def init_config(config = ConfigurationBuilderFactory.newConfigurationBuilder)
48
+ @layout = config.newLayout('PatternLayout')
40
49
  .addAttribute('pattern', java_log_pattern)
41
50
  console = config.newAppender('stdout', 'CONSOLE')
42
- .addAttribute('target', ConsoleAppender::Target::SYSTEM_OUT).add(layout)
51
+ .addAttribute('target', ConsoleAppender::Target::SYSTEM_OUT).add(@layout)
43
52
  config.add(console)
44
- root = config.newRootLogger(Level::INFO)
53
+ @root_logger = config.newRootLogger(Level::INFO)
45
54
  .add(config.newAppenderRef('stdout'))
46
- config.add(root)
55
+ config.add(@root_logger)
47
56
  app_logger = config.newLogger(app_logger_name, Level::INFO)
48
57
  .add(config.newAppenderRef('stdout'))
49
58
  .addAttribute('additivity', false)
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+
4
+ # -*- mode: ruby -*-
5
+ # vi: set ft=ruby :
6
+
7
+ # The Log4j2LoggerBridge module
8
+ module Log4j2LoggerBridge
9
+ # The Log4j2RollingFile module
10
+ module Log4j2RollingFile
11
+ def apply!(builder:, root_logger:, layout:)
12
+ destination = Log4j2LoggerBridge::Destination.config
13
+ destination.ensure_paths!
14
+
15
+ cron_policy = build_cron_policy(builder, destination)
16
+ size_policy = build_size_policy(builder, destination)
17
+ policies = build_policies(builder, cron_policy, size_policy)
18
+
19
+ build_and_add_rolling_appender(builder, layout, destination, policies)
20
+ attach_rolling_appender_to_root(builder, root_logger)
21
+ end
22
+ module_function :apply!
23
+
24
+ def build_cron_policy(builder, destination)
25
+ cron = builder.newComponent('CronTriggeringPolicy')
26
+ cron.addAttribute('schedule', destination.rollover_schedule)
27
+ end
28
+ module_function :build_cron_policy
29
+
30
+ def build_size_policy(builder, destination)
31
+ size = builder.newComponent('SizeBasedTriggeringPolicy')
32
+ size.addAttribute('size', destination.rollover_size)
33
+ end
34
+ module_function :build_size_policy
35
+
36
+ def build_policies(builder, cron_policy, size_policy)
37
+ policies = builder.newComponent('Policies')
38
+ policies = policies.addComponent(cron_policy)
39
+ policies.addComponent(size_policy)
40
+ end
41
+ module_function :build_policies
42
+
43
+ def build_and_add_rolling_appender(builder, layout, destination, policies)
44
+ appender = builder.newAppender('rolling_file', 'RollingFile')
45
+ appender = appender.addAttribute('fileName', destination.log_file_path)
46
+ appender = appender.addAttribute(
47
+ 'filePattern',
48
+ destination.resolved_rolling_file_name_template
49
+ )
50
+ appender = appender.add(layout)
51
+ appender = appender.addComponent(policies)
52
+ builder.add(appender)
53
+ end
54
+ module_function :build_and_add_rolling_appender
55
+
56
+ def attach_rolling_appender_to_root(builder, root_logger)
57
+ root_logger = root_logger.addAttribute('additivity', false)
58
+ root_logger.add(builder.newAppenderRef('rolling_file'))
59
+ end
60
+ module_function :attach_rolling_appender_to_root
61
+ end
62
+ end
@@ -21,7 +21,7 @@ module Log4j2LoggerBridge
21
21
 
22
22
  def ruby_formatter(severity, datetime, _progname, msg)
23
23
  category = (Thread.current[:logging_category] || app_name).to_s
24
- timestamp = datetime.strftime(time_format)
24
+ timestamp = datetime.strftime(timestamp_format)
25
25
  format(ruby_log_format, timestamp: timestamp,
26
26
  severity: severity_label(severity), category: category, msg: msg)
27
27
  end
@@ -4,6 +4,7 @@
4
4
  # -*- mode: ruby -*-
5
5
  # vi: set ft=ruby :
6
6
 
7
+ # The Log4j2LoggerBridge module
7
8
  module Log4j2LoggerBridge
8
- VERSION = '1.0.1'.freeze
9
+ VERSION = '1.1.1'.freeze
9
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: log4j2_logger_bridge
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.1
5
5
  platform: java
6
6
  authors:
7
7
  - Nels Nelson
@@ -49,9 +49,11 @@ files:
49
49
  - lib/log4j2_logger_bridge.rb
50
50
  - lib/log4j2_logger_bridge/backend.rb
51
51
  - lib/log4j2_logger_bridge/constants.rb
52
+ - lib/log4j2_logger_bridge/destination.rb
52
53
  - lib/log4j2_logger_bridge/helpers.rb
53
54
  - lib/log4j2_logger_bridge/injection.rb
54
55
  - lib/log4j2_logger_bridge/log4j2_initialization_methods.rb
56
+ - lib/log4j2_logger_bridge/log4j2_rolling_file.rb
55
57
  - lib/log4j2_logger_bridge/proxy.rb
56
58
  - lib/log4j2_logger_bridge/ruby_logger_initialization_methods.rb
57
59
  - lib/log4j2_logger_bridge/utils.rb