logger 1.3.0 → 1.5.1

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: 6b7218297d498d773ba9c79d57749a01f259d336a4e9b5acbfe51274d2442500
4
- data.tar.gz: c455593961790cfaf065b7b6b7798d9c184900e1ccdd0aa4f89411e33400e4b0
3
+ metadata.gz: 55dfc9db8783f8e0bce997c8f6c162b10e4602bcbe968354bb8f4a0f3a6c1764
4
+ data.tar.gz: '08e336951520fc4cc5ab2553ec563509a769a20fb461f47d4e0f2b561745783e'
5
5
  SHA512:
6
- metadata.gz: 5db2250788d1a9c583685501312a5f6ef277b3148b164b5ed1c2b123a88560ff795b40eee1ac70cf5f466e3dbd771e3d93773c387599b7f7c9916dd7319a99a6
7
- data.tar.gz: 94a96a2fba4c2e56e18e2e40f4ca0d0238edd355f65b95182e9ffdfb9a380bd7f932cf9734c0baa2a4c7b79df182cf27151972bfdd3efc6829f58530cd28c287
6
+ metadata.gz: 001ea8a77429868cfe3e438b41a1d100ee0d5c1bba2d74685fd031add97efae2bb0f31b4d889a84a954f01dfcc96624512e488bb08da4703e33bc38432c3e606
7
+ data.tar.gz: 747d62f6bf313cb3a120afcae4179feb47bbe816d40895793ccc719ca87bb4c1798c0cb72ac39862dbcbacc6468e59606d2d5600e395607562f0c0a58bbf3f6f
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # not used after 1.2.7. just for compat.
4
+ class Logger
5
+ class Error < RuntimeError # :nodoc:
6
+ end
7
+ class ShiftingError < Error # :nodoc:
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Logger
4
+ # Default formatter for log messages.
5
+ class Formatter
6
+ Format = "%s, [%s #%d] %5s -- %s: %s\n"
7
+ DatetimeFormat = "%Y-%m-%dT%H:%M:%S.%6N"
8
+
9
+ attr_accessor :datetime_format
10
+
11
+ def initialize
12
+ @datetime_format = nil
13
+ end
14
+
15
+ def call(severity, time, progname, msg)
16
+ Format % [severity[0..0], format_datetime(time), Process.pid, severity, progname,
17
+ msg2str(msg)]
18
+ end
19
+
20
+ private
21
+
22
+ def format_datetime(time)
23
+ time.strftime(@datetime_format || DatetimeFormat)
24
+ end
25
+
26
+ def msg2str(msg)
27
+ case msg
28
+ when ::String
29
+ msg
30
+ when ::Exception
31
+ "#{ msg.message } (#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }"
32
+ else
33
+ msg.inspect
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'period'
4
+
5
+ class Logger
6
+ # Device used for logging messages.
7
+ class LogDevice
8
+ include Period
9
+
10
+ attr_reader :dev
11
+ attr_reader :filename
12
+ include MonitorMixin
13
+
14
+ def initialize(log = nil, shift_age: nil, shift_size: nil, shift_period_suffix: nil, binmode: false)
15
+ @dev = @filename = @shift_age = @shift_size = @shift_period_suffix = nil
16
+ @binmode = binmode
17
+ mon_initialize
18
+ set_dev(log)
19
+ if @filename
20
+ @shift_age = shift_age || 7
21
+ @shift_size = shift_size || 1048576
22
+ @shift_period_suffix = shift_period_suffix || '%Y%m%d'
23
+
24
+ unless @shift_age.is_a?(Integer)
25
+ base_time = @dev.respond_to?(:stat) ? @dev.stat.mtime : Time.now
26
+ @next_rotate_time = next_rotate_time(base_time, @shift_age)
27
+ end
28
+ end
29
+ end
30
+
31
+ def write(message)
32
+ begin
33
+ synchronize do
34
+ if @shift_age and @dev.respond_to?(:stat)
35
+ begin
36
+ check_shift_log
37
+ rescue
38
+ warn("log shifting failed. #{$!}")
39
+ end
40
+ end
41
+ begin
42
+ @dev.write(message)
43
+ rescue
44
+ warn("log writing failed. #{$!}")
45
+ end
46
+ end
47
+ rescue Exception => ignored
48
+ warn("log writing failed. #{ignored}")
49
+ end
50
+ end
51
+
52
+ def close
53
+ begin
54
+ synchronize do
55
+ @dev.close rescue nil
56
+ end
57
+ rescue Exception
58
+ @dev.close rescue nil
59
+ end
60
+ end
61
+
62
+ def reopen(log = nil)
63
+ # reopen the same filename if no argument, do nothing for IO
64
+ log ||= @filename if @filename
65
+ if log
66
+ synchronize do
67
+ if @filename and @dev
68
+ @dev.close rescue nil # close only file opened by Logger
69
+ @filename = nil
70
+ end
71
+ set_dev(log)
72
+ end
73
+ end
74
+ self
75
+ end
76
+
77
+ private
78
+
79
+ def set_dev(log)
80
+ if log.respond_to?(:write) and log.respond_to?(:close)
81
+ @dev = log
82
+ if log.respond_to?(:path)
83
+ @filename = log.path
84
+ end
85
+ else
86
+ @dev = open_logfile(log)
87
+ @dev.sync = true
88
+ @dev.binmode if @binmode
89
+ @filename = log
90
+ end
91
+ end
92
+
93
+ def open_logfile(filename)
94
+ begin
95
+ File.open(filename, (File::WRONLY | File::APPEND))
96
+ rescue Errno::ENOENT
97
+ create_logfile(filename)
98
+ end
99
+ end
100
+
101
+ def create_logfile(filename)
102
+ begin
103
+ logdev = File.open(filename, (File::WRONLY | File::APPEND | File::CREAT | File::EXCL))
104
+ logdev.flock(File::LOCK_EX)
105
+ logdev.sync = true
106
+ logdev.binmode if @binmode
107
+ add_log_header(logdev)
108
+ logdev.flock(File::LOCK_UN)
109
+ rescue Errno::EEXIST
110
+ # file is created by another process
111
+ logdev = open_logfile(filename)
112
+ logdev.sync = true
113
+ end
114
+ logdev
115
+ end
116
+
117
+ def add_log_header(file)
118
+ file.write(
119
+ "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
120
+ ) if file.size == 0
121
+ end
122
+
123
+ def check_shift_log
124
+ if @shift_age.is_a?(Integer)
125
+ # Note: always returns false if '0'.
126
+ if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size)
127
+ lock_shift_log { shift_log_age }
128
+ end
129
+ else
130
+ now = Time.now
131
+ if now >= @next_rotate_time
132
+ @next_rotate_time = next_rotate_time(now, @shift_age)
133
+ lock_shift_log { shift_log_period(previous_period_end(now, @shift_age)) }
134
+ end
135
+ end
136
+ end
137
+
138
+ if /mswin|mingw|cygwin/ =~ RbConfig::CONFIG['host_os']
139
+ def lock_shift_log
140
+ yield
141
+ end
142
+ else
143
+ def lock_shift_log
144
+ retry_limit = 8
145
+ retry_sleep = 0.1
146
+ begin
147
+ File.open(@filename, File::WRONLY | File::APPEND) do |lock|
148
+ lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file
149
+ if File.identical?(@filename, lock) and File.identical?(lock, @dev)
150
+ yield # log shifting
151
+ else
152
+ # log shifted by another process (i-node before locking and i-node after locking are different)
153
+ @dev.close rescue nil
154
+ @dev = open_logfile(@filename)
155
+ @dev.sync = true
156
+ end
157
+ end
158
+ rescue Errno::ENOENT
159
+ # @filename file would not exist right after #rename and before #create_logfile
160
+ if retry_limit <= 0
161
+ warn("log rotation inter-process lock failed. #{$!}")
162
+ else
163
+ sleep retry_sleep
164
+ retry_limit -= 1
165
+ retry_sleep *= 2
166
+ retry
167
+ end
168
+ end
169
+ rescue
170
+ warn("log rotation inter-process lock failed. #{$!}")
171
+ end
172
+ end
173
+
174
+ def shift_log_age
175
+ (@shift_age-3).downto(0) do |i|
176
+ if FileTest.exist?("#{@filename}.#{i}")
177
+ File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
178
+ end
179
+ end
180
+ @dev.close rescue nil
181
+ File.rename("#{@filename}", "#{@filename}.0")
182
+ @dev = create_logfile(@filename)
183
+ return true
184
+ end
185
+
186
+ def shift_log_period(period_end)
187
+ suffix = period_end.strftime(@shift_period_suffix)
188
+ age_file = "#{@filename}.#{suffix}"
189
+ if FileTest.exist?(age_file)
190
+ # try to avoid filename crash caused by Timestamp change.
191
+ idx = 0
192
+ # .99 can be overridden; avoid too much file search with 'loop do'
193
+ while idx < 100
194
+ idx += 1
195
+ age_file = "#{@filename}.#{suffix}.#{idx}"
196
+ break unless FileTest.exist?(age_file)
197
+ end
198
+ end
199
+ @dev.close rescue nil
200
+ File.rename("#{@filename}", age_file)
201
+ @dev = create_logfile(@filename)
202
+ return true
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Logger
4
+ module Period
5
+ module_function
6
+
7
+ SiD = 24 * 60 * 60
8
+
9
+ def next_rotate_time(now, shift_age)
10
+ case shift_age
11
+ when 'daily'
12
+ t = Time.mktime(now.year, now.month, now.mday) + SiD
13
+ when 'weekly'
14
+ t = Time.mktime(now.year, now.month, now.mday) + SiD * (7 - now.wday)
15
+ when 'monthly'
16
+ t = Time.mktime(now.year, now.month, 1) + SiD * 32
17
+ return Time.mktime(t.year, t.month, 1)
18
+ when 'now', 'everytime'
19
+ return now
20
+ else
21
+ raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
22
+ end
23
+ if t.hour.nonzero? or t.min.nonzero? or t.sec.nonzero?
24
+ hour = t.hour
25
+ t = Time.mktime(t.year, t.month, t.mday)
26
+ t += SiD if hour > 12
27
+ end
28
+ t
29
+ end
30
+
31
+ def previous_period_end(now, shift_age)
32
+ case shift_age
33
+ when 'daily'
34
+ t = Time.mktime(now.year, now.month, now.mday) - SiD / 2
35
+ when 'weekly'
36
+ t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2)
37
+ when 'monthly'
38
+ t = Time.mktime(now.year, now.month, 1) - SiD / 2
39
+ when 'now', 'everytime'
40
+ return now
41
+ else
42
+ raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
43
+ end
44
+ Time.mktime(t.year, t.month, t.mday, 23, 59, 59)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Logger
4
+ # Logging severity.
5
+ module Severity
6
+ # Low-level information, mostly for developers.
7
+ DEBUG = 0
8
+ # Generic (useful) information about system operation.
9
+ INFO = 1
10
+ # A warning.
11
+ WARN = 2
12
+ # A handleable error condition.
13
+ ERROR = 3
14
+ # An unhandleable error that results in a program crash.
15
+ FATAL = 4
16
+ # An unknown message that should always be logged.
17
+ UNKNOWN = 5
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Logger
4
+ VERSION = "1.5.1"
5
+ end
data/lib/logger.rb CHANGED
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  # logger.rb - simple logging utility
3
3
  # Copyright (C) 2000-2003, 2005, 2008, 2011 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
4
4
  #
@@ -11,6 +11,13 @@
11
11
  # A simple system for logging messages. See Logger for more documentation.
12
12
 
13
13
  require 'monitor'
14
+ require 'rbconfig'
15
+
16
+ require_relative 'logger/version'
17
+ require_relative 'logger/formatter'
18
+ require_relative 'logger/log_device'
19
+ require_relative 'logger/severity'
20
+ require_relative 'logger/errors'
14
21
 
15
22
  # == Description
16
23
  #
@@ -224,7 +231,6 @@ require 'monitor'
224
231
  # })
225
232
  #
226
233
  class Logger
227
- VERSION = "1.3.0"
228
234
  _, name, rev = %w$Id$
229
235
  if name
230
236
  name = name.chomp(",v")
@@ -232,29 +238,8 @@ class Logger
232
238
  name = File.basename(__FILE__)
233
239
  end
234
240
  rev ||= "v#{VERSION}"
235
- ProgName = "#{name}/#{rev}".freeze
236
-
237
- class Error < RuntimeError # :nodoc:
238
- end
239
- # not used after 1.2.7. just for compat.
240
- class ShiftingError < Error # :nodoc:
241
- end
241
+ ProgName = "#{name}/#{rev}"
242
242
 
243
- # Logging severity.
244
- module Severity
245
- # Low-level information, mostly for developers.
246
- DEBUG = 0
247
- # Generic (useful) information about system operation.
248
- INFO = 1
249
- # A warning.
250
- WARN = 2
251
- # A handleable error condition.
252
- ERROR = 3
253
- # An unhandleable error that results in a program crash.
254
- FATAL = 4
255
- # An unknown message that should always be logged.
256
- UNKNOWN = 5
257
- end
258
243
  include Severity
259
244
 
260
245
  # Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
@@ -318,25 +303,40 @@ class Logger
318
303
  alias sev_threshold level
319
304
  alias sev_threshold= level=
320
305
 
321
- # Returns +true+ iff the current severity level allows for the printing of
306
+ # Returns +true+ if and only if the current severity level allows for the printing of
322
307
  # +DEBUG+ messages.
323
- def debug?; @level <= DEBUG; end
308
+ def debug?; level <= DEBUG; end
309
+
310
+ # Sets the severity to DEBUG.
311
+ def debug!; self.level = DEBUG; end
324
312
 
325
- # Returns +true+ iff the current severity level allows for the printing of
313
+ # Returns +true+ if and only if the current severity level allows for the printing of
326
314
  # +INFO+ messages.
327
- def info?; @level <= INFO; end
315
+ def info?; level <= INFO; end
328
316
 
329
- # Returns +true+ iff the current severity level allows for the printing of
317
+ # Sets the severity to INFO.
318
+ def info!; self.level = INFO; end
319
+
320
+ # Returns +true+ if and only if the current severity level allows for the printing of
330
321
  # +WARN+ messages.
331
- def warn?; @level <= WARN; end
322
+ def warn?; level <= WARN; end
323
+
324
+ # Sets the severity to WARN.
325
+ def warn!; self.level = WARN; end
332
326
 
333
- # Returns +true+ iff the current severity level allows for the printing of
327
+ # Returns +true+ if and only if the current severity level allows for the printing of
334
328
  # +ERROR+ messages.
335
- def error?; @level <= ERROR; end
329
+ def error?; level <= ERROR; end
330
+
331
+ # Sets the severity to ERROR.
332
+ def error!; self.level = ERROR; end
336
333
 
337
- # Returns +true+ iff the current severity level allows for the printing of
334
+ # Returns +true+ if and only if the current severity level allows for the printing of
338
335
  # +FATAL+ messages.
339
- def fatal?; @level <= FATAL; end
336
+ def fatal?; level <= FATAL; end
337
+
338
+ # Sets the severity to FATAL.
339
+ def fatal!; self.level = FATAL; end
340
340
 
341
341
  #
342
342
  # :call-seq:
@@ -350,14 +350,16 @@ class Logger
350
350
  # === Args
351
351
  #
352
352
  # +logdev+::
353
- # The log device. This is a filename (String) or IO object (typically
354
- # +STDOUT+, +STDERR+, or an open file).
353
+ # The log device. This is a filename (String), IO object (typically
354
+ # +STDOUT+, +STDERR+, or an open file), +nil+ (it writes nothing) or
355
+ # +File::NULL+ (same as +nil+).
355
356
  # +shift_age+::
356
357
  # Number of old log files to keep, *or* frequency of rotation (+daily+,
357
- # +weekly+ or +monthly+). Default value is 0.
358
+ # +weekly+ or +monthly+). Default value is 0, which disables log file
359
+ # rotation.
358
360
  # +shift_size+::
359
- # Maximum logfile size in bytes (only applies when +shift_age+ is a number).
360
- # Defaults to +1048576+ (1MB).
361
+ # Maximum logfile size in bytes (only applies when +shift_age+ is a positive
362
+ # Integer). Defaults to +1048576+ (1MB).
361
363
  # +level+::
362
364
  # Logging severity threshold. Default values is Logger::DEBUG.
363
365
  # +progname+::
@@ -366,6 +368,8 @@ class Logger
366
368
  # Logging formatter. Default values is an instance of Logger::Formatter.
367
369
  # +datetime_format+::
368
370
  # Date and time format. Default value is '%Y-%m-%d %H:%M:%S'.
371
+ # +binmode+::
372
+ # Use binary mode on the log device. Default value is false.
369
373
  # +shift_period_suffix+::
370
374
  # The log file suffix format for +daily+, +weekly+ or +monthly+ rotation.
371
375
  # Default is '%Y%m%d'.
@@ -376,17 +380,18 @@ class Logger
376
380
  #
377
381
  def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
378
382
  progname: nil, formatter: nil, datetime_format: nil,
379
- shift_period_suffix: '%Y%m%d')
383
+ binmode: false, shift_period_suffix: '%Y%m%d')
380
384
  self.level = level
381
385
  self.progname = progname
382
386
  @default_formatter = Formatter.new
383
387
  self.datetime_format = datetime_format
384
388
  self.formatter = formatter
385
389
  @logdev = nil
386
- if logdev
387
- @logdev = LogDevice.new(logdev, :shift_age => shift_age,
388
- :shift_size => shift_size,
389
- :shift_period_suffix => shift_period_suffix)
390
+ if logdev && logdev != File::NULL
391
+ @logdev = LogDevice.new(logdev, shift_age: shift_age,
392
+ shift_size: shift_size,
393
+ shift_period_suffix: shift_period_suffix,
394
+ binmode: binmode)
390
395
  end
391
396
  end
392
397
 
@@ -407,7 +412,7 @@ class Logger
407
412
  # Reopen a log device.
408
413
  #
409
414
  def reopen(logdev = nil)
410
- @logdev.reopen(logdev)
415
+ @logdev&.reopen(logdev)
411
416
  self
412
417
  end
413
418
 
@@ -454,7 +459,7 @@ class Logger
454
459
  #
455
460
  def add(severity, message = nil, progname = nil)
456
461
  severity ||= UNKNOWN
457
- if @logdev.nil? or severity < @level
462
+ if @logdev.nil? or severity < level
458
463
  return true
459
464
  end
460
465
  if progname.nil?
@@ -572,7 +577,7 @@ class Logger
572
577
  private
573
578
 
574
579
  # Severity label for logging (max 5 chars).
575
- SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).each(&:freeze).freeze
580
+ SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).freeze
576
581
 
577
582
  def format_severity(severity)
578
583
  SEV_LABEL[severity] || 'ANY'
@@ -581,273 +586,4 @@ private
581
586
  def format_message(severity, datetime, progname, msg)
582
587
  (@formatter || @default_formatter).call(severity, datetime, progname, msg)
583
588
  end
584
-
585
-
586
- # Default formatter for log messages.
587
- class Formatter
588
- Format = "%s, [%s#%d] %5s -- %s: %s\n".freeze
589
-
590
- attr_accessor :datetime_format
591
-
592
- def initialize
593
- @datetime_format = nil
594
- end
595
-
596
- def call(severity, time, progname, msg)
597
- Format % [severity[0..0], format_datetime(time), $$, severity, progname,
598
- msg2str(msg)]
599
- end
600
-
601
- private
602
-
603
- def format_datetime(time)
604
- time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze)
605
- end
606
-
607
- def msg2str(msg)
608
- case msg
609
- when ::String
610
- msg
611
- when ::Exception
612
- "#{ msg.message } (#{ msg.class })\n" <<
613
- (msg.backtrace || []).join("\n")
614
- else
615
- msg.inspect
616
- end
617
- end
618
- end
619
-
620
- module Period
621
- module_function
622
-
623
- SiD = 24 * 60 * 60
624
-
625
- def next_rotate_time(now, shift_age)
626
- case shift_age
627
- when 'daily'
628
- t = Time.mktime(now.year, now.month, now.mday) + SiD
629
- when 'weekly'
630
- t = Time.mktime(now.year, now.month, now.mday) + SiD * (7 - now.wday)
631
- when 'monthly'
632
- t = Time.mktime(now.year, now.month, 1) + SiD * 32
633
- return Time.mktime(t.year, t.month, 1)
634
- else
635
- return now
636
- end
637
- if t.hour.nonzero? or t.min.nonzero? or t.sec.nonzero?
638
- hour = t.hour
639
- t = Time.mktime(t.year, t.month, t.mday)
640
- t += SiD if hour > 12
641
- end
642
- t
643
- end
644
-
645
- def previous_period_end(now, shift_age)
646
- case shift_age
647
- when 'daily'
648
- t = Time.mktime(now.year, now.month, now.mday) - SiD / 2
649
- when 'weekly'
650
- t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2)
651
- when 'monthly'
652
- t = Time.mktime(now.year, now.month, 1) - SiD / 2
653
- else
654
- return now
655
- end
656
- Time.mktime(t.year, t.month, t.mday, 23, 59, 59)
657
- end
658
- end
659
-
660
- # Device used for logging messages.
661
- class LogDevice
662
- include Period
663
-
664
- attr_reader :dev
665
- attr_reader :filename
666
- include MonitorMixin
667
-
668
- def initialize(log = nil, shift_age: nil, shift_size: nil, shift_period_suffix: nil)
669
- @dev = @filename = @shift_age = @shift_size = @shift_period_suffix = nil
670
- mon_initialize
671
- set_dev(log)
672
- if @filename
673
- @shift_age = shift_age || 7
674
- @shift_size = shift_size || 1048576
675
- @shift_period_suffix = shift_period_suffix || '%Y%m%d'
676
-
677
- unless @shift_age.is_a?(Integer)
678
- base_time = @dev.respond_to?(:stat) ? @dev.stat.mtime : Time.now
679
- @next_rotate_time = next_rotate_time(base_time, @shift_age)
680
- end
681
- end
682
- end
683
-
684
- def write(message)
685
- begin
686
- synchronize do
687
- if @shift_age and @dev.respond_to?(:stat)
688
- begin
689
- check_shift_log
690
- rescue
691
- warn("log shifting failed. #{$!}")
692
- end
693
- end
694
- begin
695
- @dev.write(message)
696
- rescue
697
- warn("log writing failed. #{$!}")
698
- end
699
- end
700
- rescue Exception => ignored
701
- warn("log writing failed. #{ignored}")
702
- end
703
- end
704
-
705
- def close
706
- begin
707
- synchronize do
708
- @dev.close rescue nil
709
- end
710
- rescue Exception
711
- @dev.close rescue nil
712
- end
713
- end
714
-
715
- def reopen(log = nil)
716
- # reopen the same filename if no argument, do nothing for IO
717
- log ||= @filename if @filename
718
- if log
719
- synchronize do
720
- if @filename and @dev
721
- @dev.close rescue nil # close only file opened by Logger
722
- @filename = nil
723
- end
724
- set_dev(log)
725
- end
726
- end
727
- self
728
- end
729
-
730
- private
731
-
732
- def set_dev(log)
733
- if log.respond_to?(:write) and log.respond_to?(:close)
734
- @dev = log
735
- else
736
- @dev = open_logfile(log)
737
- @dev.sync = true
738
- @filename = log
739
- end
740
- end
741
-
742
- def open_logfile(filename)
743
- begin
744
- File.open(filename, (File::WRONLY | File::APPEND))
745
- rescue Errno::ENOENT
746
- create_logfile(filename)
747
- end
748
- end
749
-
750
- def create_logfile(filename)
751
- begin
752
- logdev = File.open(filename, (File::WRONLY | File::APPEND | File::CREAT | File::EXCL))
753
- logdev.flock(File::LOCK_EX)
754
- logdev.sync = true
755
- add_log_header(logdev)
756
- logdev.flock(File::LOCK_UN)
757
- rescue Errno::EEXIST
758
- # file is created by another process
759
- logdev = open_logfile(filename)
760
- logdev.sync = true
761
- end
762
- logdev
763
- end
764
-
765
- def add_log_header(file)
766
- file.write(
767
- "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
768
- ) if file.size == 0
769
- end
770
-
771
- def check_shift_log
772
- if @shift_age.is_a?(Integer)
773
- # Note: always returns false if '0'.
774
- if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size)
775
- lock_shift_log { shift_log_age }
776
- end
777
- else
778
- now = Time.now
779
- if now >= @next_rotate_time
780
- @next_rotate_time = next_rotate_time(now, @shift_age)
781
- lock_shift_log { shift_log_period(previous_period_end(now, @shift_age)) }
782
- end
783
- end
784
- end
785
-
786
- if /mswin|mingw/ =~ RUBY_PLATFORM
787
- def lock_shift_log
788
- yield
789
- end
790
- else
791
- def lock_shift_log
792
- retry_limit = 8
793
- retry_sleep = 0.1
794
- begin
795
- File.open(@filename, File::WRONLY | File::APPEND) do |lock|
796
- lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file
797
- if File.identical?(@filename, lock) and File.identical?(lock, @dev)
798
- yield # log shifting
799
- else
800
- # log shifted by another process (i-node before locking and i-node after locking are different)
801
- @dev.close rescue nil
802
- @dev = open_logfile(@filename)
803
- @dev.sync = true
804
- end
805
- end
806
- rescue Errno::ENOENT
807
- # @filename file would not exist right after #rename and before #create_logfile
808
- if retry_limit <= 0
809
- warn("log rotation inter-process lock failed. #{$!}")
810
- else
811
- sleep retry_sleep
812
- retry_limit -= 1
813
- retry_sleep *= 2
814
- retry
815
- end
816
- end
817
- rescue
818
- warn("log rotation inter-process lock failed. #{$!}")
819
- end
820
- end
821
-
822
- def shift_log_age
823
- (@shift_age-3).downto(0) do |i|
824
- if FileTest.exist?("#{@filename}.#{i}")
825
- File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
826
- end
827
- end
828
- @dev.close rescue nil
829
- File.rename("#{@filename}", "#{@filename}.0")
830
- @dev = create_logfile(@filename)
831
- return true
832
- end
833
-
834
- def shift_log_period(period_end)
835
- suffix = period_end.strftime(@shift_period_suffix)
836
- age_file = "#{@filename}.#{suffix}"
837
- if FileTest.exist?(age_file)
838
- # try to avoid filename crash caused by Timestamp change.
839
- idx = 0
840
- # .99 can be overridden; avoid too much file search with 'loop do'
841
- while idx < 100
842
- idx += 1
843
- age_file = "#{@filename}.#{suffix}.#{idx}"
844
- break unless FileTest.exist?(age_file)
845
- end
846
- end
847
- @dev.close rescue nil
848
- File.rename("#{@filename}", age_file)
849
- @dev = create_logfile(@filename)
850
- return true
851
- end
852
- end
853
589
  end
data/logger.gemspec CHANGED
@@ -1,27 +1,27 @@
1
1
  begin
2
- require_relative "lib/logger"
3
- rescue LoadError
4
- # for Ruby core repository
5
- require_relative "logger"
2
+ require_relative "lib/logger/version"
3
+ rescue LoadError # Fallback to load version file in ruby core repository
4
+ require_relative "version"
6
5
  end
7
6
 
8
7
  Gem::Specification.new do |spec|
9
8
  spec.name = "logger"
10
9
  spec.version = Logger::VERSION
11
- spec.authors = ["SHIBATA Hiroshi"]
12
- spec.email = ["hsbt@ruby-lang.org"]
10
+ spec.authors = ["Naotoshi Seo", "SHIBATA Hiroshi"]
11
+ spec.email = ["sonots@gmail.com", "hsbt@ruby-lang.org"]
13
12
 
14
13
  spec.summary = %q{Provides a simple logging utility for outputting messages.}
15
14
  spec.description = %q{Provides a simple logging utility for outputting messages.}
16
15
  spec.homepage = "https://github.com/ruby/logger"
17
- spec.license = "BSD-2-Clause"
16
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
18
17
 
19
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/logger.rb", "logger.gemspec"]
20
- spec.bindir = "exe"
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"]
22
19
  spec.require_paths = ["lib"]
23
20
 
24
- spec.add_development_dependency "bundler", "~> 1.16"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "minitest", "~> 5.0"
21
+ spec.required_ruby_version = ">= 2.3.0"
22
+
23
+ spec.add_development_dependency "bundler", ">= 0"
24
+ spec.add_development_dependency "rake", ">= 12.3.3"
25
+ spec.add_development_dependency "test-unit"
26
+ spec.add_development_dependency "rdoc"
27
27
  end
metadata CHANGED
@@ -1,79 +1,94 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
+ - Naotoshi Seo
7
8
  - SHIBATA Hiroshi
8
- autorequire:
9
- bindir: exe
9
+ autorequire:
10
+ bindir: bin
10
11
  cert_chain: []
11
- date: 2018-12-05 00:00:00.000000000 Z
12
+ date: 2022-03-17 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - "~>"
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: '1.16'
20
+ version: '0'
20
21
  type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - "~>"
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: '1.16'
27
+ version: '0'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: rake
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - "~>"
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: '10.0'
34
+ version: 12.3.3
34
35
  type: :development
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - "~>"
39
+ - - ">="
39
40
  - !ruby/object:Gem::Version
40
- version: '10.0'
41
+ version: 12.3.3
41
42
  - !ruby/object:Gem::Dependency
42
- name: minitest
43
+ name: test-unit
43
44
  requirement: !ruby/object:Gem::Requirement
44
45
  requirements:
45
- - - "~>"
46
+ - - ">="
46
47
  - !ruby/object:Gem::Version
47
- version: '5.0'
48
+ version: '0'
48
49
  type: :development
49
50
  prerelease: false
50
51
  version_requirements: !ruby/object:Gem::Requirement
51
52
  requirements:
52
- - - "~>"
53
+ - - ">="
53
54
  - !ruby/object:Gem::Version
54
- version: '5.0'
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'
55
70
  description: Provides a simple logging utility for outputting messages.
56
71
  email:
72
+ - sonots@gmail.com
57
73
  - hsbt@ruby-lang.org
58
74
  executables: []
59
75
  extensions: []
60
76
  extra_rdoc_files: []
61
77
  files:
62
- - ".gitignore"
63
- - ".travis.yml"
64
- - Gemfile
65
- - LICENSE.txt
66
- - README.md
67
- - Rakefile
68
- - bin/console
69
- - bin/setup
70
78
  - lib/logger.rb
79
+ - lib/logger/errors.rb
80
+ - lib/logger/formatter.rb
81
+ - lib/logger/log_device.rb
82
+ - lib/logger/period.rb
83
+ - lib/logger/severity.rb
84
+ - lib/logger/version.rb
71
85
  - logger.gemspec
72
86
  homepage: https://github.com/ruby/logger
73
87
  licenses:
88
+ - Ruby
74
89
  - BSD-2-Clause
75
90
  metadata: {}
76
- post_install_message:
91
+ post_install_message:
77
92
  rdoc_options: []
78
93
  require_paths:
79
94
  - lib
@@ -81,16 +96,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
96
  requirements:
82
97
  - - ">="
83
98
  - !ruby/object:Gem::Version
84
- version: '0'
99
+ version: 2.3.0
85
100
  required_rubygems_version: !ruby/object:Gem::Requirement
86
101
  requirements:
87
102
  - - ">="
88
103
  - !ruby/object:Gem::Version
89
104
  version: '0'
90
105
  requirements: []
91
- rubyforge_project:
92
- rubygems_version: 2.7.6
93
- signing_key:
106
+ rubygems_version: 3.4.0.dev
107
+ signing_key:
94
108
  specification_version: 4
95
109
  summary: Provides a simple logging utility for outputting messages.
96
110
  test_files: []
data/.gitignore DELETED
@@ -1,8 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.1
5
- - ruby-head
6
- before_install: gem install bundler -v 1.16.2
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in logger.gemspec
6
- gemspec
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
-
3
- Redistribution and use in source and binary forms, with or without
4
- modification, are permitted provided that the following conditions
5
- are met:
6
- 1. Redistributions of source code must retain the above copyright
7
- notice, this list of conditions and the following disclaimer.
8
- 2. Redistributions in binary form must reproduce the above copyright
9
- notice, this list of conditions and the following disclaimer in the
10
- documentation and/or other materials provided with the distribution.
11
-
12
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
- SUCH DAMAGE.
data/README.md DELETED
@@ -1,39 +0,0 @@
1
- # Logger
2
-
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/logger`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- ```ruby
12
- gem 'logger'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install logger
22
-
23
- ## Usage
24
-
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
- ## Contributing
34
-
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/logger.
36
-
37
- ## License
38
-
39
- The gem is available as open source under the terms of the [BSD-2-Clause](LICENSE.txt).
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib" << "test/lib"
7
- t.test_files = FileList["test/**/test_*.rb"]
8
- end
9
-
10
- task :default => :test
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "logger"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here