logging 0.9.8 → 1.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.
- data/History.txt +13 -0
- data/README.rdoc +51 -39
- data/Rakefile +1 -0
- data/examples/appenders.rb +44 -0
- data/examples/classes.rb +39 -0
- data/examples/formatting.rb +49 -0
- data/examples/hierarchies.rb +71 -0
- data/examples/layouts.rb +45 -0
- data/examples/loggers.rb +26 -0
- data/examples/names.rb +40 -0
- data/examples/simple.rb +14 -0
- data/lib/logging.rb +50 -21
- data/lib/logging/appender.rb +4 -56
- data/lib/logging/appenders.rb +120 -0
- data/lib/logging/appenders/buffering.rb +2 -1
- data/lib/logging/appenders/console.rb +0 -2
- data/lib/logging/appenders/rolling_file.rb +0 -2
- data/lib/logging/appenders/string_io.rb +1 -3
- data/lib/logging/appenders/syslog.rb +0 -7
- data/lib/logging/config/configurator.rb +1 -1
- data/lib/logging/config/yaml_configurator.rb +3 -7
- data/lib/logging/layout.rb +2 -4
- data/lib/logging/layouts.rb +47 -0
- data/lib/logging/layouts/basic.rb +2 -4
- data/lib/logging/layouts/parseable.rb +211 -0
- data/lib/logging/layouts/pattern.rb +6 -8
- data/lib/logging/log_event.rb +1 -1
- data/lib/logging/logger.rb +4 -4
- data/lib/spec/logging_helper.rb +2 -2
- data/test/appenders/test_buffered_io.rb +26 -18
- data/test/appenders/test_console.rb +10 -10
- data/test/appenders/test_email.rb +18 -19
- data/test/appenders/test_file.rb +12 -12
- data/test/appenders/test_growl.rb +11 -12
- data/test/appenders/test_io.rb +14 -15
- data/test/appenders/test_rolling_file.rb +15 -24
- data/test/appenders/test_syslog.rb +10 -10
- data/test/layouts/test_basic.rb +4 -5
- data/test/layouts/test_json.rb +112 -0
- data/test/layouts/test_pattern.rb +9 -9
- data/test/layouts/test_yaml.rb +121 -0
- data/test/setup.rb +1 -1
- data/test/test_appender.rb +0 -14
- data/test/test_log_event.rb +1 -1
- data/test/test_logging.rb +3 -3
- metadata +17 -2
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== 1.0.0 / 2009-04-17
|
2
|
+
|
3
|
+
2 major enhancements
|
4
|
+
- Refactored access to the appenders
|
5
|
+
- Created a much cleaner way to initialize the logging framework
|
6
|
+
3 minor enhancements
|
7
|
+
- Added a YAML layout option
|
8
|
+
- Added a JSON layout option
|
9
|
+
- Cration of an "examples" directory
|
10
|
+
1 bug fix
|
11
|
+
- Logging initialization happens implicitly when a logger, layout, or
|
12
|
+
appender is created
|
13
|
+
|
1
14
|
== 0.9.8 / 2009-04-11
|
2
15
|
|
3
16
|
2 minor enhancements
|
data/README.rdoc
CHANGED
@@ -14,7 +14,7 @@ formatting, and more.
|
|
14
14
|
|
15
15
|
== INSTALL
|
16
16
|
|
17
|
-
|
17
|
+
sudo gem install logging
|
18
18
|
|
19
19
|
== EXAMPLE
|
20
20
|
|
@@ -22,58 +22,70 @@ This example configures a logger to output messages in a format similar to the
|
|
22
22
|
core ruby Logger class. Only log messages that are warnings or higher will be
|
23
23
|
logged.
|
24
24
|
|
25
|
-
|
25
|
+
require 'logging'
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
logger = Logging.logger(STDOUT)
|
28
|
+
logger.level = :warn
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
logger.debug "this debug message will not be output by the logger"
|
31
|
+
logger.warn "this is your last warning"
|
32
32
|
|
33
33
|
In this example, a single logger is crated that will append to STDOUT and to a
|
34
34
|
file. Only log messages that are informational or higher will be logged.
|
35
35
|
|
36
|
-
|
36
|
+
require 'logging'
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
logger = Logging.logger['example_logger']
|
39
|
+
logger.add_appenders(
|
40
|
+
Logging.appenders.stdout,
|
41
|
+
Logging.appenders.file('example.log')
|
42
|
+
)
|
43
|
+
logger.level = :info
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
logger.debug "this debug message will not be output by the logger"
|
46
|
+
logger.info "just some friendly advice"
|
47
47
|
|
48
48
|
The Logging library was created to allow each class in a program to have its
|
49
49
|
own configurable logger. The logging level for a particular class can be
|
50
50
|
changed independently of all other loggers in the system. This example shows
|
51
51
|
the recommended way of accomplishing this.
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
53
|
+
require 'logging'
|
54
|
+
|
55
|
+
Logging.logger['FirstClass'].level = :warn
|
56
|
+
Logging.logger['SecondClass'].level = :debug
|
57
|
+
|
58
|
+
class FirstClass
|
59
|
+
def initialize
|
60
|
+
@log = Logging.logger[self]
|
61
|
+
end
|
62
|
+
|
63
|
+
def some_method
|
64
|
+
@log.debug "some method was called on #{self.inspect}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class SecondClass
|
69
|
+
def initialize
|
70
|
+
@log = Logging.logger[self]
|
71
|
+
end
|
72
|
+
|
73
|
+
def another_method
|
74
|
+
@log.debug "another method was called on #{self.inspect}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
There are many more examples in the "examples" folder of the logging
|
79
|
+
package. The recommended reading order is the following:
|
80
|
+
|
81
|
+
simple.rb
|
82
|
+
loggers.rb
|
83
|
+
classes.rb
|
84
|
+
hierarchies.rb
|
85
|
+
names.rb
|
86
|
+
appenders.rb
|
87
|
+
layouts.rb
|
88
|
+
formatting.rb
|
77
89
|
|
78
90
|
== NOTES
|
79
91
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
# Appenders are used to output log events to some logging destination. The
|
3
|
+
# same log event can be sent to multiple desitnations by associating
|
4
|
+
# multiple appenders with the logger.
|
5
|
+
#
|
6
|
+
# The following is a list of all the available appenders and a brief
|
7
|
+
# description of each. Please refer to the documentation for specific
|
8
|
+
# configuration options available for each.
|
9
|
+
#
|
10
|
+
# Email generates e-mail messages
|
11
|
+
# File writes to a regular file
|
12
|
+
# Growl outputs growl notifications (Mac OS X only)
|
13
|
+
# IO generic IO appender
|
14
|
+
# RollingFile writes to a file and rolls based on size or age
|
15
|
+
# Stdout appends to STDOUT
|
16
|
+
# Stderr appends to STDERR
|
17
|
+
# StringIo writes to a StringIO instance (useful for testing)
|
18
|
+
# Syslog outputs to syslogd (not available on all systems)
|
19
|
+
#
|
20
|
+
# And you can access these appenders:
|
21
|
+
#
|
22
|
+
# Logging.appenders.email
|
23
|
+
# Logging.appenders.file
|
24
|
+
# Logging.appenders.growl
|
25
|
+
# Logging.appenders.io
|
26
|
+
# Logging.appenders.rolling_file
|
27
|
+
# Logging.appenders.stdout
|
28
|
+
# Logging.appenders.stderr
|
29
|
+
# Logging.appenders.string_io
|
30
|
+
# Logging.appenders.syslog
|
31
|
+
#
|
32
|
+
|
33
|
+
require 'logging'
|
34
|
+
|
35
|
+
log = Logging.logger['example']
|
36
|
+
log.add_appenders(
|
37
|
+
Logging.appenders.stdout,
|
38
|
+
Logging.appenders.file('development.log')
|
39
|
+
)
|
40
|
+
log.level = :debug
|
41
|
+
|
42
|
+
# These messages will be logged to both the log file and to STDOUT
|
43
|
+
log.debug "a very nice little debug message"
|
44
|
+
log.warn "this is your last warning"
|
data/examples/classes.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# The Logging framework is very good about figuring out predictable names
|
3
|
+
# for loggers regardless of what object is used to create them. The name is
|
4
|
+
# the class name or module name of whatever is passed to the logger bracket
|
5
|
+
# method. The following lines all return the exact same logger instance:
|
6
|
+
#
|
7
|
+
# ary = Array.new
|
8
|
+
# Logging.logger[ary]
|
9
|
+
# Logging.logger[Array]
|
10
|
+
# Logging.logger['Array']
|
11
|
+
# Logging.logger[:Array]
|
12
|
+
#
|
13
|
+
# So, if you want each class to have it's own logger this is very easy to
|
14
|
+
# do.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'logging'
|
18
|
+
|
19
|
+
Logging.logger.root.appenders = Logging.appenders.stdout
|
20
|
+
Logging.logger.root.level = :info
|
21
|
+
|
22
|
+
class Foo
|
23
|
+
attr_reader :log
|
24
|
+
def initialize() @log = Logging.logger[self]; end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Foo::Bar
|
28
|
+
attr_reader :log
|
29
|
+
def initialize() @log = Logging.logger[self]; end
|
30
|
+
end
|
31
|
+
|
32
|
+
foo = Foo.new.log
|
33
|
+
bar = Foo::Bar.new.log
|
34
|
+
|
35
|
+
# you'll notice in these log messages that the logger names were taken
|
36
|
+
# from the class names of the Foo and Foo::Bar instances
|
37
|
+
foo.info 'this message came from Foo'
|
38
|
+
bar.warn 'this is a warning from Foo::Bar'
|
39
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#
|
2
|
+
# Any Ruby object can be passed to the log methods of a logger. How these
|
3
|
+
# objects are formatted by the Logging framework is controlled by a global
|
4
|
+
# "format_as" option and a global "backtrace" option.
|
5
|
+
#
|
6
|
+
# The format_as option allows objects to be converted to a string using the
|
7
|
+
# standard "to_s" method, the "inspect" method, or the "to_yaml" method
|
8
|
+
# (this is independent of the YAML layout). The format_as option can be
|
9
|
+
# overridden by each layout as desired.
|
10
|
+
#
|
11
|
+
# Logging.format_as :string # or :inspect or :yaml
|
12
|
+
#
|
13
|
+
# Exceptions are treated differently by the logging framework. The Exception
|
14
|
+
# class is printed along with the message. Optionally, exception backtraces
|
15
|
+
# can be included in the logging output; this option is enabled by default.
|
16
|
+
#
|
17
|
+
# Logging.backtrace false
|
18
|
+
#
|
19
|
+
# The backtrace can be enabled or disabled for each layout as needed.
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'logging'
|
23
|
+
|
24
|
+
Logging.format_as :inspect
|
25
|
+
Logging.backtrace false
|
26
|
+
|
27
|
+
Logging.appenders.stdout(
|
28
|
+
:layout => Logging.layouts.basic(:format_as => :yaml)
|
29
|
+
)
|
30
|
+
|
31
|
+
Logging.appenders.stderr(
|
32
|
+
:layout => Logging.layouts.basic(:backtrace => true)
|
33
|
+
)
|
34
|
+
|
35
|
+
log = Logging.logger['foo']
|
36
|
+
log.appenders = %w[stdout stderr]
|
37
|
+
|
38
|
+
# these log messages will all appear twice because of the two appenders -
|
39
|
+
# STDOUT and STDERR - but the interesting thing is the difference in the
|
40
|
+
# output
|
41
|
+
log.info %w[An Array Of Strings]
|
42
|
+
log.info({"one"=>1, "two"=>2})
|
43
|
+
|
44
|
+
begin
|
45
|
+
1 / 0
|
46
|
+
rescue => err
|
47
|
+
log.error err
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#
|
2
|
+
# Loggers exist in a hierarchical relationship defined by their names. Each
|
3
|
+
# logger has a parent (except for the root logger). A logger can zero or
|
4
|
+
# more children. This parent/child relationship is determined by the Ruby
|
5
|
+
# namespace separator '::'.
|
6
|
+
#
|
7
|
+
# root
|
8
|
+
# |-- Foo
|
9
|
+
# | |-- Foo::Bar
|
10
|
+
# | `-- Foo::Baz
|
11
|
+
# |-- ActiveRecord
|
12
|
+
# | `-- ActiveRecord::Base
|
13
|
+
# |-- ActiveSupport
|
14
|
+
# | `-- ActiveSupport::Base
|
15
|
+
# `-- Rails
|
16
|
+
#
|
17
|
+
# A logger inherits its log level from its parent. This level can be set for
|
18
|
+
# each logger in the system. Setting the level on a logger affects all it's
|
19
|
+
# children and grandchildren, etc. unless the child has it's own level set.
|
20
|
+
#
|
21
|
+
# Loggers also have a property called "additivity", and by default it is set
|
22
|
+
# to true for all loggers. This property enables a logger to pass log events
|
23
|
+
# up to its parent.
|
24
|
+
#
|
25
|
+
# If a logger does not have an appender and its additivity is true, it will
|
26
|
+
# pass all log events up to its parent who will then try to send the log
|
27
|
+
# event to its appenders. The parent will do the same thing, passing the log
|
28
|
+
# event up the chain till the root logger is reached or some parent logger
|
29
|
+
# has its additivity set to false.
|
30
|
+
#
|
31
|
+
# So, if the root logger is the only one with an appender, all loggers can
|
32
|
+
# still output log events to the appender because of additivity. A logger
|
33
|
+
# will ALWAYS send log events to its own appenders regardless of its
|
34
|
+
# additivity.
|
35
|
+
#
|
36
|
+
# The show_configuration method can be used to dump the logging hierarchy.
|
37
|
+
#
|
38
|
+
|
39
|
+
require 'logging'
|
40
|
+
|
41
|
+
Logging.logger.root.level = :debug
|
42
|
+
|
43
|
+
foo = Logging.logger['Foo']
|
44
|
+
bar = Logging.logger['Foo::Bar']
|
45
|
+
baz = Logging.logger['Foo::Baz']
|
46
|
+
|
47
|
+
# configure the Foo logger
|
48
|
+
foo.level = 'warn'
|
49
|
+
foo.appenders = Logging.appenders.stdout
|
50
|
+
|
51
|
+
# since Foo is the parent of Foo::Bar and Foo::Baz, these loggers all have
|
52
|
+
# their level set to warn
|
53
|
+
|
54
|
+
foo.warn 'this is a warning, not a ticket'
|
55
|
+
bar.info 'this message will not be logged'
|
56
|
+
baz.info 'nor will this message'
|
57
|
+
bar.error 'but this error message will be logged'
|
58
|
+
|
59
|
+
# let's demonstrate additivity of loggers
|
60
|
+
|
61
|
+
Logging.logger.root.appenders = Logging.appenders.stdout
|
62
|
+
|
63
|
+
baz.warn 'this message will be logged twice - once by Foo and once by root'
|
64
|
+
|
65
|
+
foo.additive = false
|
66
|
+
bar.warn "foo is no longer passing log events up to it's parent"
|
67
|
+
|
68
|
+
# let's look at the logger hierarchy
|
69
|
+
puts '='*76
|
70
|
+
Logging.show_configuration
|
71
|
+
|
data/examples/layouts.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# The formatting of log messages is controlled by the layout given to the
|
3
|
+
# appender. By default all appenders use the Basic layout. It's pretty
|
4
|
+
# basic. However, a more sophisticated Pattern layout can be used or one of
|
5
|
+
# the Parseable layouts -- JSON or YAML.
|
6
|
+
#
|
7
|
+
# The available layouts are:
|
8
|
+
#
|
9
|
+
# Logging.layouts.basic
|
10
|
+
# Logging.layouts.pattern
|
11
|
+
# Logging.layouts.json
|
12
|
+
# Logging.layouts.yaml
|
13
|
+
#
|
14
|
+
# In this example we'll demonstrate use of different layouts and setting log
|
15
|
+
# levels in the appenders to filter out events.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'logging'
|
19
|
+
|
20
|
+
# only show "info" or higher messages on STDOUT using the Basic layout
|
21
|
+
Logging.appenders.stdout(:level => :info)
|
22
|
+
|
23
|
+
# send all log events to the development log (including debug) as JSON
|
24
|
+
Logging.appenders.rolling_file(
|
25
|
+
'development.log',
|
26
|
+
:age => 'daily',
|
27
|
+
:layout => Logging.layouts.json
|
28
|
+
)
|
29
|
+
|
30
|
+
# send growl notifications for errors and fatals using a nice pattern
|
31
|
+
Logging.appenders.growl(
|
32
|
+
'growl',
|
33
|
+
:level => :error,
|
34
|
+
:layout => Logging.layouts.pattern(:pattern => '[%d] %-5l: %m\n')
|
35
|
+
)
|
36
|
+
|
37
|
+
log = Logging.logger['Foo::Bar']
|
38
|
+
log.add_appenders 'stdout', 'development.log', 'growl'
|
39
|
+
log.level = :debug
|
40
|
+
|
41
|
+
log.debug "a very nice little debug message"
|
42
|
+
log.info "things are operating nominally"
|
43
|
+
log.warn "this is your last warning"
|
44
|
+
log.error StandardError.new("something went horribly wrong")
|
45
|
+
log.fatal "I Die!"
|
data/examples/loggers.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#
|
2
|
+
# Multiple loggers can be created and each can be configured with it's own
|
3
|
+
# log level and appenders. So one logger can be configured to output debug
|
4
|
+
# messages, and all the others can be left at the info or warn level. This
|
5
|
+
# makes it easier to debug specific portions of your code.
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'logging'
|
9
|
+
|
10
|
+
# all loggers inherit the log level of the "root" logger
|
11
|
+
# but specific loggers can be given their own level
|
12
|
+
Logging.logger.root.level = :warn
|
13
|
+
|
14
|
+
# similarly, the root appender will be used by all loggers
|
15
|
+
Logging.logger.root.appenders = Logging.appenders.file('output.log')
|
16
|
+
|
17
|
+
log1 = Logging.logger['Log1']
|
18
|
+
log2 = Logging.logger['Log2']
|
19
|
+
log3 = Logging.logger['Log3']
|
20
|
+
|
21
|
+
# you can use strings or symbols to set the log level
|
22
|
+
log3.level = 'debug'
|
23
|
+
|
24
|
+
log1.info "this message will not get logged"
|
25
|
+
log2.info "nor will this message"
|
26
|
+
log3.info "but this message will get logged"
|
data/examples/names.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Loggers and appenders can be looked up by name. The bracket notation is
|
3
|
+
# used to find these objects:
|
4
|
+
#
|
5
|
+
# Logging.logger['foo']
|
6
|
+
# Logging.appenders['bar']
|
7
|
+
#
|
8
|
+
# A logger will be created if a new name is used. Appenders are different;
|
9
|
+
# nil is returned when an unknown appender name is used. The reason for this
|
10
|
+
# is that appenders come in many different flavors (so it is unclear which
|
11
|
+
# type should be created), but there is only one type of logger.
|
12
|
+
#
|
13
|
+
# So it is useful to be able to create an appender and then reference it by
|
14
|
+
# name to add it to multiple loggers. When the same name is used, the same
|
15
|
+
# object will be returned by the bracket methods.
|
16
|
+
#
|
17
|
+
# Layouts do not have names. Some are stateful, and none are threadsafe. So
|
18
|
+
# each appender is configured with it's own layout.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'logging'
|
22
|
+
|
23
|
+
Logging.appenders.file('Debug File', :filename => 'debug.log')
|
24
|
+
Logging.appenders.growl('Growl Notifier', :level => :error)
|
25
|
+
|
26
|
+
# configure the root logger
|
27
|
+
Logging.logger.root.appenders = 'Debug File'
|
28
|
+
Logging.logger.root.level = :debug
|
29
|
+
|
30
|
+
# add the growl notifier to the Critical logger (it will use it's own
|
31
|
+
# appender and the root logger's appender, too)
|
32
|
+
Logging.logger['Critical'].appenders = 'Growl Notifier'
|
33
|
+
|
34
|
+
# if you'll notice above, assigning appenders using just the name is valid
|
35
|
+
# the logger is smart enough to figure out it was given a string and then
|
36
|
+
# go lookup the appender by name
|
37
|
+
|
38
|
+
# and now log some messages
|
39
|
+
Logging.logger['Critical'].info 'just keeping you informed'
|
40
|
+
Logging.logger['Critical'].fatal 'WTF!!'
|