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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f455250170001f45e0124012bea062f08d8d072
4
- data.tar.gz: 783a45d09ed579227e8b343e3cd3732fae593fab
3
+ metadata.gz: 829c2ba09350eb621bb0694a0c099c7b392edf20
4
+ data.tar.gz: 43f5a2da899103fd2d42147909723229571a8d8c
5
5
  SHA512:
6
- metadata.gz: b5e3b1f15f2f8d7caa9416cc4c58e76296278daec801a54444203ac47b6685ec54961e7cfa1752f1b5fd6ee322d3a709701dfe892172ef41e5c64a4be8a1bc89
7
- data.tar.gz: 3df9a339830cf81d580f610da7fa88053c7b30cb559d960759ed709b56c28d25e7abc3482d3bed3ddacf0794091a6a320501b6bb7c19e4e75093bdfa982d3411
6
+ metadata.gz: 5c1b55af38672df94b92523b188bf26c36d97e333a225aed93d33c2901a043a0fab5e291749ecfdd91f3fca86e36fec9fd90cbe650e6039ab65cfb181026bd53
7
+ data.tar.gz: ee6f7448f2866dc7a4f5f23e6c92bec98cdbbd9ca34dc96efc93336961a68d2731fc29d7826481b5d092206f1e42c31fe4c5af67f6671232a7ecaf6ea8658d22
@@ -1,10 +1,15 @@
1
- require 'logger'
1
+ require 'English'
2
2
  require 'time'
3
3
 
4
- require 'extended_logger/color_scheme'
5
- require 'extended_logger/configure_levels'
6
- require 'extended_logger/formatter'
7
- require 'extended_logger/logger_substitute'
8
- require 'extended_logger/per_class_logging'
9
-
10
- require 'extended_logger/extended_logger'
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
- attr_reader :map
3
+ def self.build values=nil
4
+ values ||= {}
4
5
 
5
- def initialize map
6
- @map = map
6
+ instance = new
7
+ Palette.apply values, instance
8
+ instance
7
9
  end
8
10
 
9
- def self.build symbol_map
10
- code_map = {}
11
+ def colorize message
12
+ value = get message.level.name
13
+ message.prose = value.colorize message.prose
14
+ end
11
15
 
12
- symbol_map.each do |label, (fg_sym, bg_sym)|
13
- fg = Colors.index fg_sym
14
- bg = Colors.index bg_sym
16
+ def get level_name
17
+ table[level_name]
18
+ end
19
+ alias_method :[], :get
15
20
 
16
- code_map[label] = [fg, bg]
17
- end
21
+ def reset
22
+ "\e[0m"
23
+ end
18
24
 
19
- new code_map
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 color_code code
23
- if code
24
- code.to_s 16
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
- def colorize severity, text
31
- text = text.dup
37
+ None = self.new
32
38
 
33
- fg, bg = map[severity]
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
- if bg
36
- if bg > 8
37
- text.insert 0, "\e[4#{bg - 8}m"
38
- else
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
- if fg
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
- if fg or bg
52
- text << "\e[0m"
53
+ def self.get name
54
+ names.index name
53
55
  end
54
56
 
55
- text
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
- def dump
59
- output = ''.encode 'US-ASCII'
79
+ Value = Struct.new :fg, :bg do
80
+ def colorize prose
81
+ return prose if fg.nil? and bg.nil?
60
82
 
61
- map.each do |level, (fg, bg)|
62
- fg_code = color_code fg
63
- bg_code = color_code bg
64
-
65
- output << ',' unless output.empty?
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
- output
70
- end
71
-
72
- def levels
73
- map.keys
74
- end
90
+ def escape_code
91
+ string = String.new "\e["
75
92
 
76
- def self.decode code
77
- return if code == '?'.freeze
78
- code.to_i 16
79
- end
80
-
81
- def self.load data
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
- values = data.split ','.freeze
100
+ if bg
101
+ string << ';' if fg
85
102
 
86
- values.each do |assignment|
87
- match_data = AssignmentPattern.match assignment
103
+ _, bg_color = bg.divmod 8
104
+ string << '4'
105
+ string << bg_color.to_s
106
+ end
88
107
 
89
- label = match_data[:label]
90
- fg = decode match_data[:fg_code]
91
- bg = decode match_data[:bg_code]
108
+ string << 'm'
92
109
 
93
- map[label] = [fg, bg]
110
+ string
94
111
  end
95
112
 
96
- new map
97
- end
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.normal_verbose
5
- color_scheme = ExtendedLogger::ColorScheme.build(
6
- 'NORMAL' => [:gray, :none],
7
- 'VERBOSE' => [:none, :gray],
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 Loggers
13
- class NormalVerbose < ExtendedLogger
14
- self.levels = %w(VERBOSE NORMAL)
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.multiline
20
- "crcrlf\r\r\n" +
21
- "crlf\r\n" +
22
- "cr\r" +
23
- "lf\n" +
24
- "\n\n" +
25
- " \n" +
26
- "\t\n" +
27
- " \t\n" +
28
- "\n"
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.multiline
34
- <<-TEXT
35
- N, [2000-01-01##{$$}] NORMAL -- : crcrlf\\r\\r\\n
36
- N, [2000-01-01##{$$}] NORMAL -- : crlf\\r\\n
37
- N, [2000-01-01##{$$}] NORMAL -- : cr\\r
38
- N, [2000-01-01##{$$}] NORMAL -- : lf\\n
39
- N, [2000-01-01##{$$}] NORMAL -- : \\n
40
- N, [2000-01-01##{$$}] NORMAL -- : \\n
41
- N, [2000-01-01##{$$}] NORMAL -- : \\n
42
- N, [2000-01-01##{$$}] NORMAL -- : \\t\\n
43
- N, [2000-01-01##{$$}] NORMAL -- : \\t\\n
44
- N, [2000-01-01##{$$}] NORMAL -- : \\n
45
- TEXT
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
- include LoggerSubstitute
3
- extend PerClassLogging
2
+ attr_writer :clock
3
+ attr_accessor :label
4
+ attr_writer :level
5
+ attr_reader :sink
4
6
 
5
- attr_accessor :always_interpolate
6
- attr_writer :color_scheme
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
- if color_scheme and io.tty?
14
- color_scheme = ColorScheme.resolve color_scheme
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 severity, *, &block
22
- if always_interpolate and severity < level
23
- block.() if block
24
- end
18
+ def add level, prose=nil, label: nil, &block
19
+ block ||= ->{ prose }
20
+ label ||= self.label
21
+
22
+ time = clock.now
25
23
 
26
- super
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 color_scheme
30
- @color_scheme ||= ColorScheme::Null
33
+ def device
34
+ sink.device
31
35
  end
32
36
 
33
- def format severity, *arguments
34
- formatted_message = super
35
- color_scheme.colorize severity, formatted_message
37
+ def level
38
+ @level ||= levels.default
36
39
  end
37
40
 
38
- def self.levels= levels
39
- ConfigureLevels.configure_levels self, levels
41
+ def level= reference
42
+ @level = levels.resolve reference
40
43
  end
41
44
 
42
- # ExtendedLogger::Logger can be used in place of ::Logger
43
- class Logger < ExtendedLogger
44
- self.levels = %w(DEBUG INFO WARN ERROR FATAL)
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,13 @@
1
+ class ExtendedLogger
2
+ module Rule
3
+ def call _
4
+ fail "Not implemented"
5
+ end
6
+
7
+ module Assertions
8
+ def filter? message
9
+ if self.(message) then false else true end
10
+ end
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.5.3
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-01-16 00:00:00.000000000 Z
12
- dependencies: []
13
- description: 'An extended logger that provides a (mostly) substitutable alternative
14
- to ruby''s built in +Logger+ class. A number of useful extensions are provided,
15
- including colorized output, the ability to define custom log levels, multi-line
16
- formatting, and per-class logging.
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/formatter.rb
30
- - lib/extended_logger/logger_substitute.rb
31
- - lib/extended_logger/per_class_logging.rb
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