yell 2.0.0.pre → 2.0.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 +5 -13
- data/Gemfile +1 -2
- data/examples/003.4-formatting-on-your-own.rb +2 -2
- data/lib/yell/adapters.rb +36 -16
- data/lib/yell/adapters/base.rb +1 -1
- data/lib/yell/formatter.rb +13 -20
- data/lib/yell/helpers/adapter.rb +4 -18
- data/lib/yell/helpers/formatter.rb +3 -5
- data/lib/yell/helpers/level.rb +7 -3
- data/lib/yell/helpers/silencer.rb +3 -4
- data/lib/yell/helpers/tracer.rb +6 -6
- data/lib/yell/level.rb +1 -1
- data/lib/yell/logger.rb +8 -9
- data/lib/yell/version.rb +1 -1
- data/spec/yell/logger_spec.rb +21 -9
- data/yell.gemspec +1 -0
- metadata +8 -7
checksums.yaml
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
5
|
-
data.tar.gz: !binary |-
|
|
6
|
-
OTExOWM2MmU1NTk3OTU0YzgzODIwYzQ0Njg2ZTMyYTZiYTkxMDYzMQ==
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 2158e0eeef9ba26f9dfeb6dca85a6f95a2d90c95
|
|
4
|
+
data.tar.gz: 9dff5c3e776e545c9704d2fcf574716b87b32c34
|
|
7
5
|
SHA512:
|
|
8
|
-
metadata.gz:
|
|
9
|
-
|
|
10
|
-
MGY4ZmM2N2I2ZTRjODk1NGZmMWY2MzdiNTVhNTI5NWNmNWYyNDJmZTJjMDJl
|
|
11
|
-
NDEzZTc4OGI5YWI2MTkwNTlmZjg3ZjIxNDE2ZTVmZWFkNjcwN2Q=
|
|
12
|
-
data.tar.gz: !binary |-
|
|
13
|
-
ODM2ZTAyZDIwYWFiZmQ3OTE4ZTZiZmNiMGY5ODdkOWMxZmU1NDkzNzY0M2Jl
|
|
14
|
-
OTNkZmYyZTM3MDdkMjlhNDQ1ZDJlNDBiNjZkMDY3MWY3Njk3MzcwNjY0M2Nm
|
|
15
|
-
Y2ZiNjAzZTc4OTQ0NGQ0MDMyNGVhZmIzMGFkYzJmZDMwYzM1NjE=
|
|
6
|
+
metadata.gz: b0f4c57e784a8b45379a2853392de8fb8699ca5155ad5d5333da37d0fdd684c149bac7a86a69dc2e877963b1d55d1119fa7d68b95a161d05c7a01fbab513e5be
|
|
7
|
+
data.tar.gz: 9885f26f334b19200cfb68288cc8720a192144b3a42cd20b33355bdb2300ec8c9debed4a37bcc0ee7f529f6082b4d3c54ac320d929cfff9577249f0aa00b41e5
|
data/Gemfile
CHANGED
|
@@ -6,7 +6,7 @@ puts <<-EOS
|
|
|
6
6
|
|
|
7
7
|
# The extended formatting string looks like: %d [%5L] %p %h : %m.
|
|
8
8
|
|
|
9
|
-
logger = Yell.new STDOUT, :format => "[%f:%n in `%M'] %m"
|
|
9
|
+
logger = Yell.new STDOUT, :format => "[%f:%n in `%M'] %m", :trace => true
|
|
10
10
|
logger.info "Hello World!"
|
|
11
11
|
#=> [003.4-formatting-on-your-own.rb:20 in `<main>'] Hello World!
|
|
12
12
|
# ^ ^ ^ ^
|
|
@@ -16,6 +16,6 @@ logger.info "Hello World!"
|
|
|
16
16
|
EOS
|
|
17
17
|
|
|
18
18
|
puts "=== actuale example ==="
|
|
19
|
-
logger = Yell.new STDOUT, :format => "[%f:%n in `%M'] %m"
|
|
19
|
+
logger = Yell.new STDOUT, :format => "[%f:%n in `%M'] %m", :trace => true
|
|
20
20
|
logger.info "Hello World!"
|
|
21
21
|
|
data/lib/yell/adapters.rb
CHANGED
|
@@ -10,6 +10,42 @@ module Yell #:nodoc:
|
|
|
10
10
|
# directly.
|
|
11
11
|
module Adapters
|
|
12
12
|
|
|
13
|
+
class Collection
|
|
14
|
+
def initialize( options = {} )
|
|
15
|
+
@options = options
|
|
16
|
+
@collection = []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def add( type = :file, *args, &block )
|
|
20
|
+
options = [@options, *args].inject(Hash.new) do |h, c|
|
|
21
|
+
h.merge( [String, Pathname].include?(c.class) ? {:filename => c} : c )
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# remove possible :null adapters
|
|
25
|
+
@collection.shift if @collection.first.instance_of?(Yell::Adapters::Base)
|
|
26
|
+
|
|
27
|
+
new_adapter = Yell::Adapters.new(type, options, &block)
|
|
28
|
+
@collection.push(new_adapter)
|
|
29
|
+
|
|
30
|
+
new_adapter
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def empty?
|
|
34
|
+
@collection.empty?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @private
|
|
38
|
+
def write( event )
|
|
39
|
+
@collection.each { |c| c.write(event) }
|
|
40
|
+
true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @private
|
|
44
|
+
def close
|
|
45
|
+
@collection.each { |c| c.close }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
13
49
|
# holds the list of known adapters
|
|
14
50
|
@adapters = {}
|
|
15
51
|
|
|
@@ -35,25 +71,9 @@ module Yell #:nodoc:
|
|
|
35
71
|
end
|
|
36
72
|
|
|
37
73
|
raise AdapterNotFound.new(name) if adapter.nil?
|
|
38
|
-
|
|
39
74
|
adapter.new(options, &block)
|
|
40
75
|
end
|
|
41
76
|
|
|
42
|
-
# Thanks, railties :-)
|
|
43
|
-
def self.broadcast( adapter )
|
|
44
|
-
Module.new do
|
|
45
|
-
define_method(:write) do |event|
|
|
46
|
-
adapter.write(event)
|
|
47
|
-
super(event)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
define_method(:close) do
|
|
51
|
-
adapter.close
|
|
52
|
-
super()
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
77
|
end
|
|
58
78
|
end
|
|
59
79
|
|
data/lib/yell/adapters/base.rb
CHANGED
data/lib/yell/formatter.rb
CHANGED
|
@@ -160,7 +160,12 @@ module Yell #:nodoc:
|
|
|
160
160
|
def initialize( pattern = nil, date_pattern = nil, &block )
|
|
161
161
|
@modifier = Modifier.new
|
|
162
162
|
|
|
163
|
-
@pattern = pattern
|
|
163
|
+
@pattern = case pattern
|
|
164
|
+
when false then Yell::NoFormat
|
|
165
|
+
when nil then Yell::DefaultFormat
|
|
166
|
+
else pattern
|
|
167
|
+
end
|
|
168
|
+
|
|
164
169
|
@pattern << "\n" unless @pattern[-1] == ?\n # add newline if not present
|
|
165
170
|
@date_pattern = date_pattern || :iso8601
|
|
166
171
|
|
|
@@ -176,11 +181,15 @@ module Yell #:nodoc:
|
|
|
176
181
|
buf = case @date_pattern
|
|
177
182
|
when String then "t.strftime(@date_pattern)"
|
|
178
183
|
when Symbol then respond_to?(@date_pattern, true) ? "#{@date_pattern}(t)" : "t.#{@date_pattern}"
|
|
179
|
-
else
|
|
184
|
+
else t.iso8601
|
|
180
185
|
end
|
|
181
186
|
|
|
182
187
|
# define the method
|
|
183
|
-
instance_eval
|
|
188
|
+
instance_eval <<-METHOD, __FILE__, __LINE__
|
|
189
|
+
def date(t = Time.now)
|
|
190
|
+
#{buf}
|
|
191
|
+
end
|
|
192
|
+
METHOD
|
|
184
193
|
end
|
|
185
194
|
|
|
186
195
|
# define a standard +Logger+ backwards compatible #call method for the formatter
|
|
@@ -193,7 +202,6 @@ module Yell #:nodoc:
|
|
|
193
202
|
end
|
|
194
203
|
|
|
195
204
|
def to_sprintf( table )
|
|
196
|
-
# new and improved Yell version of a formatter call method
|
|
197
205
|
buff, args, _pattern = "", [], @pattern.dup
|
|
198
206
|
|
|
199
207
|
while true
|
|
@@ -208,22 +216,7 @@ module Yell #:nodoc:
|
|
|
208
216
|
_pattern = match[4]
|
|
209
217
|
end
|
|
210
218
|
|
|
211
|
-
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# The iso8601 implementation of the standard Time library is more than
|
|
215
|
-
# twice as slow compared to using strftime. So, we just implement
|
|
216
|
-
# it ourselves --R
|
|
217
|
-
def iso8601( t )
|
|
218
|
-
zone = if t.utc?
|
|
219
|
-
"-00:00"
|
|
220
|
-
else
|
|
221
|
-
offset = t.utc_offset
|
|
222
|
-
sign = offset < 0 ? '-' : '+'
|
|
223
|
-
sprintf('%s%02d:%02d', sign, *(offset.abs/60).divmod(60))
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
t.strftime("%Y-%m-%dT%H:%M:%S#{zone}")
|
|
219
|
+
%Q{sprintf("#{buff.gsub(/"/, '\"')}", #{args.join(', ')})}
|
|
227
220
|
end
|
|
228
221
|
|
|
229
222
|
def level( sev, length = nil )
|
data/lib/yell/helpers/adapter.rb
CHANGED
|
@@ -24,32 +24,18 @@ module Yell #:nodoc:
|
|
|
24
24
|
# @return [Yell::Adapter] The instance
|
|
25
25
|
# @raise [Yell::NoSuchAdapter] Will be thrown when the adapter is not defined
|
|
26
26
|
def adapter( type = :file, *args, &block )
|
|
27
|
-
|
|
28
|
-
h.merge( [String, Pathname].include?(c.class) ? {:filename => c} : c )
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
new_adapter = Yell::Adapters.new(type, options, &block)
|
|
32
|
-
|
|
33
|
-
# Also replaces the :null logger of type Yell::Adapters::Base
|
|
34
|
-
if @_adapter.nil? || @_adapter.instance_of?(Yell::Adapters::Base)
|
|
35
|
-
@_adapter = new_adapter
|
|
36
|
-
else
|
|
37
|
-
@_adapter.extend(Yell::Adapters.broadcast(new_adapter))
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
_adapter
|
|
27
|
+
adapters.add(type, *args, &block)
|
|
41
28
|
end
|
|
42
29
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@_adapter
|
|
30
|
+
def adapters
|
|
31
|
+
@__adapters__
|
|
46
32
|
end
|
|
47
33
|
|
|
48
34
|
|
|
49
35
|
private
|
|
50
36
|
|
|
51
37
|
def reset!
|
|
52
|
-
@
|
|
38
|
+
@__adapters__ = Yell::Adapters::Collection.new(@options)
|
|
53
39
|
|
|
54
40
|
super
|
|
55
41
|
end
|
|
@@ -5,17 +5,15 @@ module Yell #:nodoc:
|
|
|
5
5
|
|
|
6
6
|
# Set the format for your message.
|
|
7
7
|
def formatter=( pattern )
|
|
8
|
-
@
|
|
8
|
+
@__formatter__ = case pattern
|
|
9
9
|
when Yell::Formatter then pattern
|
|
10
|
-
when false then Yell::Formatter.new(Yell::NoFormat)
|
|
11
10
|
else Yell::Formatter.new(*pattern)
|
|
12
11
|
end
|
|
13
12
|
end
|
|
14
13
|
alias :format= :formatter=
|
|
15
14
|
|
|
16
|
-
# @private
|
|
17
15
|
def formatter
|
|
18
|
-
@
|
|
16
|
+
@__formatter__
|
|
19
17
|
end
|
|
20
18
|
alias :format :formatter
|
|
21
19
|
|
|
@@ -23,7 +21,7 @@ module Yell #:nodoc:
|
|
|
23
21
|
private
|
|
24
22
|
|
|
25
23
|
def reset!
|
|
26
|
-
@
|
|
24
|
+
@__formatter__ = Yell::Formatter.new
|
|
27
25
|
|
|
28
26
|
super
|
|
29
27
|
end
|
data/lib/yell/helpers/level.rb
CHANGED
|
@@ -10,18 +10,22 @@ module Yell #:nodoc:
|
|
|
10
10
|
#
|
|
11
11
|
# @param [String, Symbol, Integer] severity The minimum log level
|
|
12
12
|
def level=( severity )
|
|
13
|
-
@
|
|
13
|
+
@__level__ = case severity
|
|
14
|
+
when Yell::Level then severity
|
|
15
|
+
else Yell::Level.new(severity)
|
|
16
|
+
end
|
|
14
17
|
end
|
|
15
18
|
|
|
16
19
|
# @private
|
|
17
20
|
def level
|
|
18
|
-
@
|
|
21
|
+
@__level__
|
|
19
22
|
end
|
|
20
23
|
|
|
24
|
+
|
|
21
25
|
private
|
|
22
26
|
|
|
23
27
|
def reset!
|
|
24
|
-
@
|
|
28
|
+
@__level__ = Yell::Level.new
|
|
25
29
|
|
|
26
30
|
super
|
|
27
31
|
end
|
|
@@ -8,22 +8,21 @@ module Yell #:nodoc:
|
|
|
8
8
|
silencer.add(*patterns)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
# @private
|
|
12
11
|
def silencer
|
|
13
|
-
@
|
|
12
|
+
@__silencer__
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
private
|
|
18
17
|
|
|
19
18
|
def reset!
|
|
20
|
-
@
|
|
19
|
+
@__silencer__ = Yell::Silencer.new
|
|
21
20
|
|
|
22
21
|
super
|
|
23
22
|
end
|
|
24
23
|
|
|
25
24
|
def silence!( *messages )
|
|
26
|
-
|
|
25
|
+
@__silencer__.silence!(*messages) if silencer.silence?
|
|
27
26
|
end
|
|
28
27
|
|
|
29
28
|
end
|
data/lib/yell/helpers/tracer.rb
CHANGED
|
@@ -18,22 +18,22 @@ module Yell #:nodoc:
|
|
|
18
18
|
#
|
|
19
19
|
# @return [Yell::Level] a level representation of the tracer
|
|
20
20
|
def trace=( severity )
|
|
21
|
-
case severity
|
|
22
|
-
when
|
|
23
|
-
|
|
21
|
+
@__trace__ = case severity
|
|
22
|
+
when Yell::Level then severity
|
|
23
|
+
when false then Yell::Level.new("gt.#{Yell::Severities.last}")
|
|
24
|
+
else Yell::Level.new(severity)
|
|
24
25
|
end
|
|
25
26
|
end
|
|
26
27
|
|
|
27
|
-
# @private
|
|
28
28
|
def trace
|
|
29
|
-
@
|
|
29
|
+
@__trace__
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
private
|
|
34
34
|
|
|
35
35
|
def reset!
|
|
36
|
-
@
|
|
36
|
+
@__trace__ = Yell::Level.new('gte.error')
|
|
37
37
|
|
|
38
38
|
super
|
|
39
39
|
end
|
data/lib/yell/level.rb
CHANGED
|
@@ -55,8 +55,8 @@ module Yell #:nodoc:
|
|
|
55
55
|
when Array then at(*severity)
|
|
56
56
|
when Range then gte(severity.first).lte(severity.last)
|
|
57
57
|
when String then interpret(severity)
|
|
58
|
-
when Yell::Level then @severities = severity.severities
|
|
59
58
|
when Integer, Symbol then gte(severity)
|
|
59
|
+
when Yell::Level then @severities = severity.severities
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
data/lib/yell/logger.rb
CHANGED
|
@@ -42,8 +42,6 @@ module Yell #:nodoc:
|
|
|
42
42
|
# l.level = :info
|
|
43
43
|
# end
|
|
44
44
|
def initialize( *args, &block )
|
|
45
|
-
reset!
|
|
46
|
-
|
|
47
45
|
# extract options
|
|
48
46
|
@options = args.last.is_a?(Hash) ? args.pop : {}
|
|
49
47
|
|
|
@@ -52,6 +50,8 @@ module Yell #:nodoc:
|
|
|
52
50
|
@options[:filename] = args.pop unless @options[:filename]
|
|
53
51
|
end
|
|
54
52
|
|
|
53
|
+
reset!
|
|
54
|
+
|
|
55
55
|
# FIXME: :format is deprecated in future versions --R
|
|
56
56
|
self.formatter = @options.fetch(:format, @options[:formatter])
|
|
57
57
|
self.level = @options.fetch(:level, 0)
|
|
@@ -71,7 +71,7 @@ module Yell #:nodoc:
|
|
|
71
71
|
block.arity > 0 ? block.call(self) : instance_eval(&block) if block_given?
|
|
72
72
|
|
|
73
73
|
# default adapter when none defined
|
|
74
|
-
self.adapter(:file) if
|
|
74
|
+
self.adapter(:file) if adapters.empty?
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
|
|
@@ -124,17 +124,16 @@ module Yell #:nodoc:
|
|
|
124
124
|
|
|
125
125
|
# @private
|
|
126
126
|
def close
|
|
127
|
-
|
|
127
|
+
adapters.close
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
private
|
|
132
|
-
|
|
130
|
+
# @private
|
|
133
131
|
def write( event )
|
|
134
|
-
|
|
135
|
-
true
|
|
132
|
+
adapters.write(event)
|
|
136
133
|
end
|
|
137
134
|
|
|
135
|
+
private
|
|
136
|
+
|
|
138
137
|
# The :adapters key may be passed to the options hash. It may appear in
|
|
139
138
|
# multiple variations:
|
|
140
139
|
#
|
data/lib/yell/version.rb
CHANGED
data/spec/yell/logger_spec.rb
CHANGED
|
@@ -48,7 +48,10 @@ describe Yell::Logger do
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
context "default #adapter" do
|
|
51
|
-
|
|
51
|
+
subject { logger.adapters.instance_variable_get(:@collection) }
|
|
52
|
+
|
|
53
|
+
its(:size) { should == 1 }
|
|
54
|
+
its(:first) { should be_kind_of(Yell::Adapters::File) }
|
|
52
55
|
end
|
|
53
56
|
|
|
54
57
|
context "default #level" do
|
|
@@ -150,25 +153,34 @@ describe Yell::Logger do
|
|
|
150
153
|
|
|
151
154
|
context "initialize with a block" do
|
|
152
155
|
let(:level) { Yell::Level.new :error }
|
|
153
|
-
let(:
|
|
154
|
-
let(:adapters) { loggr.instance_variable_get(:@adapters) }
|
|
156
|
+
let(:adapters) { logger.adapters.instance_variable_get(:@collection) }
|
|
155
157
|
|
|
156
158
|
context "with arity" do
|
|
157
|
-
|
|
159
|
+
let(:logger) do
|
|
158
160
|
Yell::Logger.new(:level => level) { |l| l.adapter(:stdout) }
|
|
159
161
|
end
|
|
160
162
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
+
it "should pass the level correctly" do
|
|
164
|
+
expect(logger.level).to eq(level)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "should pass the adapter correctly" do
|
|
168
|
+
expect(adapters.first).to be_instance_of(Yell::Adapters::Stdout)
|
|
169
|
+
end
|
|
163
170
|
end
|
|
164
171
|
|
|
165
172
|
context "without arity" do
|
|
166
|
-
|
|
173
|
+
let(:logger) do
|
|
167
174
|
Yell::Logger.new(:level => level) { adapter(:stdout) }
|
|
168
175
|
end
|
|
169
176
|
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
it "should pass the level correctly" do
|
|
178
|
+
expect(logger.level).to eq(level)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "should pass the adapter correctly" do
|
|
182
|
+
expect(adapters.first).to be_instance_of(Yell::Adapters::Stdout)
|
|
183
|
+
end
|
|
172
184
|
end
|
|
173
185
|
end
|
|
174
186
|
|
data/yell.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yell
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.0
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rudolf Schmidt
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-
|
|
11
|
+
date: 2013-11-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Yell - Your Extensible Logging Library. Define multiple adapters, various
|
|
14
14
|
log level combinations or message formatting options like you've never done before
|
|
@@ -81,7 +81,8 @@ files:
|
|
|
81
81
|
- spec/yell_spec.rb
|
|
82
82
|
- yell.gemspec
|
|
83
83
|
homepage: http://rudionrails.github.com/yell
|
|
84
|
-
licenses:
|
|
84
|
+
licenses:
|
|
85
|
+
- MIT
|
|
85
86
|
metadata: {}
|
|
86
87
|
post_install_message:
|
|
87
88
|
rdoc_options: []
|
|
@@ -89,17 +90,17 @@ require_paths:
|
|
|
89
90
|
- lib
|
|
90
91
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
92
|
requirements:
|
|
92
|
-
- -
|
|
93
|
+
- - '>='
|
|
93
94
|
- !ruby/object:Gem::Version
|
|
94
95
|
version: '0'
|
|
95
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
97
|
requirements:
|
|
97
|
-
- -
|
|
98
|
+
- - '>='
|
|
98
99
|
- !ruby/object:Gem::Version
|
|
99
|
-
version:
|
|
100
|
+
version: '0'
|
|
100
101
|
requirements: []
|
|
101
102
|
rubyforge_project: yell
|
|
102
|
-
rubygems_version: 2.
|
|
103
|
+
rubygems_version: 2.0.6
|
|
103
104
|
signing_key:
|
|
104
105
|
specification_version: 4
|
|
105
106
|
summary: Yell - Your Extensible Logging Library
|