sgeorgi-logging 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/History.txt +262 -0
  2. data/README.rdoc +115 -0
  3. data/Rakefile +32 -0
  4. data/data/bad_logging_1.rb +13 -0
  5. data/data/bad_logging_2.rb +21 -0
  6. data/data/logging.rb +42 -0
  7. data/data/logging.yaml +63 -0
  8. data/data/simple_logging.rb +13 -0
  9. data/examples/appenders.rb +47 -0
  10. data/examples/classes.rb +41 -0
  11. data/examples/consolidation.rb +83 -0
  12. data/examples/fork.rb +37 -0
  13. data/examples/formatting.rb +51 -0
  14. data/examples/hierarchies.rb +73 -0
  15. data/examples/layouts.rb +48 -0
  16. data/examples/loggers.rb +29 -0
  17. data/examples/names.rb +43 -0
  18. data/examples/simple.rb +17 -0
  19. data/lib/logging.rb +528 -0
  20. data/lib/logging/appender.rb +260 -0
  21. data/lib/logging/appenders.rb +137 -0
  22. data/lib/logging/appenders/buffering.rb +178 -0
  23. data/lib/logging/appenders/console.rb +60 -0
  24. data/lib/logging/appenders/email.rb +75 -0
  25. data/lib/logging/appenders/file.rb +75 -0
  26. data/lib/logging/appenders/growl.rb +197 -0
  27. data/lib/logging/appenders/io.rb +69 -0
  28. data/lib/logging/appenders/rolling_file.rb +327 -0
  29. data/lib/logging/appenders/string_io.rb +68 -0
  30. data/lib/logging/appenders/syslog.rb +210 -0
  31. data/lib/logging/config/configurator.rb +188 -0
  32. data/lib/logging/config/yaml_configurator.rb +191 -0
  33. data/lib/logging/layout.rb +117 -0
  34. data/lib/logging/layouts.rb +47 -0
  35. data/lib/logging/layouts/basic.rb +32 -0
  36. data/lib/logging/layouts/parseable.rb +211 -0
  37. data/lib/logging/layouts/pattern.rb +311 -0
  38. data/lib/logging/log_event.rb +45 -0
  39. data/lib/logging/logger.rb +504 -0
  40. data/lib/logging/repository.rb +232 -0
  41. data/lib/logging/root_logger.rb +61 -0
  42. data/lib/logging/stats.rb +278 -0
  43. data/lib/logging/utils.rb +201 -0
  44. data/lib/spec/logging_helper.rb +34 -0
  45. data/test/appenders/test_buffered_io.rb +176 -0
  46. data/test/appenders/test_console.rb +66 -0
  47. data/test/appenders/test_email.rb +170 -0
  48. data/test/appenders/test_file.rb +95 -0
  49. data/test/appenders/test_growl.rb +127 -0
  50. data/test/appenders/test_io.rb +129 -0
  51. data/test/appenders/test_rolling_file.rb +209 -0
  52. data/test/appenders/test_syslog.rb +194 -0
  53. data/test/benchmark.rb +86 -0
  54. data/test/config/test_configurator.rb +70 -0
  55. data/test/config/test_yaml_configurator.rb +40 -0
  56. data/test/layouts/test_basic.rb +42 -0
  57. data/test/layouts/test_json.rb +112 -0
  58. data/test/layouts/test_pattern.rb +198 -0
  59. data/test/layouts/test_yaml.rb +121 -0
  60. data/test/setup.rb +43 -0
  61. data/test/test_appender.rb +152 -0
  62. data/test/test_consolidate.rb +46 -0
  63. data/test/test_layout.rb +110 -0
  64. data/test/test_log_event.rb +80 -0
  65. data/test/test_logger.rb +699 -0
  66. data/test/test_logging.rb +267 -0
  67. data/test/test_repository.rb +158 -0
  68. data/test/test_root_logger.rb +81 -0
  69. data/test/test_stats.rb +274 -0
  70. data/test/test_utils.rb +116 -0
  71. data/version.txt +1 -0
  72. metadata +227 -0
data/data/logging.rb ADDED
@@ -0,0 +1,42 @@
1
+
2
+ Logging.configure {
3
+
4
+ pre_config {
5
+ levels %w[DEB INF PRT WRN ERR FAT]
6
+ format_as :inspect
7
+ }
8
+
9
+ logger('A::B::C') {
10
+ level 'DEB'
11
+ additive false
12
+ trace false
13
+ appenders %w[stderr logfile]
14
+ }
15
+
16
+ logger('yourlogger') {
17
+ level 'INF'
18
+ appenders %w[stderr logfile]
19
+ }
20
+
21
+ appender('stderr') {
22
+ type 'Stderr'
23
+ level 'DEB'
24
+ layout {
25
+ type 'Basic'
26
+ format_as :string
27
+ }
28
+ }
29
+
30
+ appender('logfile') {
31
+ type 'File'
32
+ level 'DEB'
33
+ filename 'tmp/temp.log'
34
+ truncate true
35
+ layout {
36
+ type 'Pattern'
37
+ date_method 'to_s'
38
+ pattern '[%d] %l %c : %m\n'
39
+ }
40
+ }
41
+
42
+ } # logging configuration
data/data/logging.yaml ADDED
@@ -0,0 +1,63 @@
1
+
2
+ purpose : TestA
3
+ description: This is the 1st YAML doc
4
+ say : Hi
5
+
6
+ ---
7
+ # *** YAML2LOGGING ***
8
+ logging_config:
9
+ # define all pre config ...
10
+ pre_config:
11
+ define_levels:
12
+ - DEB
13
+ - INF
14
+ - PRT
15
+ - WRN
16
+ - ERR
17
+ - FAT
18
+ format_as : inspect
19
+ root:
20
+ level : WRN
21
+
22
+ # define all loggers ...
23
+ loggers:
24
+ - name : mylogger
25
+ level : DEB
26
+ additive : false
27
+ trace : false
28
+ appenders:
29
+ - stderr
30
+ - logfile
31
+
32
+ - name : yourlogger
33
+ level : INF
34
+ appenders:
35
+ - stderr
36
+ - logfile
37
+
38
+ # define all appenders (incl. layouts)
39
+ appenders:
40
+ - type : Stderr
41
+ name : stderr
42
+ level : DEB
43
+ layout:
44
+ type : Basic
45
+ format_as : string
46
+
47
+ - type : File
48
+ name : logfile
49
+ level : DEB
50
+ filename : 'tmp/temp.log'
51
+ truncate : true
52
+ layout:
53
+ type : Pattern
54
+ date_method : to_s
55
+ pattern : '[%d] %l %c : %m\n'
56
+
57
+ ---
58
+ purpose : TestB
59
+ description: This is the last YAML doc
60
+ say : Bye
61
+
62
+
63
+ # EOF
@@ -0,0 +1,13 @@
1
+
2
+ Logging.configure {
3
+
4
+ logger(:root) {
5
+ level :info
6
+ appenders 'stdout'
7
+ }
8
+
9
+ appender('stdout') {
10
+ type 'Stdout'
11
+ }
12
+
13
+ } # logging configuration
@@ -0,0 +1,47 @@
1
+ # :stopdoc:
2
+ #
3
+ # Appenders are used to output log events to some logging destination. The
4
+ # same log event can be sent to multiple desitnations by associating
5
+ # multiple appenders with the logger.
6
+ #
7
+ # The following is a list of all the available appenders and a brief
8
+ # description of each. Please refer to the documentation for specific
9
+ # configuration options available for each.
10
+ #
11
+ # Email generates e-mail messages
12
+ # File writes to a regular file
13
+ # Growl outputs growl notifications (Mac OS X only)
14
+ # IO generic IO appender
15
+ # RollingFile writes to a file and rolls based on size or age
16
+ # Stdout appends to STDOUT
17
+ # Stderr appends to STDERR
18
+ # StringIo writes to a StringIO instance (useful for testing)
19
+ # Syslog outputs to syslogd (not available on all systems)
20
+ #
21
+ # And you can access these appenders:
22
+ #
23
+ # Logging.appenders.email
24
+ # Logging.appenders.file
25
+ # Logging.appenders.growl
26
+ # Logging.appenders.io
27
+ # Logging.appenders.rolling_file
28
+ # Logging.appenders.stdout
29
+ # Logging.appenders.stderr
30
+ # Logging.appenders.string_io
31
+ # Logging.appenders.syslog
32
+ #
33
+
34
+ require 'logging'
35
+
36
+ log = Logging.logger['example']
37
+ log.add_appenders(
38
+ Logging.appenders.stdout,
39
+ Logging.appenders.file('development.log')
40
+ )
41
+ log.level = :debug
42
+
43
+ # These messages will be logged to both the log file and to STDOUT
44
+ log.debug "a very nice little debug message"
45
+ log.warn "this is your last warning"
46
+
47
+ # :startdoc:
@@ -0,0 +1,41 @@
1
+ # :stopdoc:
2
+ #
3
+ # The Logging framework is very good about figuring out predictable names
4
+ # for loggers regardless of what object is used to create them. The name is
5
+ # the class name or module name of whatever is passed to the logger bracket
6
+ # method. The following lines all return the exact same logger instance:
7
+ #
8
+ # ary = Array.new
9
+ # Logging.logger[ary]
10
+ # Logging.logger[Array]
11
+ # Logging.logger['Array']
12
+ # Logging.logger[:Array]
13
+ #
14
+ # So, if you want each class to have it's own logger this is very easy to
15
+ # do.
16
+ #
17
+
18
+ require 'logging'
19
+
20
+ Logging.logger.root.appenders = Logging.appenders.stdout
21
+ Logging.logger.root.level = :info
22
+
23
+ class Foo
24
+ attr_reader :log
25
+ def initialize() @log = Logging.logger[self]; end
26
+ end
27
+
28
+ class Foo::Bar
29
+ attr_reader :log
30
+ def initialize() @log = Logging.logger[self]; end
31
+ end
32
+
33
+ foo = Foo.new.log
34
+ bar = Foo::Bar.new.log
35
+
36
+ # you'll notice in these log messages that the logger names were taken
37
+ # from the class names of the Foo and Foo::Bar instances
38
+ foo.info 'this message came from Foo'
39
+ bar.warn 'this is a warning from Foo::Bar'
40
+
41
+ # :startdoc:
@@ -0,0 +1,83 @@
1
+ # :stopdoc:
2
+ #
3
+ # Logging support can be included globally giving all objects in the Ruby
4
+ # space access to a logger instance. This "logger" method invokes
5
+ #
6
+ # Logging.logger[self]
7
+ #
8
+ # And returns the appropriate logger for the current context.
9
+ #
10
+ # However, there might be times when it is not desirable to create an
11
+ # individual logger for every class and module. This is where the concept of
12
+ # "logger consolidation" comes into play. A ruby namespace can be configured
13
+ # to consolidate loggers such that all classes and modules in that namespace
14
+ # use the same logger instance.
15
+ #
16
+ # Because our loggers are being accessed via the self context, it becomes
17
+ # very easy to turn on debugging on a class-by-class basis (or a
18
+ # module-by-module basis). The trick is to create the debug logger first and
19
+ # then configure the namespace to consolidate all loggers. Since we already
20
+ # created our debug logger, it will be used by the class in question instead
21
+ # of the consolidated namespace logger.
22
+ #
23
+
24
+ require 'logging'
25
+ include Logging.globally
26
+
27
+ Logging.logger.root.appenders = Logging.appenders.stdout
28
+ Logging.logger.root.level = :info
29
+
30
+ # we want to debug the "FooBar" module of ActiveRecord
31
+ Logging.logger['ActiveRecord::FooBar'].level = :debug
32
+
33
+ # and we want everything else in ActiveRecord and ActiveResource
34
+ # to use the same consolidated loggers (one for each namespace)
35
+ Logging.consolidate 'ActiveRecord', 'ActiveResource'
36
+
37
+
38
+ logger.info 'because we included Logging globally, ' \
39
+ 'we have access to a logger anywhere in our code'
40
+
41
+
42
+ module ActiveRecord
43
+ logger.info 'even at the module level'
44
+
45
+ class Base
46
+ logger.info 'and at the class level'
47
+ end
48
+ end
49
+
50
+
51
+ module ActiveResource
52
+ logger.info "you'll notice that these log messages " \
53
+ "are coming from the same logger"
54
+
55
+ class Base
56
+ logger.info "even though the logger is invoked from different classes"
57
+ end
58
+
59
+ class Foo
60
+ def foo
61
+ logger.info "that is because ActiveRecord and ActiveResource " \
62
+ "are consolidating loggers in their respective namespaces"
63
+ end
64
+ end
65
+ Foo.new.foo
66
+ end
67
+
68
+
69
+ module ActiveRecord
70
+ logger.debug 'this debug message will not be logged ' \
71
+ '- level is info'
72
+
73
+ class Base
74
+ logger.debug 'and this debug message will not be logged either ' \
75
+ '- same logger as above'
76
+ end
77
+
78
+ module FooBar
79
+ logger.debug 'however, this debug message WILL be logged'
80
+ end
81
+ end
82
+
83
+ # :startdoc:
data/examples/fork.rb ADDED
@@ -0,0 +1,37 @@
1
+ # :stopdoc:
2
+ #
3
+ # Because of the global interpreter lock, Kernel#fork is the best way
4
+ # to acheive true concurrency in Ruby scripts. However, there are pecularities
5
+ # when using frok and passing file descriptors between process. These
6
+ # pecularities affect the logging framework.
7
+ #
8
+ # In short, always reopen file descriptors in the child process after fork has
9
+ # been called. The RollingFile appender uses flock to safely coordinate the
10
+ # rolling of the log file when multiple processes are writing to the same
11
+ # file. If the file descriptor is opened in the parent and multiple children
12
+ # are forked, then each child will use the same file descriptor lock; when one
13
+ # child locks the file any other child will also have the lock. This creates a
14
+ # race condition in the rolling code. The solution is to reopen the file to
15
+ # obtain a new file descriptor in each of the children.
16
+ #
17
+
18
+ require 'logging'
19
+
20
+ log = Logging.logger['example']
21
+ log.add_appenders(
22
+ Logging.appenders.rolling_file('roller.log', :age => 'daily')
23
+ )
24
+ log.level = :debug
25
+
26
+ # Create four child processes and reopen the "roller.log" file descriptor in
27
+ # each child. Now log rolling will work safely.
28
+ 4.times do
29
+ fork {
30
+ Logging.reopen
31
+ log.info "This is child process #{Process.pid}"
32
+ }
33
+ end
34
+
35
+ log.info "This is the parent process #{Process.pid}"
36
+
37
+ # :startdoc:
@@ -0,0 +1,51 @@
1
+ # :stopdoc:
2
+ #
3
+ # Any Ruby object can be passed to the log methods of a logger. How these
4
+ # objects are formatted by the Logging framework is controlled by a global
5
+ # "format_as" option and a global "backtrace" option.
6
+ #
7
+ # The format_as option allows objects to be converted to a string using the
8
+ # standard "to_s" method, the "inspect" method, or the "to_yaml" method
9
+ # (this is independent of the YAML layout). The format_as option can be
10
+ # overridden by each layout as desired.
11
+ #
12
+ # Logging.format_as :string # or :inspect or :yaml
13
+ #
14
+ # Exceptions are treated differently by the logging framework. The Exception
15
+ # class is printed along with the message. Optionally, exception backtraces
16
+ # can be included in the logging output; this option is enabled by default.
17
+ #
18
+ # Logging.backtrace false
19
+ #
20
+ # The backtrace can be enabled or disabled for each layout as needed.
21
+ #
22
+
23
+ require 'logging'
24
+
25
+ Logging.format_as :inspect
26
+ Logging.backtrace false
27
+
28
+ Logging.appenders.stdout(
29
+ :layout => Logging.layouts.basic(:format_as => :yaml)
30
+ )
31
+
32
+ Logging.appenders.stderr(
33
+ :layout => Logging.layouts.basic(:backtrace => true)
34
+ )
35
+
36
+ log = Logging.logger['foo']
37
+ log.appenders = %w[stdout stderr]
38
+
39
+ # these log messages will all appear twice because of the two appenders -
40
+ # STDOUT and STDERR - but the interesting thing is the difference in the
41
+ # output
42
+ log.info %w[An Array Of Strings]
43
+ log.info({"one"=>1, "two"=>2})
44
+
45
+ begin
46
+ 1 / 0
47
+ rescue => err
48
+ log.error err
49
+ end
50
+
51
+ # :startdoc:
@@ -0,0 +1,73 @@
1
+ # :stopdoc:
2
+ #
3
+ # Loggers exist in a hierarchical relationship defined by their names. Each
4
+ # logger has a parent (except for the root logger). A logger can zero or
5
+ # more children. This parent/child relationship is determined by the Ruby
6
+ # namespace separator '::'.
7
+ #
8
+ # root
9
+ # |-- Foo
10
+ # | |-- Foo::Bar
11
+ # | `-- Foo::Baz
12
+ # |-- ActiveRecord
13
+ # | `-- ActiveRecord::Base
14
+ # |-- ActiveSupport
15
+ # | `-- ActiveSupport::Base
16
+ # `-- Rails
17
+ #
18
+ # A logger inherits its log level from its parent. This level can be set for
19
+ # each logger in the system. Setting the level on a logger affects all it's
20
+ # children and grandchildren, etc. unless the child has it's own level set.
21
+ #
22
+ # Loggers also have a property called "additivity", and by default it is set
23
+ # to true for all loggers. This property enables a logger to pass log events
24
+ # up to its parent.
25
+ #
26
+ # If a logger does not have an appender and its additivity is true, it will
27
+ # pass all log events up to its parent who will then try to send the log
28
+ # event to its appenders. The parent will do the same thing, passing the log
29
+ # event up the chain till the root logger is reached or some parent logger
30
+ # has its additivity set to false.
31
+ #
32
+ # So, if the root logger is the only one with an appender, all loggers can
33
+ # still output log events to the appender because of additivity. A logger
34
+ # will ALWAYS send log events to its own appenders regardless of its
35
+ # additivity.
36
+ #
37
+ # The show_configuration method can be used to dump the logging hierarchy.
38
+ #
39
+
40
+ require 'logging'
41
+
42
+ Logging.logger.root.level = :debug
43
+
44
+ foo = Logging.logger['Foo']
45
+ bar = Logging.logger['Foo::Bar']
46
+ baz = Logging.logger['Foo::Baz']
47
+
48
+ # configure the Foo logger
49
+ foo.level = 'warn'
50
+ foo.appenders = Logging.appenders.stdout
51
+
52
+ # since Foo is the parent of Foo::Bar and Foo::Baz, these loggers all have
53
+ # their level set to warn
54
+
55
+ foo.warn 'this is a warning, not a ticket'
56
+ bar.info 'this message will not be logged'
57
+ baz.info 'nor will this message'
58
+ bar.error 'but this error message will be logged'
59
+
60
+ # let's demonstrate additivity of loggers
61
+
62
+ Logging.logger.root.appenders = Logging.appenders.stdout
63
+
64
+ baz.warn 'this message will be logged twice - once by Foo and once by root'
65
+
66
+ foo.additive = false
67
+ bar.warn "foo is no longer passing log events up to it's parent"
68
+
69
+ # let's look at the logger hierarchy
70
+ puts '='*76
71
+ Logging.show_configuration
72
+
73
+ # :startdoc: