logger 1.3.0 → 1.5.1

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: 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