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.
Files changed (46) hide show
  1. data/History.txt +13 -0
  2. data/README.rdoc +51 -39
  3. data/Rakefile +1 -0
  4. data/examples/appenders.rb +44 -0
  5. data/examples/classes.rb +39 -0
  6. data/examples/formatting.rb +49 -0
  7. data/examples/hierarchies.rb +71 -0
  8. data/examples/layouts.rb +45 -0
  9. data/examples/loggers.rb +26 -0
  10. data/examples/names.rb +40 -0
  11. data/examples/simple.rb +14 -0
  12. data/lib/logging.rb +50 -21
  13. data/lib/logging/appender.rb +4 -56
  14. data/lib/logging/appenders.rb +120 -0
  15. data/lib/logging/appenders/buffering.rb +2 -1
  16. data/lib/logging/appenders/console.rb +0 -2
  17. data/lib/logging/appenders/rolling_file.rb +0 -2
  18. data/lib/logging/appenders/string_io.rb +1 -3
  19. data/lib/logging/appenders/syslog.rb +0 -7
  20. data/lib/logging/config/configurator.rb +1 -1
  21. data/lib/logging/config/yaml_configurator.rb +3 -7
  22. data/lib/logging/layout.rb +2 -4
  23. data/lib/logging/layouts.rb +47 -0
  24. data/lib/logging/layouts/basic.rb +2 -4
  25. data/lib/logging/layouts/parseable.rb +211 -0
  26. data/lib/logging/layouts/pattern.rb +6 -8
  27. data/lib/logging/log_event.rb +1 -1
  28. data/lib/logging/logger.rb +4 -4
  29. data/lib/spec/logging_helper.rb +2 -2
  30. data/test/appenders/test_buffered_io.rb +26 -18
  31. data/test/appenders/test_console.rb +10 -10
  32. data/test/appenders/test_email.rb +18 -19
  33. data/test/appenders/test_file.rb +12 -12
  34. data/test/appenders/test_growl.rb +11 -12
  35. data/test/appenders/test_io.rb +14 -15
  36. data/test/appenders/test_rolling_file.rb +15 -24
  37. data/test/appenders/test_syslog.rb +10 -10
  38. data/test/layouts/test_basic.rb +4 -5
  39. data/test/layouts/test_json.rb +112 -0
  40. data/test/layouts/test_pattern.rb +9 -9
  41. data/test/layouts/test_yaml.rb +121 -0
  42. data/test/setup.rb +1 -1
  43. data/test/test_appender.rb +0 -14
  44. data/test/test_log_event.rb +1 -1
  45. data/test/test_logging.rb +3 -3
  46. 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
- sudo gem install logging
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
- require 'logging'
25
+ require 'logging'
26
26
 
27
- logger = Logging.logger(STDOUT)
28
- logger.level = :warn
27
+ logger = Logging.logger(STDOUT)
28
+ logger.level = :warn
29
29
 
30
- logger.debug "this debug message will not be output by the logger"
31
- logger.warn "this is your last warning"
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
- require 'logging'
36
+ require 'logging'
37
37
 
38
- logger = Logging::Logger['example_logger']
39
- logger.add_appenders(
40
- Logging::Appender.stdout,
41
- Logging::Appenders::File.new('example.log')
42
- )
43
- logger.level = :info
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
- logger.debug "this debug message will not be output by the logger"
46
- logger.info "just some friendly advice"
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
- 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
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
@@ -27,6 +27,7 @@ PROJ.ignore_file = '.gitignore'
27
27
 
28
28
  PROJ.exclude << %w[^tags$ logging.gemspec]
29
29
  PROJ.rdoc.exclude << '^data'
30
+ PROJ.rdoc.include << '^examples/.*\.rb'
30
31
  #PROJ.rdoc.dir = 'doc/rdoc'
31
32
  #PROJ.rdoc.remote_dir = 'rdoc'
32
33
  PROJ.rdoc.dir = 'doc'
@@ -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"
@@ -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
+
@@ -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!"
@@ -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!!'