extended_logger 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|