logging 0.9.8 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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!!'
|