birling 0.1.3 → 0.3.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 +5 -5
- data/.travis.yml +9 -0
- data/Gemfile +4 -3
- data/LICENSE.txt +1 -1
- data/README.md +6 -6
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/birling.gemspec +22 -22
- data/lib/birling.rb +9 -0
- data/lib/birling/formatter.rb +8 -0
- data/lib/birling/logger.rb +117 -69
- data/lib/birling/support.rb +4 -0
- data/test/helper.rb +3 -3
- data/test/test_birling.rb +0 -13
- data/test/test_birling_logger.rb +95 -64
- data/test/test_birling_support.rb +6 -0
- metadata +22 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d21ba47bfcdcfd8d53f782d406a93b300955217f9cc657897a359d16ebf71ca9
|
|
4
|
+
data.tar.gz: c78c0d8a855f174ae1ae10603815a77ffe595383c6dba1057960e5183b3c15c3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 154f866b171df5fc48b40d901f8b21749a4f3c7f25a8560dc4e60c412059ab6be8e54d6d74d0804d38774cda6517f2d5ca570d32621cc1b82a0a1e4e5ad320f2
|
|
7
|
+
data.tar.gz: 517c2a23524f253867037122622fac1ce20545634c0f9c4f79854fafa325268c3f61869bcdf77fa7026c70084010e785d0f1c819b9ca33d639c65fd14566f9e7
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -34,8 +34,8 @@ of ten hourly logs:
|
|
|
34
34
|
```ruby
|
|
35
35
|
logger = Birling.open(
|
|
36
36
|
'test.log',
|
|
37
|
-
:
|
|
38
|
-
:
|
|
37
|
+
period: :hourly,
|
|
38
|
+
retain_count: 10
|
|
39
39
|
)
|
|
40
40
|
```
|
|
41
41
|
|
|
@@ -46,8 +46,8 @@ that period will be removed:
|
|
|
46
46
|
```ruby
|
|
47
47
|
logger = Birling.open(
|
|
48
48
|
'test.log',
|
|
49
|
-
:
|
|
50
|
-
:
|
|
49
|
+
period: :hourly,
|
|
50
|
+
retain_period: 10 * 3600
|
|
51
51
|
)
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -60,7 +60,7 @@ Example:
|
|
|
60
60
|
```ruby
|
|
61
61
|
logger = Birling.open(
|
|
62
62
|
'test.log',
|
|
63
|
-
:
|
|
63
|
+
formatter: -> (severity, time, program, message) { "#{time}> #{message}\n" }
|
|
64
64
|
)
|
|
65
65
|
```
|
|
66
66
|
|
|
@@ -76,4 +76,4 @@ using `STDOUT` the logger will not rotate.
|
|
|
76
76
|
|
|
77
77
|
## Copyright
|
|
78
78
|
|
|
79
|
-
Copyright (c) 2011-
|
|
79
|
+
Copyright (c) 2011-2019 Scott Tadman, PostageApp Ltd.
|
data/Rakefile
CHANGED
|
@@ -14,7 +14,7 @@ require 'jeweler'
|
|
|
14
14
|
|
|
15
15
|
Jeweler::Tasks.new do |gem|
|
|
16
16
|
gem.name = "birling"
|
|
17
|
-
gem.homepage = "http://github.com/
|
|
17
|
+
gem.homepage = "http://github.com/postageapp/birling"
|
|
18
18
|
gem.license = "MIT"
|
|
19
19
|
gem.summary = %Q{Logger with simple log rotation system}
|
|
20
20
|
gem.description = %Q{Mostly drop-in replacement for Logger with a more robust log rotation facility}
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1
|
|
1
|
+
0.3.1
|
data/birling.gemspec
CHANGED
|
@@ -2,24 +2,25 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: birling 0.1
|
|
5
|
+
# stub: birling 0.3.1 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
|
-
s.name = "birling"
|
|
9
|
-
s.version = "0.1
|
|
8
|
+
s.name = "birling".freeze
|
|
9
|
+
s.version = "0.3.1"
|
|
10
10
|
|
|
11
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
12
|
-
s.require_paths = ["lib"]
|
|
13
|
-
s.authors = ["Scott Tadman"]
|
|
14
|
-
s.date = "
|
|
15
|
-
s.description = "Mostly drop-in replacement for Logger with a more robust log rotation facility"
|
|
16
|
-
s.email = "github@tadman.ca"
|
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
|
+
s.require_paths = ["lib".freeze]
|
|
13
|
+
s.authors = ["Scott Tadman".freeze]
|
|
14
|
+
s.date = "2021-03-30"
|
|
15
|
+
s.description = "Mostly drop-in replacement for Logger with a more robust log rotation facility".freeze
|
|
16
|
+
s.email = "github@tadman.ca".freeze
|
|
17
17
|
s.extra_rdoc_files = [
|
|
18
18
|
"LICENSE.txt",
|
|
19
19
|
"README.md"
|
|
20
20
|
]
|
|
21
21
|
s.files = [
|
|
22
22
|
".document",
|
|
23
|
+
".travis.yml",
|
|
23
24
|
"Gemfile",
|
|
24
25
|
"LICENSE.txt",
|
|
25
26
|
"README.md",
|
|
@@ -35,24 +36,23 @@ Gem::Specification.new do |s|
|
|
|
35
36
|
"test/test_birling_logger.rb",
|
|
36
37
|
"test/test_birling_support.rb"
|
|
37
38
|
]
|
|
38
|
-
s.homepage = "http://github.com/
|
|
39
|
-
s.licenses = ["MIT"]
|
|
40
|
-
s.rubygems_version = "
|
|
41
|
-
s.summary = "Logger with simple log rotation system"
|
|
39
|
+
s.homepage = "http://github.com/postageapp/birling".freeze
|
|
40
|
+
s.licenses = ["MIT".freeze]
|
|
41
|
+
s.rubygems_version = "3.2.3".freeze
|
|
42
|
+
s.summary = "Logger with simple log rotation system".freeze
|
|
42
43
|
|
|
43
44
|
if s.respond_to? :specification_version then
|
|
44
45
|
s.specification_version = 4
|
|
46
|
+
end
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
s.add_dependency(%q<bundler>, [">= 0"])
|
|
51
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
|
52
|
-
end
|
|
48
|
+
if s.respond_to? :add_runtime_dependency then
|
|
49
|
+
s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
|
|
50
|
+
s.add_development_dependency(%q<test-unit>.freeze, [">= 0"])
|
|
51
|
+
s.add_development_dependency(%q<jeweler>.freeze, [">= 0"])
|
|
53
52
|
else
|
|
54
|
-
s.add_dependency(%q<bundler
|
|
55
|
-
s.add_dependency(%q<
|
|
53
|
+
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
|
54
|
+
s.add_dependency(%q<test-unit>.freeze, [">= 0"])
|
|
55
|
+
s.add_dependency(%q<jeweler>.freeze, [">= 0"])
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
data/lib/birling.rb
CHANGED
|
@@ -7,6 +7,15 @@ class Birling
|
|
|
7
7
|
|
|
8
8
|
# == Module Methods =======================================================
|
|
9
9
|
|
|
10
|
+
# Opens a new log file at the given path with options:
|
|
11
|
+
# * encoding: The encoding of the file (default: 'UTF8')
|
|
12
|
+
# * period: The rotation period to use (optional)
|
|
13
|
+
# * retain_count: How many log files to retain when rotating (optional)
|
|
14
|
+
# * retain_period: How long rotated log files are retained for (optional)
|
|
15
|
+
# * formatter: Custom log formatter (optional)
|
|
16
|
+
# * program: Name of program being logged (optional)
|
|
17
|
+
# * time_source: Source of time to use (optional)
|
|
18
|
+
# * path_format: The strftime-compatible format for the path (optional)
|
|
10
19
|
def self.open(path, options = nil)
|
|
11
20
|
Birling::Logger.new(path, options)
|
|
12
21
|
end
|
data/lib/birling/formatter.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
|
|
1
3
|
module Birling::Formatter
|
|
2
4
|
# == Constants ============================================================
|
|
3
5
|
|
|
@@ -5,6 +7,12 @@ module Birling::Formatter
|
|
|
5
7
|
|
|
6
8
|
# == Module Methods =======================================================
|
|
7
9
|
|
|
10
|
+
# Default time formatter method.
|
|
11
|
+
def self.time_format(time)
|
|
12
|
+
(time || Time.now).strftime(TIME_FORMAT_DEFAULT)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Implementation for a plug-in Logger formatter.
|
|
8
16
|
def self.call(severity, time, program, message)
|
|
9
17
|
if (program)
|
|
10
18
|
"[#{time.strftime(TIME_FORMAT_DEFAULT)}] <#{program}> #{message}\n"
|
data/lib/birling/logger.rb
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
1
3
|
class Birling::Logger
|
|
2
4
|
# == Constants ============================================================
|
|
3
|
-
|
|
5
|
+
|
|
4
6
|
# These level constants are the same as the syslog system utility
|
|
5
7
|
SEVERITY = {
|
|
6
|
-
:
|
|
7
|
-
:
|
|
8
|
-
:
|
|
9
|
-
:
|
|
10
|
-
:
|
|
11
|
-
:
|
|
12
|
-
:
|
|
13
|
-
:
|
|
14
|
-
:
|
|
8
|
+
emergency: EMERGENCY = 0,
|
|
9
|
+
alert: ALERT = 1,
|
|
10
|
+
critical: CRITICAL = 2,
|
|
11
|
+
error: ERROR = 3,
|
|
12
|
+
warning: WARNING = 4,
|
|
13
|
+
notice: NOTICE = 5,
|
|
14
|
+
info: INFO = 6,
|
|
15
|
+
debug: DEBUG = 7,
|
|
16
|
+
unknown: UNKNOWN = 999
|
|
15
17
|
}.freeze
|
|
16
|
-
|
|
18
|
+
|
|
17
19
|
DEFAULT_SEVERITY = UNKNOWN
|
|
18
20
|
|
|
19
21
|
SEVERITY_LABEL = SEVERITY.invert.freeze
|
|
20
|
-
|
|
22
|
+
|
|
21
23
|
PATH_TIME_DEFAULT = {
|
|
22
|
-
:
|
|
23
|
-
:
|
|
24
|
-
:
|
|
24
|
+
hourly: '%Y%m%d%H'.freeze,
|
|
25
|
+
daily: '%Y%m%d'.freeze,
|
|
26
|
+
default: '%s'.freeze
|
|
25
27
|
}.freeze
|
|
26
|
-
|
|
28
|
+
|
|
27
29
|
# == Properties ===========================================================
|
|
28
30
|
|
|
29
31
|
attr_reader :severity
|
|
@@ -38,24 +40,25 @@ class Birling::Logger
|
|
|
38
40
|
attr_reader :retain_period
|
|
39
41
|
attr_reader :period
|
|
40
42
|
attr_reader :rotation_time
|
|
41
|
-
|
|
43
|
+
|
|
42
44
|
# == Class Methods ========================================================
|
|
43
|
-
|
|
45
|
+
|
|
44
46
|
def self.severity(value)
|
|
45
47
|
case (value)
|
|
46
48
|
when Symbol
|
|
47
49
|
SEVERITY[value] or DEFAULT_SEVERITY
|
|
48
50
|
when String
|
|
49
51
|
SEVERITY[value.to_sym] or DEFAULT_SEVERITY
|
|
50
|
-
when
|
|
52
|
+
when Integer
|
|
51
53
|
SEVERITY_LABEL[value] and value or DEFAULT_SEVERITY
|
|
52
54
|
else
|
|
53
55
|
DEFAULT_SEVERITY
|
|
54
56
|
end
|
|
55
57
|
end
|
|
56
|
-
|
|
58
|
+
|
|
57
59
|
# == Instance Methods =====================================================
|
|
58
60
|
|
|
61
|
+
# Use Birling.open(...) to create new instances.
|
|
59
62
|
def initialize(log, options = nil)
|
|
60
63
|
@encoding = (options and options[:encoding])
|
|
61
64
|
@period = (options and options[:period])
|
|
@@ -69,6 +72,10 @@ class Birling::Logger
|
|
|
69
72
|
|
|
70
73
|
@file_open_options = { }
|
|
71
74
|
|
|
75
|
+
@rotation_time = nil
|
|
76
|
+
@path = nil
|
|
77
|
+
@log = nil
|
|
78
|
+
|
|
72
79
|
if (@encoding)
|
|
73
80
|
@file_open_options[:encoding] = @encoding
|
|
74
81
|
end
|
|
@@ -79,79 +86,112 @@ class Birling::Logger
|
|
|
79
86
|
when String
|
|
80
87
|
@path = log
|
|
81
88
|
end
|
|
82
|
-
|
|
89
|
+
|
|
83
90
|
if (@path and @period)
|
|
84
91
|
@rotation_time = self.next_rotation_time
|
|
85
|
-
|
|
92
|
+
|
|
86
93
|
@path_time_format = (PATH_TIME_DEFAULT[@period] or PATH_TIME_DEFAULT[:default])
|
|
87
|
-
|
|
94
|
+
|
|
88
95
|
@path_format ||=
|
|
89
96
|
@path.sub(/\.(\w+)$/) do |s|
|
|
90
97
|
'.' + @path_time_format + '.' + $1
|
|
91
98
|
end
|
|
92
99
|
end
|
|
93
|
-
|
|
100
|
+
|
|
94
101
|
if (@path and !@log)
|
|
95
102
|
self.log_open!
|
|
96
103
|
end
|
|
97
|
-
|
|
104
|
+
|
|
98
105
|
yield(self) if (block_given?)
|
|
99
106
|
end
|
|
100
|
-
|
|
107
|
+
|
|
108
|
+
# Sets the severity filter for logging. Any messages with a lower severity
|
|
109
|
+
# will be ignored. Any invalid severity options will reset the severity
|
|
110
|
+
# filter to defaults.
|
|
101
111
|
def severity=(value)
|
|
102
112
|
@severity = self.class.severity(value)
|
|
103
113
|
end
|
|
104
|
-
|
|
114
|
+
|
|
115
|
+
# Returns true if the log can be rotated, false otherwise.
|
|
105
116
|
def can_rotate?
|
|
106
117
|
!!@path
|
|
107
118
|
end
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
|
|
120
|
+
# Sets the retention interval for log files. Value should respond to to_i
|
|
121
|
+
# and yield an integer value that's a positive number of seconds between
|
|
122
|
+
# rotation operations.
|
|
113
123
|
def retain=(value)
|
|
114
124
|
@retain = value ? value.to_i : nil
|
|
115
|
-
|
|
125
|
+
|
|
116
126
|
if (@retain_period and @retain_period <= 0)
|
|
117
127
|
@retain_period = nil
|
|
118
128
|
end
|
|
119
|
-
|
|
129
|
+
|
|
120
130
|
@retain_period
|
|
121
131
|
end
|
|
122
|
-
|
|
132
|
+
|
|
133
|
+
# An IO compatible method for writing a message to the file. Only non-empty
|
|
134
|
+
# messages are actually logged.
|
|
135
|
+
def write(message)
|
|
136
|
+
return unless (message.match(/\S/))
|
|
137
|
+
|
|
138
|
+
self.log(:debug, message.chomp)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def sync=(sync)
|
|
142
|
+
# Auto-sync is always turned on, so this operation is ignored.
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def flush
|
|
146
|
+
# Auto-sync is always turned on, so this operation is ignored.
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Log the message for the (optional) program at the given log level. No
|
|
150
|
+
# data will be written if the current log level is not sufficiently high.
|
|
123
151
|
def log(level, message = nil, program = nil)
|
|
124
152
|
return unless (@log)
|
|
125
|
-
|
|
153
|
+
|
|
126
154
|
level = self.class.severity(level)
|
|
127
155
|
program ||= @program
|
|
128
156
|
|
|
129
157
|
self.check_log_rotation!
|
|
130
|
-
|
|
158
|
+
|
|
131
159
|
@log.write(@formatter.call(level, @time_source.now, program, message))
|
|
132
160
|
end
|
|
133
161
|
alias_method :add, :log
|
|
134
162
|
|
|
163
|
+
def puts(*args)
|
|
164
|
+
args.each do |arg|
|
|
165
|
+
self.log(:debug, arg)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Writes to the log file regardless of log level.
|
|
135
170
|
def <<(message)
|
|
136
171
|
return unless (@log)
|
|
137
|
-
|
|
172
|
+
|
|
138
173
|
self.check_log_rotation!
|
|
139
|
-
|
|
174
|
+
|
|
140
175
|
@log.write(message)
|
|
141
176
|
end
|
|
142
|
-
|
|
177
|
+
|
|
178
|
+
# Each of the severity levels has an associated method name. For example:
|
|
179
|
+
# * debug? - Returns true if the logging level is at least debug, false
|
|
180
|
+
# otherwise.
|
|
181
|
+
# * debug(message, program = nil) - Used to log a message with an optional
|
|
182
|
+
# program name.
|
|
143
183
|
SEVERITY.each do |name, level|
|
|
144
184
|
define_method(:"#{name}?") do
|
|
145
185
|
@severity >= level
|
|
146
186
|
end
|
|
147
|
-
|
|
148
|
-
define_method(name) do |message = nil, program = nil|
|
|
187
|
+
|
|
188
|
+
define_method(name) do |message = nil, program = nil, &block|
|
|
149
189
|
return unless (@log and @severity >= level)
|
|
150
|
-
|
|
190
|
+
|
|
151
191
|
program ||= @program
|
|
152
|
-
|
|
192
|
+
|
|
153
193
|
if (!message and block_given?)
|
|
154
|
-
message =
|
|
194
|
+
message = block.call
|
|
155
195
|
end
|
|
156
196
|
|
|
157
197
|
self.check_log_rotation!
|
|
@@ -160,37 +200,43 @@ class Birling::Logger
|
|
|
160
200
|
end
|
|
161
201
|
end
|
|
162
202
|
|
|
203
|
+
# Closes the log.
|
|
163
204
|
def close
|
|
164
205
|
return unless (@log)
|
|
165
|
-
|
|
206
|
+
|
|
166
207
|
@log.close
|
|
167
208
|
@log = nil
|
|
168
209
|
end
|
|
169
|
-
|
|
210
|
+
|
|
211
|
+
# Returns true if the log is opened, false otherwise.
|
|
170
212
|
def opened?
|
|
171
213
|
!!@log
|
|
172
214
|
end
|
|
173
215
|
|
|
216
|
+
# Returns true if the log is closed, false otherwise.
|
|
174
217
|
def closed?
|
|
175
218
|
!@log
|
|
176
219
|
end
|
|
177
220
|
|
|
221
|
+
# Returns the creation time of the log if opened, nil otherwise.
|
|
178
222
|
def create_time
|
|
179
223
|
@log and @log.ctime
|
|
180
224
|
end
|
|
181
|
-
|
|
225
|
+
|
|
226
|
+
# Returns size of the log if opened, nil otherwise.
|
|
182
227
|
def size
|
|
183
228
|
@log and @log.size
|
|
184
229
|
end
|
|
185
|
-
|
|
230
|
+
|
|
231
|
+
# Returns the age of the log file in seconds if opened, nil otherwise.
|
|
186
232
|
def age(relative_to = nil)
|
|
187
|
-
(relative_to || @time_source.now) - @log.ctime
|
|
233
|
+
@log and (relative_to || @time_source.now) - @log.ctime
|
|
188
234
|
end
|
|
189
|
-
|
|
235
|
+
|
|
190
236
|
protected
|
|
191
237
|
def next_rotation_time
|
|
192
238
|
case (@period)
|
|
193
|
-
when
|
|
239
|
+
when Integer, Float
|
|
194
240
|
@time_source.now + @period
|
|
195
241
|
when :daily
|
|
196
242
|
Birling::Support.next_day(@time_source.now)
|
|
@@ -200,21 +246,21 @@ protected
|
|
|
200
246
|
nil
|
|
201
247
|
end
|
|
202
248
|
end
|
|
203
|
-
|
|
249
|
+
|
|
204
250
|
def prune_logs!
|
|
205
251
|
return unless (@path and (@retain_period or @retain_count))
|
|
206
|
-
|
|
252
|
+
|
|
207
253
|
log_spec = @path.sub(/\.(\w+)$/, '*')
|
|
208
|
-
|
|
254
|
+
|
|
209
255
|
logs = (Dir.glob(log_spec) - [ @path ]).collect do |p|
|
|
210
256
|
stat = File.stat(p)
|
|
211
257
|
create_time = (stat and stat.ctime or @time_source.now)
|
|
212
|
-
|
|
258
|
+
|
|
213
259
|
[ p, create_time ]
|
|
214
260
|
end.sort_by do |r|
|
|
215
261
|
r[1] || @time_source.now
|
|
216
262
|
end
|
|
217
|
-
|
|
263
|
+
|
|
218
264
|
if (@retain_period)
|
|
219
265
|
logs.reject! do |r|
|
|
220
266
|
if (Time.now - r[1] > @retain_period)
|
|
@@ -222,23 +268,23 @@ protected
|
|
|
222
268
|
end
|
|
223
269
|
end
|
|
224
270
|
end
|
|
225
|
-
|
|
271
|
+
|
|
226
272
|
if (@retain_count)
|
|
227
273
|
# The logs array is sorted from oldest to newest, so retaining the N
|
|
228
274
|
# newest entries entails stripping them off the end with pop.
|
|
229
275
|
|
|
230
276
|
logs.pop(@retain_count)
|
|
231
|
-
|
|
277
|
+
|
|
232
278
|
FileUtils.rm_f(logs.collect { |r| r[0] })
|
|
233
279
|
end
|
|
234
280
|
end
|
|
235
|
-
|
|
281
|
+
|
|
236
282
|
def check_log_rotation!
|
|
237
283
|
return unless (@rotation_time)
|
|
238
|
-
|
|
284
|
+
|
|
239
285
|
if (@time_source.now >= @rotation_time)
|
|
240
286
|
self.log_open!
|
|
241
|
-
|
|
287
|
+
|
|
242
288
|
@rotation_time = self.next_rotation_time
|
|
243
289
|
end
|
|
244
290
|
end
|
|
@@ -246,23 +292,25 @@ protected
|
|
|
246
292
|
def log_open!
|
|
247
293
|
if (@path_format)
|
|
248
294
|
@current_path = @time_source.now.strftime(@path_format)
|
|
249
|
-
|
|
250
|
-
@log = File.open(@current_path, 'a',
|
|
295
|
+
|
|
296
|
+
@log = File.open(@current_path, 'a', **@file_open_options)
|
|
251
297
|
@log.sync = true
|
|
252
|
-
|
|
253
|
-
if (File.
|
|
298
|
+
|
|
299
|
+
if (File.symlink?(@path))
|
|
254
300
|
File.unlink(@path)
|
|
255
301
|
end
|
|
256
302
|
|
|
257
303
|
unless (File.exist?(@path))
|
|
258
304
|
File.symlink(@current_path, @path)
|
|
259
305
|
end
|
|
260
|
-
|
|
306
|
+
|
|
261
307
|
self.prune_logs!
|
|
262
308
|
else
|
|
263
309
|
@current_path = @path
|
|
264
|
-
|
|
265
|
-
@log = File.open(@current_path, 'a',
|
|
310
|
+
|
|
311
|
+
@log = File.open(@current_path, 'a', **@file_open_options)
|
|
312
|
+
|
|
313
|
+
@log.sync = true
|
|
266
314
|
end
|
|
267
315
|
end
|
|
268
316
|
end
|
data/lib/birling/support.rb
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
module Birling::Support
|
|
2
|
+
# == Module + Mixin Methods ===============================================
|
|
3
|
+
|
|
4
|
+
# Computes the beginning of the next day.
|
|
2
5
|
def next_day(time, time_source = nil)
|
|
3
6
|
(time_source || Time).local(
|
|
4
7
|
time.year,
|
|
@@ -10,6 +13,7 @@ module Birling::Support
|
|
|
10
13
|
) + 1
|
|
11
14
|
end
|
|
12
15
|
|
|
16
|
+
# Computes the beginning of the next hour.
|
|
13
17
|
def next_hour(time, time_source = nil)
|
|
14
18
|
seconds_left = time.to_i % 3600
|
|
15
19
|
|
data/test/helper.rb
CHANGED
|
@@ -54,9 +54,9 @@ class Test::Unit::TestCase
|
|
|
54
54
|
name = "#{name}.log"
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
temp_path ||= File.expand_path('../tmp', File.dirname(__FILE__))
|
|
58
58
|
|
|
59
|
-
full_path = File.expand_path(name,
|
|
59
|
+
full_path = File.expand_path(name, temp_path)
|
|
60
60
|
|
|
61
61
|
FileUtils::mkdir_p(File.dirname(full_path))
|
|
62
62
|
|
|
@@ -64,7 +64,7 @@ class Test::Unit::TestCase
|
|
|
64
64
|
begin
|
|
65
65
|
yield(full_path)
|
|
66
66
|
ensure
|
|
67
|
-
remove_spec = File.expand_path('*',
|
|
67
|
+
remove_spec = File.expand_path('*', temp_path)
|
|
68
68
|
|
|
69
69
|
FileUtils.rm_f(Dir.glob(remove_spec))
|
|
70
70
|
end
|
data/test/test_birling.rb
CHANGED
|
@@ -35,17 +35,4 @@ class TestBirling < Test::Unit::TestCase
|
|
|
35
35
|
|
|
36
36
|
assert !File.exist?(_path)
|
|
37
37
|
end
|
|
38
|
-
|
|
39
|
-
def test_time_warped
|
|
40
|
-
_now = Time.now
|
|
41
|
-
|
|
42
|
-
Time::Warped.now = _now
|
|
43
|
-
|
|
44
|
-
assert_not_equal Time.now, Time.now
|
|
45
|
-
assert_equal _now, Time::Warped.now
|
|
46
|
-
|
|
47
|
-
Time::Warped.now = nil
|
|
48
|
-
|
|
49
|
-
assert_not_equal _now, Time::Warped.now
|
|
50
|
-
end
|
|
51
38
|
end
|
data/test/test_birling_logger.rb
CHANGED
|
@@ -1,47 +1,77 @@
|
|
|
1
|
-
require File.expand_path('helper',
|
|
1
|
+
require File.expand_path('helper', __dir__)
|
|
2
|
+
require 'stringio'
|
|
2
3
|
|
|
3
4
|
class TestBirlingLogger < Test::Unit::TestCase
|
|
4
5
|
def test_defaults
|
|
5
6
|
temp_path do |path|
|
|
6
7
|
log = Birling::Logger.new(path)
|
|
7
|
-
|
|
8
|
+
|
|
8
9
|
assert log
|
|
9
10
|
|
|
10
11
|
assert log.opened?
|
|
11
12
|
assert !log.closed?
|
|
12
13
|
assert_equal 0, log.size
|
|
13
14
|
assert Time.now >= log.create_time
|
|
14
|
-
|
|
15
|
+
|
|
15
16
|
assert_equal Birling::Formatter, log.formatter
|
|
16
17
|
assert_equal Time, log.time_source
|
|
17
18
|
assert_equal nil, log.period
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
def test_with_handle
|
|
22
23
|
s = StringIO.new
|
|
23
|
-
|
|
24
|
+
|
|
24
25
|
log = Birling::Logger.new(s)
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
assert log.opened?
|
|
27
|
-
|
|
28
|
+
|
|
28
29
|
assert_equal 0, log.size
|
|
29
30
|
end
|
|
30
|
-
|
|
31
|
+
|
|
32
|
+
def test_io_compatible
|
|
33
|
+
stdout = $stdout
|
|
34
|
+
|
|
35
|
+
buffer = StringIO.new
|
|
36
|
+
|
|
37
|
+
log = Birling::Logger.new(buffer, time_source: Time::Warped)
|
|
38
|
+
|
|
39
|
+
assert log.opened?
|
|
40
|
+
|
|
41
|
+
assert_equal 0, log.size
|
|
42
|
+
|
|
43
|
+
$stdout = log
|
|
44
|
+
|
|
45
|
+
start = Time.parse('2017-10-10 12:00:00')
|
|
46
|
+
|
|
47
|
+
Time::Warped.now = start
|
|
48
|
+
|
|
49
|
+
puts "Test"
|
|
50
|
+
|
|
51
|
+
log.close
|
|
52
|
+
|
|
53
|
+
expected = "[2017-10-10 12:00:00] Test\n"
|
|
54
|
+
|
|
55
|
+
assert_equal expected, buffer.string.to_s
|
|
56
|
+
|
|
57
|
+
ensure
|
|
58
|
+
$stdout = stdout
|
|
59
|
+
end
|
|
60
|
+
|
|
31
61
|
def test_formatter
|
|
32
62
|
formatter_called = false
|
|
33
63
|
formatter = lambda do |severity, time, program, message|
|
|
34
64
|
formatter_called = true
|
|
35
65
|
message
|
|
36
66
|
end
|
|
37
|
-
|
|
67
|
+
|
|
38
68
|
output = StringIO.new
|
|
39
|
-
log = Birling::Logger.new(output, :
|
|
40
|
-
|
|
69
|
+
log = Birling::Logger.new(output, formatter: formatter)
|
|
70
|
+
|
|
41
71
|
log.debug("Test")
|
|
42
|
-
|
|
72
|
+
|
|
43
73
|
assert_equal true, formatter_called
|
|
44
|
-
|
|
74
|
+
|
|
45
75
|
output.rewind
|
|
46
76
|
assert_equal "Test", output.read
|
|
47
77
|
end
|
|
@@ -49,45 +79,44 @@ class TestBirlingLogger < Test::Unit::TestCase
|
|
|
49
79
|
def test_default_level
|
|
50
80
|
temp_path do |path|
|
|
51
81
|
log = Birling::Logger.new(path)
|
|
52
|
-
|
|
82
|
+
|
|
53
83
|
assert log
|
|
54
84
|
|
|
55
85
|
assert log.opened?
|
|
56
86
|
assert !log.closed?
|
|
57
87
|
assert_equal 0, log.size
|
|
58
|
-
|
|
88
|
+
|
|
59
89
|
assert log.debug?
|
|
60
90
|
|
|
61
91
|
log.debug("Test")
|
|
62
|
-
|
|
92
|
+
|
|
63
93
|
current_size = log.size
|
|
64
94
|
assert current_size > 0
|
|
65
95
|
end
|
|
66
96
|
end
|
|
67
|
-
|
|
97
|
+
|
|
68
98
|
def test_direct_write
|
|
69
99
|
output = StringIO.new
|
|
70
|
-
|
|
100
|
+
|
|
71
101
|
log = Birling::Logger.new(output)
|
|
72
|
-
|
|
102
|
+
|
|
73
103
|
log << "TEST"
|
|
74
|
-
|
|
75
|
-
output.
|
|
76
|
-
assert_equal "TEST", output.read
|
|
104
|
+
|
|
105
|
+
assert_equal "TEST", output.string
|
|
77
106
|
end
|
|
78
|
-
|
|
107
|
+
|
|
79
108
|
def test_level_filter
|
|
80
109
|
output = StringIO.new
|
|
81
|
-
|
|
110
|
+
|
|
82
111
|
log = Birling::Logger.new(
|
|
83
112
|
output,
|
|
84
|
-
:
|
|
85
|
-
:
|
|
113
|
+
formatter: lambda { |s, t, p, m| "#{m}\n" },
|
|
114
|
+
severity: :info
|
|
86
115
|
)
|
|
87
|
-
|
|
116
|
+
|
|
88
117
|
log.debug("DEBUG")
|
|
89
118
|
log.info("INFO")
|
|
90
|
-
|
|
119
|
+
|
|
91
120
|
output.rewind
|
|
92
121
|
assert_equal "INFO\n", output.read
|
|
93
122
|
end
|
|
@@ -99,98 +128,100 @@ class TestBirlingLogger < Test::Unit::TestCase
|
|
|
99
128
|
assert log.debug?
|
|
100
129
|
|
|
101
130
|
log.debug("Test")
|
|
102
|
-
|
|
131
|
+
|
|
103
132
|
current_size = log.size
|
|
104
133
|
assert current_size > 0
|
|
105
|
-
|
|
134
|
+
|
|
106
135
|
create_time = log.create_time
|
|
107
136
|
assert create_time <= Time.now
|
|
108
|
-
|
|
137
|
+
|
|
109
138
|
log.close
|
|
110
|
-
|
|
139
|
+
|
|
111
140
|
log = Birling::Logger.new(path)
|
|
112
|
-
|
|
141
|
+
|
|
113
142
|
assert_equal current_size, log.size
|
|
114
143
|
assert_equal create_time, log.create_time
|
|
115
144
|
end
|
|
116
145
|
end
|
|
117
|
-
|
|
146
|
+
|
|
118
147
|
def test_time_source
|
|
119
148
|
temp_path do |path|
|
|
120
149
|
frozen_time = Time.now
|
|
121
150
|
Time::Warped.now = frozen_time
|
|
122
|
-
|
|
123
|
-
logger = Birling::Logger.new(path, :
|
|
124
|
-
|
|
151
|
+
|
|
152
|
+
logger = Birling::Logger.new(path, time_source: Time::Warped)
|
|
153
|
+
|
|
125
154
|
assert_equal frozen_time, logger.time_source.now
|
|
126
155
|
end
|
|
127
156
|
end
|
|
128
|
-
|
|
157
|
+
|
|
129
158
|
def test_cycling
|
|
130
159
|
temp_path(:cycle) do |path|
|
|
131
160
|
start = Time.now
|
|
132
161
|
Time::Warped.now = start
|
|
133
|
-
logger = Birling::Logger.new(path, :
|
|
134
|
-
|
|
162
|
+
logger = Birling::Logger.new(path, period: 1, time_source: Time::Warped)
|
|
163
|
+
|
|
135
164
|
assert_equal 1, logger.period
|
|
136
|
-
|
|
165
|
+
|
|
137
166
|
current_path = logger.current_path
|
|
138
167
|
assert_equal '%s', logger.path_time_format
|
|
139
|
-
|
|
168
|
+
|
|
140
169
|
logger.debug("Test")
|
|
141
|
-
|
|
170
|
+
|
|
142
171
|
Time::Warped.now += 1
|
|
143
|
-
|
|
172
|
+
|
|
144
173
|
logger.debug("Test")
|
|
145
174
|
|
|
146
175
|
assert_not_equal current_path, logger.current_path
|
|
147
|
-
|
|
176
|
+
|
|
148
177
|
current_path = logger.current_path
|
|
149
178
|
|
|
150
179
|
Time::Warped.now += 1
|
|
151
|
-
|
|
180
|
+
|
|
152
181
|
logger.debug("Test")
|
|
153
|
-
|
|
182
|
+
|
|
154
183
|
assert_not_equal current_path, logger.current_path
|
|
155
184
|
end
|
|
156
185
|
end
|
|
157
|
-
|
|
186
|
+
|
|
158
187
|
def test_retain_count
|
|
159
188
|
temp_path(:cycle) do |path|
|
|
160
189
|
start = Time.now
|
|
161
190
|
Time::Warped.now = start
|
|
162
|
-
|
|
191
|
+
|
|
163
192
|
retain_count = 10
|
|
164
193
|
|
|
165
194
|
logger = Birling::Logger.new(
|
|
166
195
|
path,
|
|
167
|
-
:
|
|
168
|
-
:
|
|
169
|
-
:
|
|
196
|
+
period: 1,
|
|
197
|
+
time_source: Time::Warped,
|
|
198
|
+
retain_count: retain_count
|
|
170
199
|
)
|
|
171
200
|
|
|
172
201
|
(retain_count + 5).times do |n|
|
|
173
202
|
logger.debug("Test")
|
|
203
|
+
|
|
174
204
|
Time::Warped.now += 1
|
|
205
|
+
|
|
175
206
|
logger.debug("Test")
|
|
176
207
|
end
|
|
177
|
-
|
|
208
|
+
|
|
178
209
|
assert_equal retain_count, Dir.glob(logger.path_format % '*').length
|
|
179
210
|
end
|
|
180
211
|
end
|
|
181
|
-
|
|
212
|
+
|
|
182
213
|
def test_default_formatter
|
|
183
214
|
temp_path(:cycle) do |path|
|
|
184
215
|
logger = Birling::Logger.new(path)
|
|
185
|
-
|
|
216
|
+
|
|
186
217
|
lines = 100
|
|
187
|
-
|
|
218
|
+
|
|
188
219
|
lines.times do
|
|
189
220
|
logger.debug("Test")
|
|
190
221
|
end
|
|
191
|
-
|
|
222
|
+
|
|
192
223
|
logger.close
|
|
193
|
-
|
|
224
|
+
|
|
194
225
|
assert_equal lines, File.readlines(path).length
|
|
195
226
|
end
|
|
196
227
|
end
|
|
@@ -198,13 +229,13 @@ class TestBirlingLogger < Test::Unit::TestCase
|
|
|
198
229
|
def test_retain_period
|
|
199
230
|
temp_path(:cycle) do |path|
|
|
200
231
|
retain_period = 3
|
|
201
|
-
|
|
232
|
+
|
|
202
233
|
logger = Birling::Logger.new(
|
|
203
234
|
path,
|
|
204
|
-
:
|
|
205
|
-
:
|
|
235
|
+
period: 1,
|
|
236
|
+
retain_period: retain_period
|
|
206
237
|
)
|
|
207
|
-
|
|
238
|
+
|
|
208
239
|
assert_equal true, File.exist?(path)
|
|
209
240
|
assert_equal true, File.symlink?(path)
|
|
210
241
|
|
|
@@ -215,7 +246,7 @@ class TestBirlingLogger < Test::Unit::TestCase
|
|
|
215
246
|
Time::Warped.now += 1
|
|
216
247
|
logger.debug("Test")
|
|
217
248
|
end
|
|
218
|
-
|
|
249
|
+
|
|
219
250
|
assert_equal retain_period + 1, Dir.glob(logger.path_format % '*').length
|
|
220
251
|
end
|
|
221
252
|
end
|
|
@@ -227,6 +258,6 @@ class TestBirlingLogger < Test::Unit::TestCase
|
|
|
227
258
|
invalid = (0..255).to_a.pack('C*')
|
|
228
259
|
|
|
229
260
|
logger.debug(invalid)
|
|
230
|
-
end
|
|
261
|
+
end
|
|
231
262
|
end
|
|
232
263
|
end
|
|
@@ -4,6 +4,8 @@ class TestBirlingSupport < Test::Unit::TestCase
|
|
|
4
4
|
def test_next_day_on_dst_flip
|
|
5
5
|
in_time_zone('EST5EDT') do
|
|
6
6
|
time = Time.new(2012, 11, 4)
|
|
7
|
+
|
|
8
|
+
assert_equal 'EDT', time.zone
|
|
7
9
|
|
|
8
10
|
assert_equal time.day, (time + 86400).day
|
|
9
11
|
|
|
@@ -21,6 +23,8 @@ class TestBirlingSupport < Test::Unit::TestCase
|
|
|
21
23
|
def test_hour_day_on_dst_flip
|
|
22
24
|
in_time_zone('EST5EDT') do
|
|
23
25
|
time = Time.new(2012, 11, 4, 0, 59, 59) + 1
|
|
26
|
+
|
|
27
|
+
assert_equal 'EDT', time.zone
|
|
24
28
|
|
|
25
29
|
assert_equal time.hour, (time + 3600).hour
|
|
26
30
|
|
|
@@ -40,6 +44,8 @@ class TestBirlingSupport < Test::Unit::TestCase
|
|
|
40
44
|
def test_next_day_at_year_end
|
|
41
45
|
in_time_zone('EST5EDT') do
|
|
42
46
|
time = Time.new(2012, 12, 31)
|
|
47
|
+
|
|
48
|
+
assert_equal 'EST', time.zone
|
|
43
49
|
|
|
44
50
|
next_day = Birling::Support.next_day(time)
|
|
45
51
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: birling
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Tadman
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-03-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: test-unit
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
27
41
|
- !ruby/object:Gem::Dependency
|
|
28
42
|
name: jeweler
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -48,6 +62,7 @@ extra_rdoc_files:
|
|
|
48
62
|
- README.md
|
|
49
63
|
files:
|
|
50
64
|
- ".document"
|
|
65
|
+
- ".travis.yml"
|
|
51
66
|
- Gemfile
|
|
52
67
|
- LICENSE.txt
|
|
53
68
|
- README.md
|
|
@@ -62,11 +77,11 @@ files:
|
|
|
62
77
|
- test/test_birling.rb
|
|
63
78
|
- test/test_birling_logger.rb
|
|
64
79
|
- test/test_birling_support.rb
|
|
65
|
-
homepage: http://github.com/
|
|
80
|
+
homepage: http://github.com/postageapp/birling
|
|
66
81
|
licenses:
|
|
67
82
|
- MIT
|
|
68
83
|
metadata: {}
|
|
69
|
-
post_install_message:
|
|
84
|
+
post_install_message:
|
|
70
85
|
rdoc_options: []
|
|
71
86
|
require_paths:
|
|
72
87
|
- lib
|
|
@@ -81,9 +96,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
81
96
|
- !ruby/object:Gem::Version
|
|
82
97
|
version: '0'
|
|
83
98
|
requirements: []
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
signing_key:
|
|
99
|
+
rubygems_version: 3.2.3
|
|
100
|
+
signing_key:
|
|
87
101
|
specification_version: 4
|
|
88
102
|
summary: Logger with simple log rotation system
|
|
89
103
|
test_files: []
|