sgeorgi-logging 1.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|