logger 1.4.0 → 1.4.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: 8ac30b81e7461bb8da11d63f68d4981b0f058960d6001319c8709c98b05b1dfa
4
- data.tar.gz: 25dfc74c49ea696330c6e2c435a27a0b6933ecd65cf4ed9ea2ede8accde35606
3
+ metadata.gz: 9ddf4801d5f2a31d107d694a433dcd93583d43cc405ee2347ca8054409705c68
4
+ data.tar.gz: d42cd2e291492d13dd458afc25b349a2501dbddfba526af27185ec199cc203b2
5
5
  SHA512:
6
- metadata.gz: 1d724998e973037c4c5baaae8c8edc965129533a72f70b0551cfed8c871e27d6ec11e780636b329fb9ba9636e22da0cb0cfe0e76bf0fe73fe6cbbdc575068c0b
7
- data.tar.gz: aaf0393b43f86dc1cada4f57e5faf64159f3d1cf52a93e97077b64721bd6287aaea7f55a7377ecf74689ed68ecda65c58440b27fbf1404f7ffd087fd80f0381a
6
+ metadata.gz: 1db29e10a929c956f8db43abfbd42ac12edf83f10eff23026041e3c1381929bd571f74c9f900337994c980a9eda9ba9e10ca888f67ba986f3727c9897326c98d
7
+ data.tar.gz: 55b2c8e12eac1c2a9b7a0ac41ea7df4be72704c4f8b5396fa8c90e13c1682ca6d6711f9ee903bf386a0283bf02cd68dcb1577737998144536ab137dc8e4ba2ac
@@ -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,36 @@
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
+
8
+ attr_accessor :datetime_format
9
+
10
+ def initialize
11
+ @datetime_format = nil
12
+ end
13
+
14
+ def call(severity, time, progname, msg)
15
+ Format % [severity[0..0], format_datetime(time), $$, severity, progname,
16
+ msg2str(msg)]
17
+ end
18
+
19
+ private
20
+
21
+ def format_datetime(time)
22
+ time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ")
23
+ end
24
+
25
+ def msg2str(msg)
26
+ case msg
27
+ when ::String
28
+ msg
29
+ when ::Exception
30
+ "#{ msg.message } (#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }"
31
+ else
32
+ msg.inspect
33
+ end
34
+ end
35
+ end
36
+ 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/ =~ RUBY_PLATFORM
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,43 @@
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
+ else
19
+ return now
20
+ end
21
+ if t.hour.nonzero? or t.min.nonzero? or t.sec.nonzero?
22
+ hour = t.hour
23
+ t = Time.mktime(t.year, t.month, t.mday)
24
+ t += SiD if hour > 12
25
+ end
26
+ t
27
+ end
28
+
29
+ def previous_period_end(now, shift_age)
30
+ case shift_age
31
+ when 'daily'
32
+ t = Time.mktime(now.year, now.month, now.mday) - SiD / 2
33
+ when 'weekly'
34
+ t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2)
35
+ when 'monthly'
36
+ t = Time.mktime(now.year, now.month, 1) - SiD / 2
37
+ else
38
+ return now
39
+ end
40
+ Time.mktime(t.year, t.month, t.mday, 23, 59, 59)
41
+ end
42
+ end
43
+ 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.4.1"
5
+ end
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.homepage = "https://github.com/ruby/logger"
16
16
  spec.license = "BSD-2-Clause"
17
17
 
18
- spec.files = ["Gemfile", "LICENSE.txt", "README.md", "Rakefile", "lib/logger.rb", "logger.gemspec"]
18
+ spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"]
19
19
  spec.bindir = "exe"
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naotoshi Seo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-08-19 00:00:00.000000000 Z
12
+ date: 2019-08-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -75,11 +75,13 @@ executables: []
75
75
  extensions: []
76
76
  extra_rdoc_files: []
77
77
  files:
78
- - Gemfile
79
- - LICENSE.txt
80
- - README.md
81
- - Rakefile
82
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
83
85
  - logger.gemspec
84
86
  homepage: https://github.com/ruby/logger
85
87
  licenses:
data/Gemfile DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- gemspec
@@ -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,104 +0,0 @@
1
- # Logger
2
-
3
- [![Build Status](https://travis-ci.com/ruby/logger.svg?branch=master)](https://travis-ci.com/ruby/logger)
4
-
5
- Logger is a simple but powerful logging utility to output messages in your Ruby program.
6
-
7
- Logger has the following features:
8
-
9
- * Print messages to different levels such as `info` and `error`
10
- * Auto-rolling of log files
11
- * Setting the format of log messages
12
- * Specifying a program name in conjunction with the message
13
-
14
- ## Installation
15
-
16
- Add this line to your application's Gemfile:
17
-
18
- ```ruby
19
- gem 'logger'
20
- ```
21
-
22
- And then execute:
23
-
24
- $ bundle
25
-
26
- Or install it yourself as:
27
-
28
- $ gem install logger
29
-
30
- ## Usage
31
-
32
- ### Simple Example
33
-
34
- require 'logger'
35
-
36
- # Create a Logger that prints to STDOUT
37
- log = Logger.new(STDOUT)
38
- log.debug("Created Logger")
39
-
40
- log.info("Program finished")
41
-
42
- # Create a Logger that prints to STDERR
43
- error_log = Logger.new(STDERR)
44
- error_log = Logger.error("fatal error")
45
-
46
- ## Development
47
-
48
- After checking out the repo, run the following to install dependencies.
49
-
50
- ```
51
- $ bin/setup
52
- ```
53
-
54
- Then, run the tests as:
55
-
56
- ```
57
- $ rake test
58
- ```
59
-
60
- To install this gem onto your local machine, run
61
-
62
- ```
63
- $ rake install
64
- ```
65
-
66
- To release a new version, update the version number in `lib/logger/version.rb`, and then run
67
-
68
- ```
69
- $ rake release
70
- ```
71
-
72
- 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).
73
-
74
- ## Advanced Development
75
-
76
- ### Run tests of a specific file
77
-
78
- ```
79
- $ ruby test/logger/test_logger.rb
80
- ```
81
-
82
- ### Run tests filtering test methods by a name
83
-
84
- `--name` option is available as:
85
-
86
- ```
87
- $ ruby test/logger/test_logger.rb --name test_lshift
88
- ```
89
-
90
- ### Publish documents to GitHub Pages
91
-
92
- ```
93
- $ rake gh-pages
94
- ```
95
-
96
- Then, git commit and push the generated HTMLs onto `gh-pages` branch.
97
-
98
- ## Contributing
99
-
100
- Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/logger.
101
-
102
- ## License
103
-
104
- The gem is available as open source under the terms of the [BSD-2-Clause](LICENSE.txt).
data/Rakefile DELETED
@@ -1,28 +0,0 @@
1
- begin
2
- require "bundler/gem_tasks"
3
- rescue LoadError
4
- end
5
-
6
- require "rake/testtask"
7
- Rake::TestTask.new(:test) do |t|
8
- t.test_files = FileList["test/**/test_*.rb"]
9
- end
10
-
11
- require "rdoc/task"
12
- RDoc::Task.new do |doc|
13
- doc.main = "README.md"
14
- doc.title = "Logger -- Ruby Standard Logger"
15
- doc.rdoc_files = FileList.new %w[README.md lib LICENSE.txt]
16
- doc.rdoc_dir = "html"
17
- end
18
-
19
- task "gh-pages" => :rdoc do
20
- %x[git checkout gh-pages]
21
- require "fileutils"
22
- FileUtils.rm_rf "/tmp/html"
23
- FileUtils.mv "html", "/tmp"
24
- FileUtils.rm_rf "*"
25
- FileUtils.cp_r Dir.glob("/tmp/html/*"), "."
26
- end
27
-
28
- task :default => :test