logger 1.4.0 → 1.4.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: 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