logger 1.4.3 → 1.6.0

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
2
  SHA256:
3
- metadata.gz: be49be41055335fa90e79c26a714b7176077de04b414def791b1a9524169ad80
4
- data.tar.gz: f064246f7c9e483f96e9838ace1d079ce0d9acea770eb68d5a492a792157bb83
3
+ metadata.gz: 25185d093ab5e02f9933ce7d395e5929f1ad6f345301fbbbded9e720f67c16e4
4
+ data.tar.gz: 44d81cc02f511f27d70f3ece4bf99670e9b292a625b0984a47dc128c836385e9
5
5
  SHA512:
6
- metadata.gz: 8dc3387289106d3f98eda8384351d9486b8ad5bb21e5c58a3932595b101705600b1b66c64666eabab90a11f1d90a4b7f01e6f0ce658249bfb9ede51d76414ef4
7
- data.tar.gz: 693e411b78fc95e47d008b3ced6247606ebb641f7a17368321e8e0002fa450694267794a620fc76f949ac9cf2a7e5ac8b891416d7d4accb738f8c2c228421388
6
+ metadata.gz: 7055c80ccdc88976a5616b6a648ba877c6c2fba8a6d6c575ed88dda70a537ba2aa698574128b8824f68521715762cb38a7f2c1847713a6ba5ff7941241d99e24
7
+ data.tar.gz: 0c7d1bdf93857052c4fbbf64536445d2b2eefddb33b527d18bd2a6b638b0771b92b846b669d57b7500c280bd8fe4ae836ecad5e8b92517a0d2d4aaac66784182
data/lib/logger/errors.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # not used after 1.2.7. just for compat.
4
3
  class Logger
4
+ # not used after 1.2.7. just for compat.
5
5
  class Error < RuntimeError # :nodoc:
6
6
  end
7
7
  class ShiftingError < Error # :nodoc:
@@ -3,7 +3,8 @@
3
3
  class Logger
4
4
  # Default formatter for log messages.
5
5
  class Formatter
6
- Format = "%s, [%s#%d] %5s -- %s: %s\n"
6
+ Format = "%.1s, [%s #%d] %5s -- %s: %s\n"
7
+ DatetimeFormat = "%Y-%m-%dT%H:%M:%S.%6N"
7
8
 
8
9
  attr_accessor :datetime_format
9
10
 
@@ -12,14 +13,13 @@ class Logger
12
13
  end
13
14
 
14
15
  def call(severity, time, progname, msg)
15
- Format % [severity[0..0], format_datetime(time), Process.pid, severity, progname,
16
- msg2str(msg)]
16
+ sprintf(Format, severity, format_datetime(time), Process.pid, severity, progname, msg2str(msg))
17
17
  end
18
18
 
19
19
  private
20
20
 
21
21
  def format_datetime(time)
22
- time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ")
22
+ time.strftime(@datetime_format || DatetimeFormat)
23
23
  end
24
24
 
25
25
  def msg2str(msg)
@@ -79,8 +79,10 @@ class Logger
79
79
  def set_dev(log)
80
80
  if log.respond_to?(:write) and log.respond_to?(:close)
81
81
  @dev = log
82
- if log.respond_to?(:path)
83
- @filename = log.path
82
+ if log.respond_to?(:path) and path = log.path
83
+ if File.exist?(path)
84
+ @filename = path
85
+ end
84
86
  end
85
87
  else
86
88
  @dev = open_logfile(log)
@@ -135,7 +137,7 @@ class Logger
135
137
  end
136
138
  end
137
139
 
138
- if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
140
+ if /mswin|mingw|cygwin/ =~ RbConfig::CONFIG['host_os']
139
141
  def lock_shift_log
140
142
  yield
141
143
  end
@@ -15,5 +15,24 @@ class Logger
15
15
  FATAL = 4
16
16
  # An unknown message that should always be logged.
17
17
  UNKNOWN = 5
18
+
19
+ LEVELS = {
20
+ "debug" => DEBUG,
21
+ "info" => INFO,
22
+ "warn" => WARN,
23
+ "error" => ERROR,
24
+ "fatal" => FATAL,
25
+ "unknown" => UNKNOWN,
26
+ }
27
+ private_constant :LEVELS
28
+
29
+ def self.coerce(severity)
30
+ if severity.is_a?(Integer)
31
+ severity
32
+ else
33
+ key = severity.to_s.downcase
34
+ LEVELS[key] || raise(ArgumentError, "invalid log level: #{severity}")
35
+ end
36
+ end
18
37
  end
19
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Logger
4
- VERSION = "1.4.3"
4
+ VERSION = "1.6.0"
5
5
  end
data/lib/logger.rb CHANGED
@@ -10,7 +10,9 @@
10
10
  #
11
11
  # A simple system for logging messages. See Logger for more documentation.
12
12
 
13
+ require 'fiber'
13
14
  require 'monitor'
15
+ require 'rbconfig'
14
16
 
15
17
  require_relative 'logger/version'
16
18
  require_relative 'logger/formatter'
@@ -18,216 +20,352 @@ require_relative 'logger/log_device'
18
20
  require_relative 'logger/severity'
19
21
  require_relative 'logger/errors'
20
22
 
21
- # == Description
23
+ # \Class \Logger provides a simple but sophisticated logging utility that
24
+ # you can use to create one or more
25
+ # {event logs}[https://en.wikipedia.org/wiki/Logging_(software)#Event_logs]
26
+ # for your program.
27
+ # Each such log contains a chronological sequence of entries
28
+ # that provides a record of the program's activities.
22
29
  #
23
- # The Logger class provides a simple but sophisticated logging utility that
24
- # you can use to output messages.
30
+ # == About the Examples
25
31
  #
26
- # The messages have associated levels, such as +INFO+ or +ERROR+ that indicate
27
- # their importance. You can then give the Logger a level, and only messages
28
- # at that level or higher will be printed.
32
+ # All examples on this page assume that \Logger has been required:
29
33
  #
30
- # The levels are:
34
+ # require 'logger'
31
35
  #
32
- # +UNKNOWN+:: An unknown message that should always be logged.
33
- # +FATAL+:: An unhandleable error that results in a program crash.
34
- # +ERROR+:: A handleable error condition.
35
- # +WARN+:: A warning.
36
- # +INFO+:: Generic (useful) information about system operation.
37
- # +DEBUG+:: Low-level information for developers.
36
+ # == Synopsis
38
37
  #
39
- # For instance, in a production system, you may have your Logger set to
40
- # +INFO+ or even +WARN+.
41
- # When you are developing the system, however, you probably
42
- # want to know about the program's internal state, and would set the Logger to
43
- # +DEBUG+.
38
+ # Create a log with Logger.new:
44
39
  #
45
- # *Note*: Logger does not escape or sanitize any messages passed to it.
46
- # Developers should be aware of when potentially malicious data (user-input)
47
- # is passed to Logger, and manually escape the untrusted data:
40
+ # # Single log file.
41
+ # logger = Logger.new('t.log')
42
+ # # Size-based rotated logging: 3 10-megabyte files.
43
+ # logger = Logger.new('t.log', 3, 10485760)
44
+ # # Period-based rotated logging: daily (also allowed: 'weekly', 'monthly').
45
+ # logger = Logger.new('t.log', 'daily')
46
+ # # Log to an IO stream.
47
+ # logger = Logger.new($stdout)
48
48
  #
49
- # logger.info("User-input: #{input.dump}")
50
- # logger.info("User-input: %p" % input)
49
+ # Add entries (level, message) with Logger#add:
51
50
  #
52
- # You can use #formatter= for escaping all data.
51
+ # logger.add(Logger::DEBUG, 'Maximal debugging info')
52
+ # logger.add(Logger::INFO, 'Non-error information')
53
+ # logger.add(Logger::WARN, 'Non-error warning')
54
+ # logger.add(Logger::ERROR, 'Non-fatal error')
55
+ # logger.add(Logger::FATAL, 'Fatal error')
56
+ # logger.add(Logger::UNKNOWN, 'Most severe')
53
57
  #
54
- # original_formatter = Logger::Formatter.new
55
- # logger.formatter = proc { |severity, datetime, progname, msg|
56
- # original_formatter.call(severity, datetime, progname, msg.dump)
57
- # }
58
- # logger.info(input)
58
+ # Close the log with Logger#close:
59
59
  #
60
- # === Example
60
+ # logger.close
61
61
  #
62
- # This creates a Logger that outputs to the standard output stream, with a
63
- # level of +WARN+:
62
+ # == Entries
64
63
  #
65
- # require 'logger'
64
+ # You can add entries with method Logger#add:
65
+ #
66
+ # logger.add(Logger::DEBUG, 'Maximal debugging info')
67
+ # logger.add(Logger::INFO, 'Non-error information')
68
+ # logger.add(Logger::WARN, 'Non-error warning')
69
+ # logger.add(Logger::ERROR, 'Non-fatal error')
70
+ # logger.add(Logger::FATAL, 'Fatal error')
71
+ # logger.add(Logger::UNKNOWN, 'Most severe')
72
+ #
73
+ # These shorthand methods also add entries:
74
+ #
75
+ # logger.debug('Maximal debugging info')
76
+ # logger.info('Non-error information')
77
+ # logger.warn('Non-error warning')
78
+ # logger.error('Non-fatal error')
79
+ # logger.fatal('Fatal error')
80
+ # logger.unknown('Most severe')
81
+ #
82
+ # When you call any of these methods,
83
+ # the entry may or may not be written to the log,
84
+ # depending on the entry's severity and on the log level;
85
+ # see {Log Level}[rdoc-ref:Logger@Log+Level]
86
+ #
87
+ # An entry always has:
88
+ #
89
+ # - A severity (the required argument to #add).
90
+ # - An automatically created timestamp.
91
+ #
92
+ # And may also have:
93
+ #
94
+ # - A message.
95
+ # - A program name.
96
+ #
97
+ # Example:
98
+ #
99
+ # logger = Logger.new($stdout)
100
+ # logger.add(Logger::INFO, 'My message.', 'mung')
101
+ # # => I, [2022-05-07T17:21:46.536234 #20536] INFO -- mung: My message.
102
+ #
103
+ # The default format for an entry is:
104
+ #
105
+ # "%s, [%s #%d] %5s -- %s: %s\n"
106
+ #
107
+ # where the values to be formatted are:
108
+ #
109
+ # - \Severity (one letter).
110
+ # - Timestamp.
111
+ # - Process id.
112
+ # - \Severity (word).
113
+ # - Program name.
114
+ # - Message.
115
+ #
116
+ # You can use a different entry format by:
117
+ #
118
+ # - Setting a custom format proc (affects following entries);
119
+ # see {formatter=}[Logger.html#attribute-i-formatter].
120
+ # - Calling any of the methods above with a block
121
+ # (affects only the one entry).
122
+ # Doing so can have two benefits:
123
+ #
124
+ # - Context: the block can evaluate the entire program context
125
+ # and create a context-dependent message.
126
+ # - Performance: the block is not evaluated unless the log level
127
+ # permits the entry actually to be written:
128
+ #
129
+ # logger.error { my_slow_message_generator }
130
+ #
131
+ # Contrast this with the string form, where the string is
132
+ # always evaluated, regardless of the log level:
133
+ #
134
+ # logger.error("#{my_slow_message_generator}")
135
+ #
136
+ # === \Severity
137
+ #
138
+ # The severity of a log entry has two effects:
139
+ #
140
+ # - Determines whether the entry is selected for inclusion in the log;
141
+ # see {Log Level}[rdoc-ref:Logger@Log+Level].
142
+ # - Indicates to any log reader (whether a person or a program)
143
+ # the relative importance of the entry.
144
+ #
145
+ # === Timestamp
66
146
  #
67
- # logger = Logger.new(STDOUT)
68
- # logger.level = Logger::WARN
147
+ # The timestamp for a log entry is generated automatically
148
+ # when the entry is created.
69
149
  #
70
- # logger.debug("Created logger")
71
- # logger.info("Program started")
72
- # logger.warn("Nothing to do!")
150
+ # The logged timestamp is formatted by method
151
+ # {Time#strftime}[https://docs.ruby-lang.org/en/master/Time.html#method-i-strftime]
152
+ # using this format string:
73
153
  #
74
- # path = "a_non_existent_file"
154
+ # '%Y-%m-%dT%H:%M:%S.%6N'
75
155
  #
76
- # begin
77
- # File.foreach(path) do |line|
78
- # unless line =~ /^(\w+) = (.*)$/
79
- # logger.error("Line in wrong format: #{line.chomp}")
80
- # end
81
- # end
82
- # rescue => err
83
- # logger.fatal("Caught exception; exiting")
84
- # logger.fatal(err)
85
- # end
156
+ # Example:
86
157
  #
87
- # Because the Logger's level is set to +WARN+, only the warning, error, and
88
- # fatal messages are recorded. The debug and info messages are silently
89
- # discarded.
158
+ # logger = Logger.new($stdout)
159
+ # logger.add(Logger::INFO)
160
+ # # => I, [2022-05-07T17:04:32.318331 #20536] INFO -- : nil
90
161
  #
91
- # === Features
162
+ # You can set a different format using method #datetime_format=.
92
163
  #
93
- # There are several interesting features that Logger provides, like
94
- # auto-rolling of log files, setting the format of log messages, and
95
- # specifying a program name in conjunction with the message. The next section
96
- # shows you how to achieve these things.
164
+ # === Message
97
165
  #
166
+ # The message is an optional argument to an entry method:
98
167
  #
99
- # == HOWTOs
168
+ # logger = Logger.new($stdout)
169
+ # logger.add(Logger::INFO, 'My message')
170
+ # # => I, [2022-05-07T18:15:37.647581 #20536] INFO -- : My message
100
171
  #
101
- # === How to create a logger
172
+ # For the default entry formatter, <tt>Logger::Formatter</tt>,
173
+ # the message object may be:
102
174
  #
103
- # The options below give you various choices, in more or less increasing
104
- # complexity.
175
+ # - A string: used as-is.
176
+ # - An Exception: <tt>message.message</tt> is used.
177
+ # - Anything else: <tt>message.inspect</tt> is used.
105
178
  #
106
- # 1. Create a logger which logs messages to STDERR/STDOUT.
179
+ # *Note*: Logger::Formatter does not escape or sanitize
180
+ # the message passed to it.
181
+ # Developers should be aware that malicious data (user input)
182
+ # may be in the message, and should explicitly escape untrusted data.
107
183
  #
108
- # logger = Logger.new(STDERR)
109
- # logger = Logger.new(STDOUT)
184
+ # You can use a custom formatter to escape message data;
185
+ # see the example at {formatter=}[Logger.html#attribute-i-formatter].
110
186
  #
111
- # 2. Create a logger for the file which has the specified name.
187
+ # === Program Name
112
188
  #
113
- # logger = Logger.new('logfile.log')
189
+ # The program name is an optional argument to an entry method:
114
190
  #
115
- # 3. Create a logger for the specified file.
191
+ # logger = Logger.new($stdout)
192
+ # logger.add(Logger::INFO, 'My message', 'mung')
193
+ # # => I, [2022-05-07T18:17:38.084716 #20536] INFO -- mung: My message
116
194
  #
117
- # file = File.open('foo.log', File::WRONLY | File::APPEND)
118
- # # To create new logfile, add File::CREAT like:
119
- # # file = File.open('foo.log', File::WRONLY | File::APPEND | File::CREAT)
120
- # logger = Logger.new(file)
195
+ # The default program name for a new logger may be set in the call to
196
+ # Logger.new via optional keyword argument +progname+:
121
197
  #
122
- # 4. Create a logger which ages the logfile once it reaches a certain size.
123
- # Leave 10 "old" log files where each file is about 1,024,000 bytes.
198
+ # logger = Logger.new('t.log', progname: 'mung')
124
199
  #
125
- # logger = Logger.new('foo.log', 10, 1024000)
200
+ # The default program name for an existing logger may be set
201
+ # by a call to method #progname=:
126
202
  #
127
- # 5. Create a logger which ages the logfile daily/weekly/monthly.
203
+ # logger.progname = 'mung'
128
204
  #
129
- # logger = Logger.new('foo.log', 'daily')
130
- # logger = Logger.new('foo.log', 'weekly')
131
- # logger = Logger.new('foo.log', 'monthly')
205
+ # The current program name may be retrieved with method
206
+ # {progname}[Logger.html#attribute-i-progname]:
132
207
  #
133
- # === How to log a message
208
+ # logger.progname # => "mung"
134
209
  #
135
- # Notice the different methods (+fatal+, +error+, +info+) being used to log
136
- # messages of various levels? Other methods in this family are +warn+ and
137
- # +debug+. +add+ is used below to log a message of an arbitrary (perhaps
138
- # dynamic) level.
210
+ # == Log Level
139
211
  #
140
- # 1. Message in a block.
212
+ # The log level setting determines whether an entry is actually
213
+ # written to the log, based on the entry's severity.
141
214
  #
142
- # logger.fatal { "Argument 'foo' not given." }
215
+ # These are the defined severities (least severe to most severe):
143
216
  #
144
- # 2. Message as a string.
217
+ # logger = Logger.new($stdout)
218
+ # logger.add(Logger::DEBUG, 'Maximal debugging info')
219
+ # # => D, [2022-05-07T17:57:41.776220 #20536] DEBUG -- : Maximal debugging info
220
+ # logger.add(Logger::INFO, 'Non-error information')
221
+ # # => I, [2022-05-07T17:59:14.349167 #20536] INFO -- : Non-error information
222
+ # logger.add(Logger::WARN, 'Non-error warning')
223
+ # # => W, [2022-05-07T18:00:45.337538 #20536] WARN -- : Non-error warning
224
+ # logger.add(Logger::ERROR, 'Non-fatal error')
225
+ # # => E, [2022-05-07T18:02:41.592912 #20536] ERROR -- : Non-fatal error
226
+ # logger.add(Logger::FATAL, 'Fatal error')
227
+ # # => F, [2022-05-07T18:05:24.703931 #20536] FATAL -- : Fatal error
228
+ # logger.add(Logger::UNKNOWN, 'Most severe')
229
+ # # => A, [2022-05-07T18:07:54.657491 #20536] ANY -- : Most severe
145
230
  #
146
- # logger.error "Argument #{@foo} mismatch."
231
+ # The default initial level setting is Logger::DEBUG, the lowest level,
232
+ # which means that all entries are to be written, regardless of severity:
147
233
  #
148
- # 3. With progname.
234
+ # logger = Logger.new($stdout)
235
+ # logger.level # => 0
236
+ # logger.add(0, "My message")
237
+ # # => D, [2022-05-11T15:10:59.773668 #20536] DEBUG -- : My message
149
238
  #
150
- # logger.info('initialize') { "Initializing..." }
239
+ # You can specify a different setting in a new logger
240
+ # using keyword argument +level+ with an appropriate value:
151
241
  #
152
- # 4. With severity.
242
+ # logger = Logger.new($stdout, level: Logger::ERROR)
243
+ # logger = Logger.new($stdout, level: 'error')
244
+ # logger = Logger.new($stdout, level: :error)
245
+ # logger.level # => 3
153
246
  #
154
- # logger.add(Logger::FATAL) { 'Fatal error!' }
247
+ # With this level, entries with severity Logger::ERROR and higher
248
+ # are written, while those with lower severities are not written:
155
249
  #
156
- # The block form allows you to create potentially complex log messages,
157
- # but to delay their evaluation until and unless the message is
158
- # logged. For example, if we have the following:
250
+ # logger = Logger.new($stdout, level: Logger::ERROR)
251
+ # logger.add(3)
252
+ # # => E, [2022-05-11T15:17:20.933362 #20536] ERROR -- : nil
253
+ # logger.add(2) # Silent.
159
254
  #
160
- # logger.debug { "This is a " + potentially + " expensive operation" }
255
+ # You can set the log level for an existing logger
256
+ # with method #level=:
161
257
  #
162
- # If the logger's level is +INFO+ or higher, no debug messages will be logged,
163
- # and the entire block will not even be evaluated. Compare to this:
258
+ # logger.level = Logger::ERROR
164
259
  #
165
- # logger.debug("This is a " + potentially + " expensive operation")
260
+ # These shorthand methods also set the level:
166
261
  #
167
- # Here, the string concatenation is done every time, even if the log
168
- # level is not set to show the debug message.
262
+ # logger.debug! # => 0
263
+ # logger.info! # => 1
264
+ # logger.warn! # => 2
265
+ # logger.error! # => 3
266
+ # logger.fatal! # => 4
169
267
  #
170
- # === How to close a logger
268
+ # You can retrieve the log level with method #level.
171
269
  #
172
- # logger.close
270
+ # logger.level = Logger::ERROR
271
+ # logger.level # => 3
173
272
  #
174
- # === Setting severity threshold
273
+ # These methods return whether a given
274
+ # level is to be written:
175
275
  #
176
- # 1. Original interface.
276
+ # logger.level = Logger::ERROR
277
+ # logger.debug? # => false
278
+ # logger.info? # => false
279
+ # logger.warn? # => false
280
+ # logger.error? # => true
281
+ # logger.fatal? # => true
177
282
  #
178
- # logger.sev_threshold = Logger::WARN
283
+ # == Log File Rotation
179
284
  #
180
- # 2. Log4r (somewhat) compatible interface.
285
+ # By default, a log file is a single file that grows indefinitely
286
+ # (until explicitly closed); there is no file rotation.
181
287
  #
182
- # logger.level = Logger::INFO
288
+ # To keep log files to a manageable size,
289
+ # you can use _log_ _file_ _rotation_, which uses multiple log files:
183
290
  #
184
- # # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
291
+ # - Each log file has entries for a non-overlapping
292
+ # time interval.
293
+ # - Only the most recent log file is open and active;
294
+ # the others are closed and inactive.
185
295
  #
186
- # 3. Symbol or String (case insensitive)
296
+ # === Size-Based Rotation
187
297
  #
188
- # logger.level = :info
189
- # logger.level = 'INFO'
298
+ # For size-based log file rotation, call Logger.new with:
190
299
  #
191
- # # :debug < :info < :warn < :error < :fatal < :unknown
300
+ # - Argument +logdev+ as a file path.
301
+ # - Argument +shift_age+ with a positive integer:
302
+ # the number of log files to be in the rotation.
303
+ # - Argument +shift_size+ as a positive integer:
304
+ # the maximum size (in bytes) of each log file;
305
+ # defaults to 1048576 (1 megabyte).
192
306
  #
193
- # 4. Constructor
307
+ # Examples:
194
308
  #
195
- # Logger.new(logdev, level: Logger::INFO)
196
- # Logger.new(logdev, level: :info)
197
- # Logger.new(logdev, level: 'INFO')
309
+ # logger = Logger.new('t.log', 3) # Three 1-megabyte files.
310
+ # logger = Logger.new('t.log', 5, 10485760) # Five 10-megabyte files.
198
311
  #
199
- # == Format
312
+ # For these examples, suppose:
200
313
  #
201
- # Log messages are rendered in the output stream in a certain format by
202
- # default. The default format and a sample are shown below:
314
+ # logger = Logger.new('t.log', 3)
203
315
  #
204
- # Log format:
205
- # SeverityID, [DateTime #pid] SeverityLabel -- ProgName: message
316
+ # Logging begins in the new log file, +t.log+;
317
+ # the log file is "full" and ready for rotation
318
+ # when a new entry would cause its size to exceed +shift_size+.
206
319
  #
207
- # Log sample:
208
- # I, [1999-03-03T02:34:24.895701 #19074] INFO -- Main: info.
320
+ # The first time +t.log+ is full:
209
321
  #
210
- # You may change the date and time format via #datetime_format=.
322
+ # - +t.log+ is closed and renamed to +t.log.0+.
323
+ # - A new file +t.log+ is opened.
211
324
  #
212
- # logger.datetime_format = '%Y-%m-%d %H:%M:%S'
213
- # # e.g. "2004-01-03 00:54:26"
325
+ # The second time +t.log+ is full:
214
326
  #
215
- # or via the constructor.
327
+ # - +t.log.0 is renamed as +t.log.1+.
328
+ # - +t.log+ is closed and renamed to +t.log.0+.
329
+ # - A new file +t.log+ is opened.
216
330
  #
217
- # Logger.new(logdev, datetime_format: '%Y-%m-%d %H:%M:%S')
331
+ # Each subsequent time that +t.log+ is full,
332
+ # the log files are rotated:
218
333
  #
219
- # Or, you may change the overall format via the #formatter= method.
334
+ # - +t.log.1+ is removed.
335
+ # - +t.log.0 is renamed as +t.log.1+.
336
+ # - +t.log+ is closed and renamed to +t.log.0+.
337
+ # - A new file +t.log+ is opened.
220
338
  #
221
- # logger.formatter = proc do |severity, datetime, progname, msg|
222
- # "#{datetime}: #{msg}\n"
223
- # end
224
- # # e.g. "2005-09-22 08:51:08 +0900: hello world"
339
+ # === Periodic Rotation
225
340
  #
226
- # or via the constructor.
341
+ # For periodic rotation, call Logger.new with:
227
342
  #
228
- # Logger.new(logdev, formatter: proc {|severity, datetime, progname, msg|
229
- # "#{datetime}: #{msg}\n"
230
- # })
343
+ # - Argument +logdev+ as a file path.
344
+ # - Argument +shift_age+ as a string period indicator.
345
+ #
346
+ # Examples:
347
+ #
348
+ # logger = Logger.new('t.log', 'daily') # Rotate log files daily.
349
+ # logger = Logger.new('t.log', 'weekly') # Rotate log files weekly.
350
+ # logger = Logger.new('t.log', 'monthly') # Rotate log files monthly.
351
+ #
352
+ # Example:
353
+ #
354
+ # logger = Logger.new('t.log', 'daily')
355
+ #
356
+ # When the given period expires:
357
+ #
358
+ # - The base log file, +t.log+ is closed and renamed
359
+ # with a date-based suffix such as +t.log.20220509+.
360
+ # - A new log file +t.log+ is opened.
361
+ # - Nothing is removed.
362
+ #
363
+ # The default format for the suffix is <tt>'%Y%m%d'</tt>,
364
+ # which produces a suffix similar to the one above.
365
+ # You can set a different format using create-time option
366
+ # +shift_period_suffix+;
367
+ # see details and suggestions at
368
+ # {Time#strftime}[https://docs.ruby-lang.org/en/master/Time.html#method-i-strftime].
231
369
  #
232
370
  class Logger
233
371
  _, name, rev = %w$Id$
@@ -242,30 +380,40 @@ class Logger
242
380
  include Severity
243
381
 
244
382
  # Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
245
- attr_reader :level
383
+ def level
384
+ @level_override[Fiber.current] || @level
385
+ end
246
386
 
247
- # Set logging severity threshold.
387
+ # Sets the log level; returns +severity+.
388
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
389
+ #
390
+ # Argument +severity+ may be an integer, a string, or a symbol:
391
+ #
392
+ # logger.level = Logger::ERROR # => 3
393
+ # logger.level = 3 # => 3
394
+ # logger.level = 'error' # => "error"
395
+ # logger.level = :error # => :error
396
+ #
397
+ # Logger#sev_threshold= is an alias for Logger#level=.
248
398
  #
249
- # +severity+:: The Severity of the log message.
250
399
  def level=(severity)
251
- if severity.is_a?(Integer)
252
- @level = severity
253
- else
254
- case severity.to_s.downcase
255
- when 'debug'
256
- @level = DEBUG
257
- when 'info'
258
- @level = INFO
259
- when 'warn'
260
- @level = WARN
261
- when 'error'
262
- @level = ERROR
263
- when 'fatal'
264
- @level = FATAL
265
- when 'unknown'
266
- @level = UNKNOWN
400
+ @level = Severity.coerce(severity)
401
+ end
402
+
403
+ # Adjust the log level during the block execution for the current Fiber only
404
+ #
405
+ # logger.with_level(:debug) do
406
+ # logger.debug { "Hello" }
407
+ # end
408
+ def with_level(severity)
409
+ prev, @level_override[Fiber.current] = level, Severity.coerce(severity)
410
+ begin
411
+ yield
412
+ ensure
413
+ if prev
414
+ @level_override[Fiber.current] = prev
267
415
  else
268
- raise ArgumentError, "invalid log level: #{severity}"
416
+ @level_override.delete(Fiber.current)
269
417
  end
270
418
  end
271
419
  end
@@ -273,109 +421,159 @@ class Logger
273
421
  # Program name to include in log messages.
274
422
  attr_accessor :progname
275
423
 
276
- # Set date-time format.
424
+ # Sets the date-time format.
425
+ #
426
+ # Argument +datetime_format+ should be either of these:
427
+ #
428
+ # - A string suitable for use as a format for method
429
+ # {Time#strftime}[https://docs.ruby-lang.org/en/master/Time.html#method-i-strftime].
430
+ # - +nil+: the logger uses <tt>'%Y-%m-%dT%H:%M:%S.%6N'</tt>.
277
431
  #
278
- # +datetime_format+:: A string suitable for passing to +strftime+.
279
432
  def datetime_format=(datetime_format)
280
433
  @default_formatter.datetime_format = datetime_format
281
434
  end
282
435
 
283
- # Returns the date format being used. See #datetime_format=
436
+ # Returns the date-time format; see #datetime_format=.
437
+ #
284
438
  def datetime_format
285
439
  @default_formatter.datetime_format
286
440
  end
287
441
 
288
- # Logging formatter, as a +Proc+ that will take four arguments and
289
- # return the formatted message. The arguments are:
442
+ # Sets or retrieves the logger entry formatter proc.
443
+ #
444
+ # When +formatter+ is +nil+, the logger uses Logger::Formatter.
445
+ #
446
+ # When +formatter+ is a proc, a new entry is formatted by the proc,
447
+ # which is called with four arguments:
448
+ #
449
+ # - +severity+: The severity of the entry.
450
+ # - +time+: A Time object representing the entry's timestamp.
451
+ # - +progname+: The program name for the entry.
452
+ # - +msg+: The message for the entry (string or string-convertible object).
453
+ #
454
+ # The proc should return a string containing the formatted entry.
290
455
  #
291
- # +severity+:: The Severity of the log message.
292
- # +time+:: A Time instance representing when the message was logged.
293
- # +progname+:: The #progname configured, or passed to the logger method.
294
- # +msg+:: The _Object_ the user passed to the log message; not necessarily a
295
- # String.
456
+ # This custom formatter uses
457
+ # {String#dump}[https://docs.ruby-lang.org/en/master/String.html#method-i-dump]
458
+ # to escape the message string:
459
+ #
460
+ # logger = Logger.new($stdout, progname: 'mung')
461
+ # original_formatter = logger.formatter || Logger::Formatter.new
462
+ # logger.formatter = proc { |severity, time, progname, msg|
463
+ # original_formatter.call(severity, time, progname, msg.dump)
464
+ # }
465
+ # logger.add(Logger::INFO, "hello \n ''")
466
+ # logger.add(Logger::INFO, "\f\x00\xff\\\"")
467
+ #
468
+ # Output:
469
+ #
470
+ # I, [2022-05-13T13:16:29.637488 #8492] INFO -- mung: "hello \n ''"
471
+ # I, [2022-05-13T13:16:29.637610 #8492] INFO -- mung: "\f\x00\xFF\\\""
296
472
  #
297
- # The block should return an Object that can be written to the logging
298
- # device via +write+. The default formatter is used when no formatter is
299
- # set.
300
473
  attr_accessor :formatter
301
474
 
302
475
  alias sev_threshold level
303
476
  alias sev_threshold= level=
304
477
 
305
- # Returns +true+ iff the current severity level allows for the printing of
306
- # +DEBUG+ messages.
478
+ # Returns +true+ if the log level allows entries with severity
479
+ # Logger::DEBUG to be written, +false+ otherwise.
480
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
481
+ #
307
482
  def debug?; level <= DEBUG; end
308
483
 
309
- # Sets the severity to DEBUG.
484
+ # Sets the log level to Logger::DEBUG.
485
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
486
+ #
310
487
  def debug!; self.level = DEBUG; end
311
488
 
312
- # Returns +true+ iff the current severity level allows for the printing of
313
- # +INFO+ messages.
489
+ # Returns +true+ if the log level allows entries with severity
490
+ # Logger::INFO to be written, +false+ otherwise.
491
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
492
+ #
314
493
  def info?; level <= INFO; end
315
494
 
316
- # Sets the severity to INFO.
495
+ # Sets the log level to Logger::INFO.
496
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
497
+ #
317
498
  def info!; self.level = INFO; end
318
499
 
319
- # Returns +true+ iff the current severity level allows for the printing of
320
- # +WARN+ messages.
500
+ # Returns +true+ if the log level allows entries with severity
501
+ # Logger::WARN to be written, +false+ otherwise.
502
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
503
+ #
321
504
  def warn?; level <= WARN; end
322
505
 
323
- # Sets the severity to WARN.
506
+ # Sets the log level to Logger::WARN.
507
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
508
+ #
324
509
  def warn!; self.level = WARN; end
325
510
 
326
- # Returns +true+ iff the current severity level allows for the printing of
327
- # +ERROR+ messages.
511
+ # Returns +true+ if the log level allows entries with severity
512
+ # Logger::ERROR to be written, +false+ otherwise.
513
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
514
+ #
328
515
  def error?; level <= ERROR; end
329
516
 
330
- # Sets the severity to ERROR.
517
+ # Sets the log level to Logger::ERROR.
518
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
519
+ #
331
520
  def error!; self.level = ERROR; end
332
521
 
333
- # Returns +true+ iff the current severity level allows for the printing of
334
- # +FATAL+ messages.
522
+ # Returns +true+ if the log level allows entries with severity
523
+ # Logger::FATAL to be written, +false+ otherwise.
524
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
525
+ #
335
526
  def fatal?; level <= FATAL; end
336
527
 
337
- # Sets the severity to FATAL.
528
+ # Sets the log level to Logger::FATAL.
529
+ # See {Log Level}[rdoc-ref:Logger@Log+Level].
530
+ #
338
531
  def fatal!; self.level = FATAL; end
339
532
 
340
- #
341
533
  # :call-seq:
342
- # Logger.new(logdev, shift_age = 0, shift_size = 1048576)
343
- # Logger.new(logdev, shift_age = 'weekly')
344
- # Logger.new(logdev, level: :info)
345
- # Logger.new(logdev, progname: 'progname')
346
- # Logger.new(logdev, formatter: formatter)
347
- # Logger.new(logdev, datetime_format: '%Y-%m-%d %H:%M:%S')
348
- #
349
- # === Args
350
- #
351
- # +logdev+::
352
- # The log device. This is a filename (String), IO object (typically
353
- # +STDOUT+, +STDERR+, or an open file), +nil+ (it writes nothing) or
354
- # +File::NULL+ (same as +nil+).
355
- # +shift_age+::
356
- # Number of old log files to keep, *or* frequency of rotation (+daily+,
357
- # +weekly+ or +monthly+). Default value is 0, which disables log file
358
- # rotation.
359
- # +shift_size+::
360
- # Maximum logfile size in bytes (only applies when +shift_age+ is a positive
361
- # Integer). Defaults to +1048576+ (1MB).
362
- # +level+::
363
- # Logging severity threshold. Default values is Logger::DEBUG.
364
- # +progname+::
365
- # Program name to include in log messages. Default value is nil.
366
- # +formatter+::
367
- # Logging formatter. Default values is an instance of Logger::Formatter.
368
- # +datetime_format+::
369
- # Date and time format. Default value is '%Y-%m-%d %H:%M:%S'.
370
- # +binmode+::
371
- # Use binary mode on the log device. Default value is false.
372
- # +shift_period_suffix+::
373
- # The log file suffix format for +daily+, +weekly+ or +monthly+ rotation.
374
- # Default is '%Y%m%d'.
375
- #
376
- # === Description
377
- #
378
- # Create an instance.
534
+ # Logger.new(logdev, shift_age = 0, shift_size = 1048576, **options)
535
+ #
536
+ # With the single argument +logdev+,
537
+ # returns a new logger with all default options:
538
+ #
539
+ # Logger.new('t.log') # => #<Logger:0x000001e685dc6ac8>
540
+ #
541
+ # Argument +logdev+ must be one of:
542
+ #
543
+ # - A string filepath: entries are to be written
544
+ # to the file at that path; if the file at that path exists,
545
+ # new entries are appended.
546
+ # - An IO stream (typically +$stdout+, +$stderr+. or an open file):
547
+ # entries are to be written to the given stream.
548
+ # - +nil+ or +File::NULL+: no entries are to be written.
549
+ #
550
+ # Examples:
551
+ #
552
+ # Logger.new('t.log')
553
+ # Logger.new($stdout)
554
+ #
555
+ # The keyword options are:
556
+ #
557
+ # - +level+: sets the log level; default value is Logger::DEBUG.
558
+ # See {Log Level}[rdoc-ref:Logger@Log+Level]:
559
+ #
560
+ # Logger.new('t.log', level: Logger::ERROR)
561
+ #
562
+ # - +progname+: sets the default program name; default is +nil+.
563
+ # See {Program Name}[rdoc-ref:Logger@Program+Name]:
564
+ #
565
+ # Logger.new('t.log', progname: 'mung')
566
+ #
567
+ # - +formatter+: sets the entry formatter; default is +nil+.
568
+ # See {formatter=}[Logger.html#attribute-i-formatter].
569
+ # - +datetime_format+: sets the format for entry timestamp;
570
+ # default is +nil+.
571
+ # See #datetime_format=.
572
+ # - +binmode+: sets whether the logger writes in binary mode;
573
+ # default is +false+.
574
+ # - +shift_period_suffix+: sets the format for the filename suffix
575
+ # for periodic log file rotation; default is <tt>'%Y%m%d'</tt>.
576
+ # See {Periodic Rotation}[rdoc-ref:Logger@Periodic+Rotation].
379
577
  #
380
578
  def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
381
579
  progname: nil, formatter: nil, datetime_format: nil,
@@ -386,6 +584,7 @@ class Logger
386
584
  self.datetime_format = datetime_format
387
585
  self.formatter = formatter
388
586
  @logdev = nil
587
+ @level_override = {}
389
588
  if logdev && logdev != File::NULL
390
589
  @logdev = LogDevice.new(logdev, shift_age: shift_age,
391
590
  shift_size: shift_size,
@@ -394,67 +593,60 @@ class Logger
394
593
  end
395
594
  end
396
595
 
397
- #
398
- # :call-seq:
399
- # Logger#reopen
400
- # Logger#reopen(logdev)
401
- #
402
- # === Args
403
- #
404
- # +logdev+::
405
- # The log device. This is a filename (String) or IO object (typically
406
- # +STDOUT+, +STDERR+, or an open file). reopen the same filename if
407
- # it is +nil+, do nothing for IO. Default is +nil+.
408
- #
409
- # === Description
410
- #
411
- # Reopen a log device.
596
+ # Sets the logger's output stream:
597
+ #
598
+ # - If +logdev+ is +nil+, reopens the current output stream.
599
+ # - If +logdev+ is a filepath, opens the indicated file for append.
600
+ # - If +logdev+ is an IO stream
601
+ # (usually <tt>$stdout</tt>, <tt>$stderr</tt>, or an open File object),
602
+ # opens the stream for append.
603
+ #
604
+ # Example:
605
+ #
606
+ # logger = Logger.new('t.log')
607
+ # logger.add(Logger::ERROR, 'one')
608
+ # logger.close
609
+ # logger.add(Logger::ERROR, 'two') # Prints 'log writing failed. closed stream'
610
+ # logger.reopen
611
+ # logger.add(Logger::ERROR, 'three')
612
+ # logger.close
613
+ # File.readlines('t.log')
614
+ # # =>
615
+ # # ["# Logfile created on 2022-05-12 14:21:19 -0500 by logger.rb/v1.5.0\n",
616
+ # # "E, [2022-05-12T14:21:27.596726 #22428] ERROR -- : one\n",
617
+ # # "E, [2022-05-12T14:23:05.847241 #22428] ERROR -- : three\n"]
412
618
  #
413
619
  def reopen(logdev = nil)
414
620
  @logdev&.reopen(logdev)
415
621
  self
416
622
  end
417
623
 
624
+ # Creates a log entry, which may or may not be written to the log,
625
+ # depending on the entry's severity and on the log level.
626
+ # See {Log Level}[rdoc-ref:Logger@Log+Level]
627
+ # and {Entries}[rdoc-ref:Logger@Entries] for details.
418
628
  #
419
- # :call-seq:
420
- # Logger#add(severity, message = nil, progname = nil) { ... }
421
- #
422
- # === Args
423
- #
424
- # +severity+::
425
- # Severity. Constants are defined in Logger namespace: +DEBUG+, +INFO+,
426
- # +WARN+, +ERROR+, +FATAL+, or +UNKNOWN+.
427
- # +message+::
428
- # The log message. A String or Exception.
429
- # +progname+::
430
- # Program name string. Can be omitted. Treated as a message if no
431
- # +message+ and +block+ are given.
432
- # +block+::
433
- # Can be omitted. Called to get a message string if +message+ is nil.
434
- #
435
- # === Return
629
+ # Examples:
436
630
  #
437
- # When the given severity is not high enough (for this particular logger),
438
- # log no message, and return +true+.
631
+ # logger = Logger.new($stdout, progname: 'mung')
632
+ # logger.add(Logger::INFO)
633
+ # logger.add(Logger::ERROR, 'No good')
634
+ # logger.add(Logger::ERROR, 'No good', 'gnum')
439
635
  #
440
- # === Description
636
+ # Output:
441
637
  #
442
- # Log a message if the given severity is high enough. This is the generic
443
- # logging method. Users will be more inclined to use #debug, #info, #warn,
444
- # #error, and #fatal.
638
+ # I, [2022-05-12T16:25:31.469726 #36328] INFO -- mung: mung
639
+ # E, [2022-05-12T16:25:55.349414 #36328] ERROR -- mung: No good
640
+ # E, [2022-05-12T16:26:35.841134 #36328] ERROR -- gnum: No good
445
641
  #
446
- # <b>Message format</b>: +message+ can be any object, but it has to be
447
- # converted to a String in order to log it. Generally, +inspect+ is used
448
- # if the given object is not a String.
449
- # A special case is an +Exception+ object, which will be printed in detail,
450
- # including message, class, and backtrace. See #msg2str for the
451
- # implementation if required.
642
+ # These convenience methods have implicit severity:
452
643
  #
453
- # === Bugs
454
- #
455
- # * Logfile is not locked.
456
- # * Append open does not need to lock file.
457
- # * If the OS supports multi I/O, records possibly may be mixed.
644
+ # - #debug.
645
+ # - #info.
646
+ # - #warn.
647
+ # - #error.
648
+ # - #fatal.
649
+ # - #unknown.
458
650
  #
459
651
  def add(severity, message = nil, progname = nil)
460
652
  severity ||= UNKNOWN
@@ -478,104 +670,71 @@ class Logger
478
670
  end
479
671
  alias log add
480
672
 
673
+ # Writes the given +msg+ to the log with no formatting;
674
+ # returns the number of characters written,
675
+ # or +nil+ if no log device exists:
676
+ #
677
+ # logger = Logger.new($stdout)
678
+ # logger << 'My message.' # => 10
679
+ #
680
+ # Output:
481
681
  #
482
- # Dump given message to the log device without any formatting. If no log
483
- # device exists, return +nil+.
682
+ # My message.
484
683
  #
485
684
  def <<(msg)
486
685
  @logdev&.write(msg)
487
686
  end
488
687
 
489
- #
490
- # Log a +DEBUG+ message.
491
- #
492
- # See #info for more information.
688
+ # Equivalent to calling #add with severity <tt>Logger::DEBUG</tt>.
493
689
  #
494
690
  def debug(progname = nil, &block)
495
691
  add(DEBUG, nil, progname, &block)
496
692
  end
497
693
 
498
- #
499
- # :call-seq:
500
- # info(message)
501
- # info(progname, &block)
502
- #
503
- # Log an +INFO+ message.
504
- #
505
- # +message+:: The message to log; does not need to be a String.
506
- # +progname+:: In the block form, this is the #progname to use in the
507
- # log message. The default can be set with #progname=.
508
- # +block+:: Evaluates to the message to log. This is not evaluated unless
509
- # the logger's level is sufficient to log the message. This
510
- # allows you to create potentially expensive logging messages that
511
- # are only called when the logger is configured to show them.
512
- #
513
- # === Examples
514
- #
515
- # logger.info("MainApp") { "Received connection from #{ip}" }
516
- # # ...
517
- # logger.info "Waiting for input from user"
518
- # # ...
519
- # logger.info { "User typed #{input}" }
520
- #
521
- # You'll probably stick to the second form above, unless you want to provide a
522
- # program name (which you can do with #progname= as well).
523
- #
524
- # === Return
525
- #
526
- # See #add.
694
+ # Equivalent to calling #add with severity <tt>Logger::INFO</tt>.
527
695
  #
528
696
  def info(progname = nil, &block)
529
697
  add(INFO, nil, progname, &block)
530
698
  end
531
699
 
532
- #
533
- # Log a +WARN+ message.
534
- #
535
- # See #info for more information.
700
+ # Equivalent to calling #add with severity <tt>Logger::WARN</tt>.
536
701
  #
537
702
  def warn(progname = nil, &block)
538
703
  add(WARN, nil, progname, &block)
539
704
  end
540
705
 
541
- #
542
- # Log an +ERROR+ message.
543
- #
544
- # See #info for more information.
706
+ # Equivalent to calling #add with severity <tt>Logger::ERROR</tt>.
545
707
  #
546
708
  def error(progname = nil, &block)
547
709
  add(ERROR, nil, progname, &block)
548
710
  end
549
711
 
550
- #
551
- # Log a +FATAL+ message.
552
- #
553
- # See #info for more information.
712
+ # Equivalent to calling #add with severity <tt>Logger::FATAL</tt>.
554
713
  #
555
714
  def fatal(progname = nil, &block)
556
715
  add(FATAL, nil, progname, &block)
557
716
  end
558
717
 
559
- #
560
- # Log an +UNKNOWN+ message. This will be printed no matter what the logger's
561
- # level is.
562
- #
563
- # See #info for more information.
718
+ # Equivalent to calling #add with severity <tt>Logger::UNKNOWN</tt>.
564
719
  #
565
720
  def unknown(progname = nil, &block)
566
721
  add(UNKNOWN, nil, progname, &block)
567
722
  end
568
723
 
724
+ # Closes the logger; returns +nil+:
569
725
  #
570
- # Close the logging device.
726
+ # logger = Logger.new('t.log')
727
+ # logger.close # => nil
728
+ # logger.info('foo') # Prints "log writing failed. closed stream"
571
729
  #
730
+ # Related: Logger#reopen.
572
731
  def close
573
732
  @logdev&.close
574
733
  end
575
734
 
576
735
  private
577
736
 
578
- # Severity label for logging (max 5 chars).
737
+ # \Severity label for logging (max 5 chars).
579
738
  SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).freeze
580
739
 
581
740
  def format_severity(severity)
data/logger.gemspec CHANGED
@@ -16,14 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.licenses = ["Ruby", "BSD-2-Clause"]
17
17
 
18
18
  spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"]
19
- spec.bindir = "exe"
20
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
19
  spec.require_paths = ["lib"]
22
20
 
23
- spec.required_ruby_version = ">= 2.3.0"
24
-
25
- spec.add_development_dependency "bundler", ">= 0"
26
- spec.add_development_dependency "rake", ">= 12.3.3"
27
- spec.add_development_dependency "test-unit"
28
- spec.add_development_dependency "rdoc"
21
+ spec.required_ruby_version = ">= 2.5.0"
29
22
  end
metadata CHANGED
@@ -1,72 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naotoshi Seo
8
8
  - SHIBATA Hiroshi
9
9
  autorequire:
10
- bindir: exe
10
+ bindir: bin
11
11
  cert_chain: []
12
- date: 2020-12-22 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: 12.3.3
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: 12.3.3
42
- - !ruby/object:Gem::Dependency
43
- name: test-unit
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- version: '0'
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: '0'
56
- - !ruby/object:Gem::Dependency
57
- name: rdoc
58
- requirement: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: '0'
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
69
- version: '0'
12
+ date: 2023-11-07 00:00:00.000000000 Z
13
+ dependencies: []
70
14
  description: Provides a simple logging utility for outputting messages.
71
15
  email:
72
16
  - sonots@gmail.com
@@ -96,14 +40,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
40
  requirements:
97
41
  - - ">="
98
42
  - !ruby/object:Gem::Version
99
- version: 2.3.0
43
+ version: 2.5.0
100
44
  required_rubygems_version: !ruby/object:Gem::Requirement
101
45
  requirements:
102
46
  - - ">="
103
47
  - !ruby/object:Gem::Version
104
48
  version: '0'
105
49
  requirements: []
106
- rubygems_version: 3.2.2
50
+ rubygems_version: 3.5.0.dev
107
51
  signing_key:
108
52
  specification_version: 4
109
53
  summary: Provides a simple logging utility for outputting messages.