extended_logger 0.5.3 → 0.6.0
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 +4 -4
- data/lib/extended_logger.rb +13 -8
- data/lib/extended_logger/color_scheme.rb +81 -109
- data/lib/extended_logger/controls.rb +203 -30
- data/lib/extended_logger/defaults.rb +21 -0
- data/lib/extended_logger/define.rb +37 -0
- data/lib/extended_logger/extended_logger.rb +38 -28
- data/lib/extended_logger/level.rb +25 -0
- data/lib/extended_logger/level/set.rb +64 -0
- data/lib/extended_logger/message.rb +13 -0
- data/lib/extended_logger/rule.rb +13 -0
- data/lib/extended_logger/serializer.rb +44 -0
- data/lib/extended_logger/serializer/text_formatter.rb +37 -0
- data/lib/extended_logger/sink.rb +50 -0
- data/lib/extended_logger/verbosity_threshold.rb +29 -0
- metadata +29 -11
- data/lib/extended_logger/configure_levels.rb +0 -35
- data/lib/extended_logger/formatter.rb +0 -49
- data/lib/extended_logger/logger_substitute.rb +0 -97
- data/lib/extended_logger/per_class_logging.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 829c2ba09350eb621bb0694a0c099c7b392edf20
|
4
|
+
data.tar.gz: 43f5a2da899103fd2d42147909723229571a8d8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c1b55af38672df94b92523b188bf26c36d97e333a225aed93d33c2901a043a0fab5e291749ecfdd91f3fca86e36fec9fd90cbe650e6039ab65cfb181026bd53
|
7
|
+
data.tar.gz: ee6f7448f2866dc7a4f5f23e6c92bec98cdbbd9ca34dc96efc93336961a68d2731fc29d7826481b5d092206f1e42c31fe4c5af67f6671232a7ecaf6ea8658d22
|
data/lib/extended_logger.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
-
require '
|
1
|
+
require 'English'
|
2
2
|
require 'time'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
require_relative './extended_logger/color_scheme'
|
5
|
+
require_relative './extended_logger/defaults'
|
6
|
+
require_relative './extended_logger/define'
|
7
|
+
require_relative './extended_logger/extended_logger'
|
8
|
+
require_relative './extended_logger/level'
|
9
|
+
require_relative './extended_logger/level/set'
|
10
|
+
require_relative './extended_logger/message'
|
11
|
+
require_relative './extended_logger/rule'
|
12
|
+
require_relative './extended_logger/serializer'
|
13
|
+
require_relative './extended_logger/serializer/text_formatter'
|
14
|
+
require_relative './extended_logger/sink'
|
15
|
+
require_relative './extended_logger/verbosity_threshold'
|
@@ -1,146 +1,118 @@
|
|
1
1
|
class ExtendedLogger
|
2
2
|
class ColorScheme
|
3
|
-
|
3
|
+
def self.build values=nil
|
4
|
+
values ||= {}
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
instance = new
|
7
|
+
Palette.apply values, instance
|
8
|
+
instance
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
10
|
-
|
11
|
+
def colorize message
|
12
|
+
value = get message.level.name
|
13
|
+
message.prose = value.colorize message.prose
|
14
|
+
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
def get level_name
|
17
|
+
table[level_name]
|
18
|
+
end
|
19
|
+
alias_method :[], :get
|
15
20
|
|
16
|
-
|
17
|
-
|
21
|
+
def reset
|
22
|
+
"\e[0m"
|
23
|
+
end
|
18
24
|
|
19
|
-
|
25
|
+
def set level_name, fg: nil, bg: nil
|
26
|
+
value = get level_name
|
27
|
+
value.fg = fg if fg
|
28
|
+
value.bg = bg if bg
|
20
29
|
end
|
21
30
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
else
|
26
|
-
'?'.freeze
|
31
|
+
def table
|
32
|
+
@table ||= Hash.new do |hash, level_name|
|
33
|
+
hash[level_name] = Value.new
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
|
-
|
31
|
-
text = text.dup
|
37
|
+
None = self.new
|
32
38
|
|
33
|
-
|
39
|
+
module Palette
|
40
|
+
def self.apply values, color_scheme
|
41
|
+
values.each do |level_name, values|
|
42
|
+
values = { :fg => values } if values.is_a? Symbol
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
text.insert 0, "\e[4#{bg}m"
|
40
|
-
end
|
41
|
-
end
|
44
|
+
values.each_key do |target|
|
45
|
+
color_name = values[target]
|
46
|
+
values[target] = Palette.get color_name
|
47
|
+
end
|
42
48
|
|
43
|
-
|
44
|
-
if fg > 8
|
45
|
-
text.insert 0, "\e[1;3#{fg - 8}m"
|
46
|
-
else
|
47
|
-
text.insert 0, "\e[0;3#{fg}m"
|
49
|
+
color_scheme.set level_name, **values
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
51
|
-
|
52
|
-
|
53
|
+
def self.get name
|
54
|
+
names.index name
|
53
55
|
end
|
54
56
|
|
55
|
-
|
57
|
+
def self.names
|
58
|
+
%i(
|
59
|
+
black
|
60
|
+
red
|
61
|
+
green
|
62
|
+
brown
|
63
|
+
blue
|
64
|
+
magenta
|
65
|
+
cyan
|
66
|
+
gray
|
67
|
+
dark_gray
|
68
|
+
bright_red
|
69
|
+
bright_green
|
70
|
+
yellow
|
71
|
+
bright_blue
|
72
|
+
bright_magenta
|
73
|
+
bright_cyan
|
74
|
+
white
|
75
|
+
)
|
76
|
+
end
|
56
77
|
end
|
57
78
|
|
58
|
-
|
59
|
-
|
79
|
+
Value = Struct.new :fg, :bg do
|
80
|
+
def colorize prose
|
81
|
+
return prose if fg.nil? and bg.nil?
|
60
82
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
output << "#{level}=#{fg_code};#{bg_code}"
|
83
|
+
new_prose = String.new
|
84
|
+
new_prose << escape_code
|
85
|
+
new_prose << prose
|
86
|
+
new_prose << reset
|
87
|
+
new_prose
|
67
88
|
end
|
68
89
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
def levels
|
73
|
-
map.keys
|
74
|
-
end
|
90
|
+
def escape_code
|
91
|
+
string = String.new "\e["
|
75
92
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
map = {}
|
93
|
+
if fg
|
94
|
+
brightness, fg_color = fg.divmod 8
|
95
|
+
string << brightness.to_s
|
96
|
+
string << ';3'
|
97
|
+
string << fg_color.to_s
|
98
|
+
end
|
83
99
|
|
84
|
-
|
100
|
+
if bg
|
101
|
+
string << ';' if fg
|
85
102
|
|
86
|
-
|
87
|
-
|
103
|
+
_, bg_color = bg.divmod 8
|
104
|
+
string << '4'
|
105
|
+
string << bg_color.to_s
|
106
|
+
end
|
88
107
|
|
89
|
-
|
90
|
-
fg = decode match_data[:fg_code]
|
91
|
-
bg = decode match_data[:bg_code]
|
108
|
+
string << 'm'
|
92
109
|
|
93
|
-
|
110
|
+
string
|
94
111
|
end
|
95
112
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
def self.resolve input
|
100
|
-
case input
|
101
|
-
when String then self.load input
|
102
|
-
when true then Default
|
103
|
-
else raise ArgumentError, "Cannot resolve color scheme for #{input.inspect}"
|
113
|
+
def reset
|
114
|
+
"\e[0m"
|
104
115
|
end
|
105
116
|
end
|
106
|
-
|
107
|
-
AssignmentPattern = %r{\A
|
108
|
-
(?<label>[_A-Z]+)
|
109
|
-
=
|
110
|
-
(?<fg_code>[?[:xdigit:]])+
|
111
|
-
;
|
112
|
-
(?<bg_code>[?[:xdigit:]]+)\z
|
113
|
-
}nx
|
114
|
-
|
115
|
-
Colors = %i(
|
116
|
-
black
|
117
|
-
red
|
118
|
-
green
|
119
|
-
brown
|
120
|
-
blue
|
121
|
-
magenta
|
122
|
-
cyan
|
123
|
-
gray
|
124
|
-
|
125
|
-
dark_gray
|
126
|
-
bright_red
|
127
|
-
bright_green
|
128
|
-
yellow
|
129
|
-
bright_blue
|
130
|
-
bright_magenta
|
131
|
-
bright_cyan
|
132
|
-
white
|
133
|
-
)
|
134
|
-
|
135
|
-
Default = self.build(
|
136
|
-
'DEBUG' => [:cyan, nil],
|
137
|
-
'INFO' => [nil, nil],
|
138
|
-
'WARN' => [:brown, nil],
|
139
|
-
'ERROR' => [:red, nil],
|
140
|
-
'FATAL' => [:white, :red],
|
141
|
-
'ANY' => [:white, :blue],
|
142
|
-
)
|
143
|
-
|
144
|
-
Null = self.new Hash.new
|
145
117
|
end
|
146
118
|
end
|
@@ -1,48 +1,221 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
1
3
|
class ExtendedLogger
|
2
4
|
module Controls
|
3
5
|
module ColorSchemes
|
4
|
-
def self.
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def self.example
|
7
|
+
ColorScheme.build(
|
8
|
+
:verbose => { :fg => :black, :bg => :white },
|
9
|
+
:normal => { :fg => :white, :bg => :black },
|
8
10
|
)
|
9
11
|
end
|
12
|
+
|
13
|
+
module None
|
14
|
+
def self.value
|
15
|
+
ColorScheme::None
|
16
|
+
end
|
17
|
+
end
|
10
18
|
end
|
11
19
|
|
12
|
-
module
|
13
|
-
|
14
|
-
self.
|
20
|
+
module Formatters
|
21
|
+
module Plain
|
22
|
+
def self.value
|
23
|
+
-> message do
|
24
|
+
"#{message.level} -- #{message.prose}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Label
|
31
|
+
def self.value
|
32
|
+
'SomeClass'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module Levels
|
37
|
+
def self.ruby_logger
|
38
|
+
Set.ruby_logger.get :info
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.value label=nil
|
42
|
+
label ||= :normal
|
43
|
+
Set.get label
|
44
|
+
end
|
45
|
+
|
46
|
+
module Names
|
47
|
+
def self.ruby_logger
|
48
|
+
%i(debug info warn error fatal)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.value
|
52
|
+
%i(verbose normal)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module Set
|
57
|
+
def self.get name
|
58
|
+
example[name]
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.ruby_logger
|
62
|
+
names = Names.ruby_logger
|
63
|
+
Level::Set.build names
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.example
|
67
|
+
names = Names.value
|
68
|
+
Level::Set.build names, :default => :normal
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Logger < ExtendedLogger.define
|
74
|
+
def self.example device=nil
|
75
|
+
device ||= StringIO.new
|
76
|
+
|
77
|
+
instance = build device
|
78
|
+
instance.clock = Time::Clock
|
79
|
+
instance
|
15
80
|
end
|
16
81
|
end
|
17
82
|
|
18
83
|
module Messages
|
19
|
-
def self.
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
84
|
+
def self.example prose: nil, level: nil, label: nil, time: nil
|
85
|
+
prose ||= Prose.example
|
86
|
+
level ||= Levels.value
|
87
|
+
time ||= Time.reference
|
88
|
+
|
89
|
+
if prose.is_a? Proc
|
90
|
+
block = prose
|
91
|
+
else
|
92
|
+
block = ->{ prose }
|
93
|
+
end
|
94
|
+
|
95
|
+
Message.new block, level, time, label
|
96
|
+
end
|
97
|
+
|
98
|
+
module Label
|
99
|
+
def self.value label=nil
|
100
|
+
label ||= Control::Label.value
|
101
|
+
|
102
|
+
Messages.example label: label
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
module RubyLogger
|
107
|
+
def self.value label=nil
|
108
|
+
level = Level.new :info
|
109
|
+
|
110
|
+
Messages.example level: level, label: label
|
111
|
+
end
|
29
112
|
end
|
30
113
|
end
|
31
114
|
|
32
115
|
module Output
|
33
|
-
def self.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
116
|
+
def self.value prose=nil
|
117
|
+
prose ||= Prose.example
|
118
|
+
"NORMAL -- #{prose}\n"
|
119
|
+
end
|
120
|
+
|
121
|
+
module Colorized
|
122
|
+
def self.value prose=nil
|
123
|
+
prose ||= Prose.example
|
124
|
+
colorized_prose = "\e[1;37;40m#{prose}\e[0m"
|
125
|
+
|
126
|
+
Output.value colorized_prose
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
module MultipleLines
|
131
|
+
def self.value
|
132
|
+
"NORMAL -- Multiple\nNORMAL -- line\nNORMAL -- message\n"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
module RubyLogger
|
137
|
+
def self.log_format
|
138
|
+
@log_format ||= ::Logger::Formatter.new
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.value progname=nil
|
142
|
+
severity = 'INFO'
|
143
|
+
time = Time::Clock.now
|
144
|
+
message = Prose.example
|
145
|
+
|
146
|
+
log_format.(severity, time, progname, message)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
module RuleApplied
|
151
|
+
def self.value
|
152
|
+
prose = Prose.example
|
153
|
+
prose = prose.upcase
|
154
|
+
|
155
|
+
Output.value prose
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
module Prose
|
161
|
+
def self.example
|
162
|
+
SingleLine.value
|
163
|
+
end
|
164
|
+
|
165
|
+
module EscapeCodes
|
166
|
+
def self.value
|
167
|
+
"\t\r"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
module MultipleLines
|
172
|
+
def self.value
|
173
|
+
"Multiple\nline\nmessage"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
module SingleLine
|
178
|
+
def self.value
|
179
|
+
"Some log message"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
module Rule
|
185
|
+
class Example
|
186
|
+
include ExtendedLogger::Rule
|
187
|
+
|
188
|
+
def call message
|
189
|
+
message.prose = message.prose.upcase
|
190
|
+
message
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
module Sink
|
196
|
+
def self.example device=nil, format: nil, rules: nil
|
197
|
+
format ||= Controls::Formatters::Plain.value
|
198
|
+
device ||= StringIO.new
|
199
|
+
levels = Controls::Levels::Set.example
|
200
|
+
|
201
|
+
ExtendedLogger::Sink.build(
|
202
|
+
device,
|
203
|
+
format: format,
|
204
|
+
levels: levels,
|
205
|
+
rules: rules,
|
206
|
+
)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
module Time
|
211
|
+
module Clock
|
212
|
+
def self.now
|
213
|
+
Time.reference
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.reference
|
218
|
+
::Time.new 2000
|
46
219
|
end
|
47
220
|
end
|
48
221
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
module Defaults
|
3
|
+
def self.color_scheme
|
4
|
+
ColorScheme::None
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.log_format
|
8
|
+
@log_format ||= -> message do
|
9
|
+
time = message.time.strftime '%Y-%m-%dT%H:%M:%S.%6N'
|
10
|
+
level = message.level.to_s.rjust 5
|
11
|
+
|
12
|
+
"#{message.level.abbreviation}, [#{time} ##{$$}] #{level} -- #{message.label}: #{message.prose}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.levels
|
17
|
+
level_names = %i(debug info warn error fatal)
|
18
|
+
Level::Set.build level_names
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
def self.define levels=nil, **defaults
|
3
|
+
levels ||= Defaults.levels
|
4
|
+
|
5
|
+
subclass = Class.new self
|
6
|
+
Define.(subclass, levels)
|
7
|
+
subclass
|
8
|
+
end
|
9
|
+
|
10
|
+
class Define
|
11
|
+
attr_reader :levels
|
12
|
+
attr_reader :subclass
|
13
|
+
|
14
|
+
def initialize subclass, levels, **defaults
|
15
|
+
@levels = levels
|
16
|
+
@subclass = subclass
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.call *arguments
|
20
|
+
instance = new *arguments
|
21
|
+
instance.()
|
22
|
+
end
|
23
|
+
|
24
|
+
def call
|
25
|
+
levels = self.levels
|
26
|
+
subclass.send :define_method, :levels do levels end
|
27
|
+
|
28
|
+
levels.each do |level|
|
29
|
+
method_name = level.name
|
30
|
+
|
31
|
+
subclass.send :define_method, method_name do |*arguments, &block|
|
32
|
+
add level, *arguments, &block
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,46 +1,56 @@
|
|
1
1
|
class ExtendedLogger
|
2
|
-
|
3
|
-
|
2
|
+
attr_writer :clock
|
3
|
+
attr_accessor :label
|
4
|
+
attr_writer :level
|
5
|
+
attr_reader :sink
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def self.build io, always_interpolate: nil, color_scheme: nil
|
9
|
-
instance = new io
|
10
|
-
|
11
|
-
instance.always_interpolate = true if always_interpolate
|
7
|
+
def initialize sink
|
8
|
+
@sink = sink
|
9
|
+
end
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
instance.color_scheme = color_scheme
|
16
|
-
end
|
11
|
+
def self.build *arguments
|
12
|
+
sink = Sink.build *arguments
|
17
13
|
|
14
|
+
instance = new sink
|
18
15
|
instance
|
19
16
|
end
|
20
17
|
|
21
|
-
def add
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
def add level, prose=nil, label: nil, &block
|
19
|
+
block ||= ->{ prose }
|
20
|
+
label ||= self.label
|
21
|
+
|
22
|
+
time = clock.now
|
25
23
|
|
26
|
-
|
24
|
+
message = Message.new block, level, time, label
|
25
|
+
|
26
|
+
sink << message
|
27
|
+
end
|
28
|
+
|
29
|
+
def clock
|
30
|
+
@clock ||= Time
|
27
31
|
end
|
28
32
|
|
29
|
-
def
|
30
|
-
|
33
|
+
def device
|
34
|
+
sink.device
|
31
35
|
end
|
32
36
|
|
33
|
-
def
|
34
|
-
|
35
|
-
color_scheme.colorize severity, formatted_message
|
37
|
+
def level
|
38
|
+
@level ||= levels.default
|
36
39
|
end
|
37
40
|
|
38
|
-
def
|
39
|
-
|
41
|
+
def level= reference
|
42
|
+
@level = levels.resolve reference
|
40
43
|
end
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
module Assertions
|
46
|
+
def nothing_written?
|
47
|
+
written? ''
|
48
|
+
end
|
49
|
+
|
50
|
+
def written? expected_data
|
51
|
+
device.rewind
|
52
|
+
actual_data = device.read
|
53
|
+
actual_data == expected_data
|
54
|
+
end
|
45
55
|
end
|
46
56
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
class Level < Struct.new :name, :prev, :next
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
def <=> other
|
6
|
+
self.ordinal <=> other.ordinal
|
7
|
+
end
|
8
|
+
|
9
|
+
def abbreviation
|
10
|
+
label[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
def ordinal
|
14
|
+
@ordinal ||= if prev then prev.ordinal + 1 else 0 end
|
15
|
+
end
|
16
|
+
|
17
|
+
def label
|
18
|
+
@label ||= name.to_s.upcase
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
label
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
class Level
|
3
|
+
class Set
|
4
|
+
attr_reader :default_name
|
5
|
+
attr_reader :names
|
6
|
+
|
7
|
+
def initialize names, default_name=nil
|
8
|
+
@default_name = default_name
|
9
|
+
@names = names
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.build names, default: nil
|
13
|
+
default ||= names.first
|
14
|
+
new names, default
|
15
|
+
end
|
16
|
+
|
17
|
+
def == other
|
18
|
+
default_name == other.default_name and
|
19
|
+
names == other.names
|
20
|
+
end
|
21
|
+
|
22
|
+
def build_index
|
23
|
+
hash = {}
|
24
|
+
|
25
|
+
names.reduce nil do |previous_level, name|
|
26
|
+
level = Level.new name
|
27
|
+
|
28
|
+
level.prev = previous_level
|
29
|
+
previous_level.next = level if previous_level
|
30
|
+
|
31
|
+
hash[name] = level
|
32
|
+
level
|
33
|
+
end
|
34
|
+
|
35
|
+
hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def default
|
39
|
+
get default_name
|
40
|
+
end
|
41
|
+
|
42
|
+
def each &block
|
43
|
+
index.each_value &block
|
44
|
+
end
|
45
|
+
|
46
|
+
def get name
|
47
|
+
index[name]
|
48
|
+
end
|
49
|
+
alias_method :[], :get
|
50
|
+
|
51
|
+
def index
|
52
|
+
@index ||= build_index
|
53
|
+
end
|
54
|
+
|
55
|
+
def resolve reference
|
56
|
+
if reference.is_a? Symbol
|
57
|
+
get reference
|
58
|
+
else
|
59
|
+
get reference.name
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
Message = Struct.new :block, :level, :time, :label do
|
3
|
+
attr_writer :prose
|
4
|
+
|
5
|
+
def inspect
|
6
|
+
"#<ExtendedLogger::Message prose=#{prose.inspect}, level=#{level}, time=#{time.iso8601}, label=#{label.inspect}>"
|
7
|
+
end
|
8
|
+
|
9
|
+
def prose
|
10
|
+
@prose ||= block.()
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
class Serializer
|
3
|
+
attr_writer :color_scheme
|
4
|
+
attr_reader :log_format
|
5
|
+
|
6
|
+
def initialize log_format
|
7
|
+
@log_format = log_format
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.build log_format: nil, color_scheme: nil
|
11
|
+
log_format ||= Defaults.log_format
|
12
|
+
|
13
|
+
instance = new log_format
|
14
|
+
instance.color_scheme = color_scheme if color_scheme
|
15
|
+
instance
|
16
|
+
end
|
17
|
+
|
18
|
+
def call message
|
19
|
+
messages = format_text message
|
20
|
+
|
21
|
+
messages.reduce String.new do |string, message|
|
22
|
+
color_scheme.colorize message
|
23
|
+
|
24
|
+
string << log_format.(message)
|
25
|
+
string << "\n"
|
26
|
+
string
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def color_scheme
|
31
|
+
@color_scheme ||= ColorScheme::None
|
32
|
+
end
|
33
|
+
|
34
|
+
def format_text message
|
35
|
+
lines = TextFormatter.(message.prose)
|
36
|
+
|
37
|
+
lines.map do |line|
|
38
|
+
line_message = message.dup
|
39
|
+
line_message.prose = line
|
40
|
+
line_message
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
class Serializer
|
3
|
+
class TextFormatter
|
4
|
+
attr_reader :prose
|
5
|
+
|
6
|
+
def initialize prose
|
7
|
+
@prose = prose
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.call prose
|
11
|
+
instance = new prose
|
12
|
+
instance.()
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
return %w(<empty message>) if prose.nil? or prose.empty?
|
17
|
+
|
18
|
+
lines.map do |line|
|
19
|
+
line.chomp! if line.match %r{(?<!\r)\n}
|
20
|
+
|
21
|
+
if line.empty?
|
22
|
+
"\\n"
|
23
|
+
else
|
24
|
+
line = line.inspect
|
25
|
+
line.slice! 0, 1
|
26
|
+
line.slice! -1, 1
|
27
|
+
line
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def lines
|
33
|
+
@lines ||= prose.each_line $INPUT_RECORD_SEPARATOR
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
class Sink
|
3
|
+
attr_reader :device
|
4
|
+
attr_reader :levels
|
5
|
+
attr_writer :rules
|
6
|
+
attr_reader :serializer
|
7
|
+
|
8
|
+
def initialize device, levels, serializer
|
9
|
+
@device = device
|
10
|
+
@levels = levels
|
11
|
+
@serializer = serializer
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.build device=nil, format: nil, levels: nil, rules: nil, serializer: nil
|
15
|
+
device ||= $stderr
|
16
|
+
levels ||= Defaults.levels
|
17
|
+
serializer ||= Serializer.build log_format: format
|
18
|
+
|
19
|
+
instance = new device, levels, serializer
|
20
|
+
instance.rules = rules if rules
|
21
|
+
instance
|
22
|
+
end
|
23
|
+
|
24
|
+
def << message
|
25
|
+
message = apply_rules message
|
26
|
+
|
27
|
+
verbosity_threshold.(message) or return
|
28
|
+
|
29
|
+
output = serializer.(message)
|
30
|
+
|
31
|
+
device.write output
|
32
|
+
end
|
33
|
+
|
34
|
+
def apply_rules message
|
35
|
+
rules.reduce message do |message, rule|
|
36
|
+
rule.(message) or return
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def rules
|
41
|
+
@rules ||= []
|
42
|
+
end
|
43
|
+
|
44
|
+
def verbosity_threshold
|
45
|
+
@verbosity_threshold ||= VerbosityThreshold.new levels.default
|
46
|
+
end
|
47
|
+
|
48
|
+
Assertions = ExtendedLogger::Assertions
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ExtendedLogger
|
2
|
+
class VerbosityThreshold
|
3
|
+
include Rule
|
4
|
+
|
5
|
+
attr_accessor :level
|
6
|
+
|
7
|
+
def initialize level
|
8
|
+
@level = level
|
9
|
+
end
|
10
|
+
|
11
|
+
def call message
|
12
|
+
if message.level >= level
|
13
|
+
message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def lower
|
18
|
+
if level.prev
|
19
|
+
self.level = level.prev
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def raise
|
24
|
+
if level.next
|
25
|
+
self.level = level.next
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,19 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extended_logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Ladd
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
date: 2016-02-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: test_bench
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: 'A logging library that provides more feature''s than ruby''s built in
|
28
|
+
logger; namely per-class logging, color schemes, and custom log levels.
|
17
29
|
|
18
30
|
'
|
19
31
|
email: nathanladd+github@gmail.com
|
@@ -23,12 +35,18 @@ extra_rdoc_files: []
|
|
23
35
|
files:
|
24
36
|
- lib/extended_logger.rb
|
25
37
|
- lib/extended_logger/color_scheme.rb
|
26
|
-
- lib/extended_logger/configure_levels.rb
|
27
38
|
- lib/extended_logger/controls.rb
|
39
|
+
- lib/extended_logger/defaults.rb
|
40
|
+
- lib/extended_logger/define.rb
|
28
41
|
- lib/extended_logger/extended_logger.rb
|
29
|
-
- lib/extended_logger/
|
30
|
-
- lib/extended_logger/
|
31
|
-
- lib/extended_logger/
|
42
|
+
- lib/extended_logger/level.rb
|
43
|
+
- lib/extended_logger/level/set.rb
|
44
|
+
- lib/extended_logger/message.rb
|
45
|
+
- lib/extended_logger/rule.rb
|
46
|
+
- lib/extended_logger/serializer.rb
|
47
|
+
- lib/extended_logger/serializer/text_formatter.rb
|
48
|
+
- lib/extended_logger/sink.rb
|
49
|
+
- lib/extended_logger/verbosity_threshold.rb
|
32
50
|
homepage: https://github.com/ntl/extended-logger
|
33
51
|
licenses:
|
34
52
|
- MIT
|
@@ -1,35 +0,0 @@
|
|
1
|
-
class ExtendedLogger
|
2
|
-
module ConfigureLevels
|
3
|
-
def self.configure_levels target, labels
|
4
|
-
levels = []
|
5
|
-
|
6
|
-
labels.each_with_index do |label, severity|
|
7
|
-
level_name = label.upcase
|
8
|
-
levels << level_name
|
9
|
-
|
10
|
-
configure_level target, level_name, severity
|
11
|
-
end
|
12
|
-
|
13
|
-
target.const_set :UNKNOWN, labels.size
|
14
|
-
|
15
|
-
levels.each &:freeze
|
16
|
-
levels.freeze
|
17
|
-
|
18
|
-
target.send :define_singleton_method, :levels do levels end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.configure_level target, level_name, severity
|
22
|
-
method_name = level_name.downcase
|
23
|
-
|
24
|
-
target.send :define_method, "#{method_name}?" do
|
25
|
-
level <= severity
|
26
|
-
end
|
27
|
-
|
28
|
-
target.send :define_method, method_name do |progname=nil, &block|
|
29
|
-
add severity, nil, progname, &block
|
30
|
-
end
|
31
|
-
|
32
|
-
target.const_set level_name, severity
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
class ExtendedLogger
|
2
|
-
class Formatter
|
3
|
-
BlankLine = /\A[[:blank:]]*\z/n
|
4
|
-
LineEnding = /[[:blank:]]*\r*[\r\n]/n
|
5
|
-
Separator = "\n".freeze
|
6
|
-
|
7
|
-
attr_accessor :internal_formatter
|
8
|
-
|
9
|
-
def initialize internal_formatter
|
10
|
-
@internal_formatter = internal_formatter
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.build
|
14
|
-
internal_formatter = ::Logger::Formatter.new
|
15
|
-
new internal_formatter
|
16
|
-
end
|
17
|
-
|
18
|
-
def call *arguments
|
19
|
-
format internal_formatter, *arguments
|
20
|
-
end
|
21
|
-
|
22
|
-
def datetime_format= format
|
23
|
-
internal_formatter.datetime_format = format
|
24
|
-
end
|
25
|
-
|
26
|
-
def format formatter, *arguments, message
|
27
|
-
message = message.to_s
|
28
|
-
message = message.dup
|
29
|
-
|
30
|
-
if BlankLine.match message.to_s
|
31
|
-
formatter.(*arguments, '(empty log message)'.freeze)
|
32
|
-
else
|
33
|
-
message.gsub! LineEnding do |line_ending|
|
34
|
-
quoted = line_ending.inspect[1...-1]
|
35
|
-
quoted << Separator
|
36
|
-
quoted
|
37
|
-
end
|
38
|
-
|
39
|
-
lines = message.split Separator
|
40
|
-
|
41
|
-
lines.reduce String.new do |output, line|
|
42
|
-
formatted_line = formatter.(*arguments, line)
|
43
|
-
output << formatted_line
|
44
|
-
output
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
class ExtendedLogger
|
2
|
-
module LoggerSubstitute
|
3
|
-
attr_writer :clock
|
4
|
-
attr_reader :datetime_format
|
5
|
-
attr_writer :formatter
|
6
|
-
attr_reader :io
|
7
|
-
attr_accessor :progname
|
8
|
-
|
9
|
-
def initialize io
|
10
|
-
@io = io
|
11
|
-
end
|
12
|
-
|
13
|
-
def add severity, message=nil, progname=nil, &block
|
14
|
-
return if log_device.nil?
|
15
|
-
|
16
|
-
severity ||= self.class.const_get :UNKNOWN
|
17
|
-
return if severity < level
|
18
|
-
|
19
|
-
progname ||= self.progname
|
20
|
-
|
21
|
-
if message.nil?
|
22
|
-
if block
|
23
|
-
message = block.()
|
24
|
-
else
|
25
|
-
message = progname
|
26
|
-
progname = self.progname
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
severity_label = self.class.levels[severity] || 'ANY'.freeze
|
31
|
-
|
32
|
-
formatted_message = format severity_label, clock.now, progname, message
|
33
|
-
|
34
|
-
log_device.write formatted_message
|
35
|
-
end
|
36
|
-
alias_method :log, :add
|
37
|
-
|
38
|
-
def clock
|
39
|
-
@clock ||= Time
|
40
|
-
end
|
41
|
-
|
42
|
-
def close
|
43
|
-
log_device.close
|
44
|
-
end
|
45
|
-
|
46
|
-
def datetime_format= format
|
47
|
-
@datetime_format = format
|
48
|
-
default_formatter.datetime_format = format
|
49
|
-
end
|
50
|
-
|
51
|
-
def default_formatter
|
52
|
-
@default_formatter ||= Formatter.build
|
53
|
-
end
|
54
|
-
|
55
|
-
def format *arguments
|
56
|
-
formatter.(*arguments)
|
57
|
-
end
|
58
|
-
|
59
|
-
def formatter
|
60
|
-
@formatter ||= default_formatter
|
61
|
-
end
|
62
|
-
|
63
|
-
def level
|
64
|
-
@level ||= 0
|
65
|
-
end
|
66
|
-
alias_method :sev_threshold, :level
|
67
|
-
|
68
|
-
def level= severity_or_label
|
69
|
-
if severity_or_label.respond_to? :to_int
|
70
|
-
severity = severity_or_label.to_int
|
71
|
-
end
|
72
|
-
|
73
|
-
unless severity
|
74
|
-
label = severity_or_label
|
75
|
-
level = label.to_s.upcase
|
76
|
-
|
77
|
-
severity = self.class.levels.index level
|
78
|
-
end
|
79
|
-
|
80
|
-
unless severity
|
81
|
-
raise ArgumentError, "Not a severity: #{severity_or_label.inspect}"
|
82
|
-
end
|
83
|
-
|
84
|
-
@level = severity
|
85
|
-
end
|
86
|
-
alias_method :sev_threshold=, :level=
|
87
|
-
|
88
|
-
def log_device
|
89
|
-
return unless io
|
90
|
-
@log_device ||= ::Logger::LogDevice.new io
|
91
|
-
end
|
92
|
-
|
93
|
-
def unknown progname=nil, &block
|
94
|
-
add nil, nil, progname, &block
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
class ExtendedLogger
|
2
|
-
module PerClassLogging
|
3
|
-
attr_writer :logger
|
4
|
-
|
5
|
-
def cache
|
6
|
-
@cache ||= Hash.new do |hash, mod|
|
7
|
-
logger = self.logger.dup
|
8
|
-
|
9
|
-
logger.progname = mod
|
10
|
-
logger.level -= verbosity
|
11
|
-
|
12
|
-
hash[mod] = logger
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def configure logger
|
17
|
-
self.logger = logger
|
18
|
-
|
19
|
-
cache.clear
|
20
|
-
end
|
21
|
-
|
22
|
-
def get mod
|
23
|
-
cache[mod]
|
24
|
-
end
|
25
|
-
|
26
|
-
def logger
|
27
|
-
@logger ||= Logger.new $stderr
|
28
|
-
end
|
29
|
-
|
30
|
-
def verbosity
|
31
|
-
@verbosity ||= 0
|
32
|
-
end
|
33
|
-
|
34
|
-
def verbosity= value
|
35
|
-
@verbosity = value
|
36
|
-
|
37
|
-
cache.clear
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|