sgeorgi-logging 1.4.2
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 +262 -0
- data/README.rdoc +115 -0
- data/Rakefile +32 -0
- data/data/bad_logging_1.rb +13 -0
- data/data/bad_logging_2.rb +21 -0
- data/data/logging.rb +42 -0
- data/data/logging.yaml +63 -0
- data/data/simple_logging.rb +13 -0
- data/examples/appenders.rb +47 -0
- data/examples/classes.rb +41 -0
- data/examples/consolidation.rb +83 -0
- data/examples/fork.rb +37 -0
- data/examples/formatting.rb +51 -0
- data/examples/hierarchies.rb +73 -0
- data/examples/layouts.rb +48 -0
- data/examples/loggers.rb +29 -0
- data/examples/names.rb +43 -0
- data/examples/simple.rb +17 -0
- data/lib/logging.rb +528 -0
- data/lib/logging/appender.rb +260 -0
- data/lib/logging/appenders.rb +137 -0
- data/lib/logging/appenders/buffering.rb +178 -0
- data/lib/logging/appenders/console.rb +60 -0
- data/lib/logging/appenders/email.rb +75 -0
- data/lib/logging/appenders/file.rb +75 -0
- data/lib/logging/appenders/growl.rb +197 -0
- data/lib/logging/appenders/io.rb +69 -0
- data/lib/logging/appenders/rolling_file.rb +327 -0
- data/lib/logging/appenders/string_io.rb +68 -0
- data/lib/logging/appenders/syslog.rb +210 -0
- data/lib/logging/config/configurator.rb +188 -0
- data/lib/logging/config/yaml_configurator.rb +191 -0
- data/lib/logging/layout.rb +117 -0
- data/lib/logging/layouts.rb +47 -0
- data/lib/logging/layouts/basic.rb +32 -0
- data/lib/logging/layouts/parseable.rb +211 -0
- data/lib/logging/layouts/pattern.rb +311 -0
- data/lib/logging/log_event.rb +45 -0
- data/lib/logging/logger.rb +504 -0
- data/lib/logging/repository.rb +232 -0
- data/lib/logging/root_logger.rb +61 -0
- data/lib/logging/stats.rb +278 -0
- data/lib/logging/utils.rb +201 -0
- data/lib/spec/logging_helper.rb +34 -0
- data/test/appenders/test_buffered_io.rb +176 -0
- data/test/appenders/test_console.rb +66 -0
- data/test/appenders/test_email.rb +170 -0
- data/test/appenders/test_file.rb +95 -0
- data/test/appenders/test_growl.rb +127 -0
- data/test/appenders/test_io.rb +129 -0
- data/test/appenders/test_rolling_file.rb +209 -0
- data/test/appenders/test_syslog.rb +194 -0
- data/test/benchmark.rb +86 -0
- data/test/config/test_configurator.rb +70 -0
- data/test/config/test_yaml_configurator.rb +40 -0
- data/test/layouts/test_basic.rb +42 -0
- data/test/layouts/test_json.rb +112 -0
- data/test/layouts/test_pattern.rb +198 -0
- data/test/layouts/test_yaml.rb +121 -0
- data/test/setup.rb +43 -0
- data/test/test_appender.rb +152 -0
- data/test/test_consolidate.rb +46 -0
- data/test/test_layout.rb +110 -0
- data/test/test_log_event.rb +80 -0
- data/test/test_logger.rb +699 -0
- data/test/test_logging.rb +267 -0
- data/test/test_repository.rb +158 -0
- data/test/test_root_logger.rb +81 -0
- data/test/test_stats.rb +274 -0
- data/test/test_utils.rb +116 -0
- data/version.txt +1 -0
- 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,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:
|
data/examples/classes.rb
ADDED
@@ -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:
|