tagged_logger 0.1.2 → 0.2.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.
- data/Rakefile +64 -8
- data/VERSION +1 -1
- data/active.log +2 -0
- data/database.log +2 -0
- data/examples/one_log_per_classes.rb +21 -0
- data/examples/one_tag_per_classes.rb +21 -0
- data/examples/per_class_customization.rb +23 -0
- data/examples/rule_with_regex.rb +19 -0
- data/examples/simplest_customization.rb +10 -0
- data/examples/simplest_usage.rb +18 -0
- data/lib/tagged_logger.rb +86 -66
- data/network.log +2 -0
- data/tagged_logger.gemspec +77 -11
- data/test/test.rb +50 -27
- metadata +75 -11
data/Rakefile
CHANGED
@@ -12,16 +12,72 @@ begin
|
|
12
12
|
require 'jeweler'
|
13
13
|
Jeweler::Tasks.new do |s|
|
14
14
|
s.name = "tagged_logger"
|
15
|
-
s.summary = "
|
15
|
+
s.summary = "Detaches _what_ is logged from _how_ it is logged."
|
16
16
|
s.email = "fkocherga@gmail.com"
|
17
17
|
s.homepage = "http://github.com/fkocherga/tagged_logger"
|
18
|
-
s.description = <<END
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
logger
|
23
|
-
|
24
|
-
|
18
|
+
s.description = <<'END'
|
19
|
+
This gem supposed to help you to forget about how to expose logging
|
20
|
+
facitilities to the code you write. Any time you want to log something,
|
21
|
+
simply do one of:
|
22
|
+
logger.debug("verbose debug information") #or
|
23
|
+
logger.warn("warning") #or
|
24
|
+
logger.info("information you frequently want to see") #or
|
25
|
+
logger.error("errors") #or
|
26
|
+
logger.fatal("fatal errors")
|
27
|
+
|
28
|
+
and do not worry about where the '#logger' is and what it does at the moment,
|
29
|
+
you will have a chance to configure it in place where you confugure other things.
|
30
|
+
So you may focus on _what_ to put in the logging rather on how to set it up.
|
31
|
+
Later you may turn logging on for specific class or bunch of classes or in case
|
32
|
+
you have special logging demands for specific classes you also may specify it
|
33
|
+
in very simple way.
|
34
|
+
|
35
|
+
The simplest way to turn logging on for every class whose methods calls '#logger':
|
36
|
+
|
37
|
+
TaggedLogger.rules do
|
38
|
+
out_everything_to Logger.new(STDOUT)
|
39
|
+
end
|
40
|
+
|
41
|
+
or you may cook it in your special way:
|
42
|
+
|
43
|
+
TaggedLogger.rules do
|
44
|
+
out /.*/ do |level, tag, msg|
|
45
|
+
puts "#{level}-#{tag}: #{msg}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Where 'tag' is the simple class name whose method calls '#logger'. Note,
|
50
|
+
you do not have to implement '#logger' method anywhere. It gets
|
51
|
+
automatically generated by specifying any of 'out' rules.
|
52
|
+
You may be even more picky about what and where to log. Imagine
|
53
|
+
you have 'Network' and 'Database' classes and you want to have
|
54
|
+
separate log files for them, it is easy:
|
55
|
+
|
56
|
+
TaggedLogger.rules do
|
57
|
+
out Network => Logger.new("network.log")
|
58
|
+
out Database => Logger.new("database.log")
|
59
|
+
end
|
60
|
+
|
61
|
+
In case you want to define common log for several classes:
|
62
|
+
|
63
|
+
TaggedLogger.rules do
|
64
|
+
out [Ftp, Http, Sockets] => Logger.new("network.log")
|
65
|
+
end
|
66
|
+
|
67
|
+
Or if you want to have all these classes showing up under common
|
68
|
+
tag 'Network' in standard output:
|
69
|
+
|
70
|
+
TaggedLogger.rules do
|
71
|
+
out_everything_to Logger.new(STDOUT)
|
72
|
+
rename [Ftp, Http, Sockets] => :Network
|
73
|
+
end
|
74
|
+
|
75
|
+
You may also use regular expressions in your rules:
|
76
|
+
|
77
|
+
TaggedLogger.rules do
|
78
|
+
out /Active::/ => Logger.new("active.log")
|
79
|
+
end
|
80
|
+
|
25
81
|
END
|
26
82
|
s.authors = ["Fedor Kocherga"]
|
27
83
|
s.test_files = ['test/test.rb']
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/active.log
ADDED
data/database.log
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'tagged_logger'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
class LogFoo
|
6
|
+
def foo
|
7
|
+
logger.info("foo")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Ftp = Class.new LogFoo
|
12
|
+
Http = Class.new LogFoo
|
13
|
+
Sockets = Class.new LogFoo
|
14
|
+
|
15
|
+
`rm -f network.log`
|
16
|
+
TaggedLogger.rules do
|
17
|
+
out [Ftp, Http, Sockets] => Logger.new("network.log")
|
18
|
+
end
|
19
|
+
|
20
|
+
[Ftp, Http, Sockets].each { |c| c.new.foo }
|
21
|
+
IO.foreach('network.log') { |line| puts line }
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'tagged_logger'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module LogFoo
|
6
|
+
def foo
|
7
|
+
logger.info("#{self.class}#foo")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Ftp = Class.new { include LogFoo }
|
12
|
+
Http = Class.new { include LogFoo }
|
13
|
+
Sockets = Class.new { include LogFoo }
|
14
|
+
|
15
|
+
TaggedLogger.rules do
|
16
|
+
out_everything_to Logger.new(STDOUT)
|
17
|
+
rename [Ftp, Http, Sockets] => :Network
|
18
|
+
end
|
19
|
+
|
20
|
+
[Ftp, Http, Sockets].each { |c| c.new.foo }
|
21
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'tagged_logger'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
class LogFoo
|
6
|
+
def foo
|
7
|
+
logger.info("foo")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Database = Class.new LogFoo
|
12
|
+
Network = Class.new LogFoo
|
13
|
+
|
14
|
+
`rm -f network.log`
|
15
|
+
`rm -f database.log`
|
16
|
+
|
17
|
+
TaggedLogger.rules do
|
18
|
+
out Network => Logger.new("network.log")
|
19
|
+
out Database => Logger.new("database.log")
|
20
|
+
end
|
21
|
+
|
22
|
+
Database.new.foo
|
23
|
+
Network.new.foo
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'tagged_logger'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Active
|
6
|
+
class Base
|
7
|
+
def foo
|
8
|
+
logger.info("foo")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
`rm -f active.log`
|
14
|
+
|
15
|
+
TaggedLogger.rules do
|
16
|
+
out /Active::/ => Logger.new("active.log")
|
17
|
+
end
|
18
|
+
|
19
|
+
Active::Base.new.foo
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'tagged_logger'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
TaggedLogger.rules do
|
6
|
+
out_everything_to Logger.new(STDOUT)
|
7
|
+
end
|
8
|
+
|
9
|
+
class A
|
10
|
+
def foo
|
11
|
+
logger.warn "foo"
|
12
|
+
end
|
13
|
+
logger.debug "A parsed"
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
logger.info("Hello word!")
|
18
|
+
A.new.foo
|
data/lib/tagged_logger.rb
CHANGED
@@ -1,60 +1,107 @@
|
|
1
1
|
require 'delegate'
|
2
|
+
require 'facets/dictionary'
|
2
3
|
|
3
4
|
class TaggedLogger
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@tags_map = {}
|
8
|
-
end
|
9
|
-
|
10
|
-
@@tagged_logger = self.new
|
11
|
-
|
12
|
-
def log(level, tag, msg)
|
13
|
-
remapped_tag = remap(tag)
|
14
|
-
find_blocks(remapped_tag).each { |b| b.call(level, remapped_tag, msg) }
|
15
|
-
end
|
5
|
+
@logger_generator_exists = false
|
6
|
+
@rename_rules = Dictionary.new
|
7
|
+
@tag_blocks = Dictionary.new
|
16
8
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
9
|
+
class << self
|
10
|
+
def reset
|
11
|
+
@rename_rules = Dictionary.new
|
12
|
+
@tag_blocks = Dictionary.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def rules(&block)
|
16
|
+
instance_eval(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def log(level, tag, msg)
|
20
|
+
tag_aliases(tag) do |tag_alias|
|
21
|
+
tag_blocks(tag_alias) do |tag_block|
|
22
|
+
tag_block.call(level, tag_alias, msg)
|
23
|
+
end
|
25
24
|
end
|
26
25
|
end
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
class << self
|
31
26
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
@@tagged_logger.instance_eval do
|
36
|
-
tags.each {|t| @tags_map[t.to_s] = with_tag}
|
27
|
+
def out_everything_to(logger = nil, &block)
|
28
|
+
if logger && block
|
29
|
+
raise ArgumentError, "Either block or logger has to be specified, but not both."
|
37
30
|
end
|
31
|
+
out /.*/ => logger if logger
|
32
|
+
oout &block if block
|
38
33
|
end
|
39
34
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
35
|
+
def out(spec, &block)
|
36
|
+
add_logger_generator_in_Object
|
37
|
+
if spec.is_a? Hash
|
38
|
+
spec.each do |what, where|
|
39
|
+
@tag_blocks[tag_matcher(what)] = lambda { |level, tag, msg | where.send(level, "#{tag}: #{msg}") }
|
40
|
+
end
|
41
|
+
raise ArgumentError "No block should be specified in this 'out' rule" if block
|
42
|
+
else
|
43
|
+
raise ArgumentError "Block has to be specified in this 'out' rule" unless block
|
44
|
+
@tag_blocks[tag_matcher(spec)] = block
|
44
45
|
end
|
45
46
|
end
|
46
|
-
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
|
48
|
+
def rename(renames)
|
49
|
+
renames.each { |from, to| @rename_rules[tag_matcher(from)] = to }
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
class TagMatcher
|
54
|
+
attr_reader :match_spec
|
55
|
+
|
56
|
+
def initialize(match_spec)
|
57
|
+
@match_spec = match_spec
|
58
|
+
end
|
59
|
+
|
60
|
+
def match?(tag)
|
61
|
+
self.class.match?(@match_spec, tag)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.match?(spec, tag)
|
65
|
+
t = tag.to_s
|
66
|
+
case spec
|
67
|
+
when Regexp
|
68
|
+
t =~ spec
|
69
|
+
when Class
|
70
|
+
t == spec.name
|
71
|
+
when Array
|
72
|
+
spec.any? {|s| match?(s, tag)}
|
73
|
+
else
|
74
|
+
spec.to_s == t
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end #TagMatcher
|
78
|
+
|
79
|
+
def tag_matcher(tag)
|
80
|
+
TagMatcher.new(tag)
|
81
|
+
end
|
82
|
+
|
83
|
+
def tag_aliases(tag, &block)
|
84
|
+
current_name = tag
|
85
|
+
@rename_rules.each { |from, to| current_name = to if from.match?(tag) }
|
86
|
+
block.call(current_name)
|
87
|
+
end
|
88
|
+
|
89
|
+
def tag_blocks(tag, &block)
|
90
|
+
@tag_blocks.each do |matcher, block|
|
91
|
+
yield block if matcher.match? tag
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def add_logger_generator_in_Object
|
96
|
+
return if @logger_generator_exists
|
97
|
+
@logger_generator_exists = true
|
51
98
|
Object.send(:define_method, "logger") do
|
52
99
|
self.class.class_eval do
|
53
100
|
attr_reader :class_logger
|
54
101
|
@class_logger = nil
|
55
102
|
def logger
|
56
103
|
return class_logger if class_logger
|
57
|
-
@class_logger = SimpleDelegator.new(
|
104
|
+
@class_logger = SimpleDelegator.new(TaggedLogger)
|
58
105
|
class_logging_tag = self.class == Class ? self.to_s : self.class.to_s
|
59
106
|
[:debug, :warn, :info, :error, :fatal].each do |method|
|
60
107
|
(class << @class_logger;self;end).instance_eval do
|
@@ -68,34 +115,7 @@ class TaggedLogger
|
|
68
115
|
end
|
69
116
|
logger
|
70
117
|
end
|
71
|
-
if block_given?
|
72
|
-
@@tagged_logger.for_tag /.*/ do |level, tag, what|
|
73
|
-
yield(level, tag, what)
|
74
|
-
end
|
75
|
-
end
|
76
118
|
end
|
77
119
|
|
78
|
-
def for_tag(*args, &block)
|
79
|
-
@@tagged_logger.for_tag(*args, &block)
|
80
|
-
end
|
81
120
|
end # class methods
|
82
|
-
|
83
|
-
private
|
84
|
-
def rules
|
85
|
-
@rules ||= {}
|
86
|
-
end
|
87
|
-
|
88
|
-
def find_blocks(tag)
|
89
|
-
compare_with = tag.to_s
|
90
|
-
result = []
|
91
|
-
rules.each do |rule, block|
|
92
|
-
result << block if compare_with =~ rule
|
93
|
-
end
|
94
|
-
result
|
95
|
-
end
|
96
|
-
|
97
|
-
def remap(tag)
|
98
|
-
return tag unless @tags_map.key? tag
|
99
|
-
@tags_map[tag]
|
100
|
-
end
|
101
121
|
end
|
data/network.log
ADDED
data/tagged_logger.gemspec
CHANGED
@@ -1,21 +1,77 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{tagged_logger}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Fedor Kocherga"]
|
12
|
-
s.date = %q{2009-
|
13
|
-
s.description = %q{
|
14
|
-
|
15
|
-
|
16
|
-
logger
|
17
|
-
|
18
|
-
|
12
|
+
s.date = %q{2009-12-20}
|
13
|
+
s.description = %q{This gem supposed to help you to forget about how to expose logging
|
14
|
+
facitilities to the code you write. Any time you want to log something,
|
15
|
+
simply do one of:
|
16
|
+
logger.debug("verbose debug information") #or
|
17
|
+
logger.warn("warning") #or
|
18
|
+
logger.info("information you frequently want to see") #or
|
19
|
+
logger.error("errors") #or
|
20
|
+
logger.fatal("fatal errors")
|
21
|
+
|
22
|
+
and do not worry about where the '#logger' is and what it does at the moment,
|
23
|
+
you will have a chance to configure it in place where you confugure other things.
|
24
|
+
So you may focus on _what_ to put in the logging rather on how to set it up.
|
25
|
+
Later you may turn logging on for specific class or bunch of classes or in case
|
26
|
+
you have special logging demands for specific classes you also may specify it
|
27
|
+
in very simple way.
|
28
|
+
|
29
|
+
The simplest way to turn logging on for every class whose methods calls '#logger':
|
30
|
+
|
31
|
+
TaggedLogger.rules do
|
32
|
+
out_everything_to Logger.new(STDOUT)
|
33
|
+
end
|
34
|
+
|
35
|
+
or you may cook it in your special way:
|
36
|
+
|
37
|
+
TaggedLogger.rules do
|
38
|
+
out /.*/ do |level, tag, msg|
|
39
|
+
puts "#{level}-#{tag}: #{msg}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Where 'tag' is the simple class name whose method calls '#logger'. Note,
|
44
|
+
you do not have to implement '#logger' method anywhere. It gets
|
45
|
+
automatically generated by specifying any of 'out' rules.
|
46
|
+
You may be even more picky about what and where to log. Imagine
|
47
|
+
you have 'Network' and 'Database' classes and you want to have
|
48
|
+
separate log files for them, it is easy:
|
49
|
+
|
50
|
+
TaggedLogger.rules do
|
51
|
+
out Network => Logger.new("network.log")
|
52
|
+
out Database => Logger.new("database.log")
|
53
|
+
end
|
54
|
+
|
55
|
+
In case you want to define common log for several classes:
|
56
|
+
|
57
|
+
TaggedLogger.rules do
|
58
|
+
out [Ftp, Http, Sockets] => Logger.new("network.log")
|
59
|
+
end
|
60
|
+
|
61
|
+
Or if you want to have all these classes showing up under common
|
62
|
+
tag 'Network' in standard output:
|
63
|
+
|
64
|
+
TaggedLogger.rules do
|
65
|
+
out_everything_to Logger.new(STDOUT)
|
66
|
+
rename [Ftp, Http, Sockets] => :Network
|
67
|
+
end
|
68
|
+
|
69
|
+
You may also use regular expressions in your rules:
|
70
|
+
|
71
|
+
TaggedLogger.rules do
|
72
|
+
out /Active::/ => Logger.new("active.log")
|
73
|
+
end
|
74
|
+
|
19
75
|
}
|
20
76
|
s.email = %q{fkocherga@gmail.com}
|
21
77
|
s.extra_rdoc_files = [
|
@@ -27,7 +83,16 @@ Logger, log4r, writing to STDOUT or something else.
|
|
27
83
|
"README.rdoc",
|
28
84
|
"Rakefile",
|
29
85
|
"VERSION",
|
86
|
+
"active.log",
|
87
|
+
"database.log",
|
88
|
+
"examples/one_log_per_classes.rb",
|
89
|
+
"examples/one_tag_per_classes.rb",
|
90
|
+
"examples/per_class_customization.rb",
|
91
|
+
"examples/rule_with_regex.rb",
|
92
|
+
"examples/simplest_customization.rb",
|
93
|
+
"examples/simplest_usage.rb",
|
30
94
|
"lib/tagged_logger.rb",
|
95
|
+
"network.log",
|
31
96
|
"tagged_logger.gemspec",
|
32
97
|
"tagged_logger.rb",
|
33
98
|
"test/test.rb"
|
@@ -36,7 +101,7 @@ Logger, log4r, writing to STDOUT or something else.
|
|
36
101
|
s.rdoc_options = ["--charset=UTF-8"]
|
37
102
|
s.require_paths = ["lib"]
|
38
103
|
s.rubygems_version = %q{1.3.5}
|
39
|
-
s.summary = %q{
|
104
|
+
s.summary = %q{Detaches _what_ is logged from _how_ it is logged.}
|
40
105
|
s.test_files = [
|
41
106
|
"test/test.rb"
|
42
107
|
]
|
@@ -51,3 +116,4 @@ Logger, log4r, writing to STDOUT or something else.
|
|
51
116
|
else
|
52
117
|
end
|
53
118
|
end
|
119
|
+
|
data/test/test.rb
CHANGED
@@ -16,29 +16,29 @@ end
|
|
16
16
|
|
17
17
|
class TaggedLoggerTest < Test::Unit::TestCase
|
18
18
|
|
19
|
-
context "#logger() generated for every class, logging goes to String @
|
19
|
+
context "#logger() generated for every class, logging goes to String @out1;" do
|
20
20
|
setup do
|
21
|
-
@
|
22
|
-
|
21
|
+
@out1 = TestLogDevice.new
|
22
|
+
standard_logger = Logger.new(@out1)
|
23
23
|
@formatter = lambda {|severity, datetime, progname, msg| "#{msg}"}
|
24
|
-
|
25
|
-
TaggedLogger.
|
26
|
-
|
27
|
-
|
24
|
+
standard_logger.formatter = @formatter
|
25
|
+
TaggedLogger.rules do
|
26
|
+
reset
|
27
|
+
out_everything_to standard_logger
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
should "include #logger in every class" do
|
32
32
|
assert Class.new.methods.include? "logger"
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
should "do logging with different levels" do
|
36
36
|
NewClass = Class.new
|
37
37
|
obj = NewClass.new
|
38
38
|
%w[debug info warn error fatal].each do |method|
|
39
39
|
assert obj.logger.methods.include? method
|
40
40
|
obj.logger.send(method.intern, method)
|
41
|
-
assert_equal "#{obj.class}: #{method}", @
|
41
|
+
assert_equal "#{obj.class}: #{method}", @out1.to_s
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -56,11 +56,16 @@ class TaggedLoggerTest < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
|
58
58
|
should "be possible to replace tags for A, B classes with single tag TEST making rules for A and B obsolete" do
|
59
|
-
TaggedLogger.
|
59
|
+
TaggedLogger.rules do
|
60
|
+
rename [A,B] => :TEST
|
61
|
+
end
|
62
|
+
|
60
63
|
@a.foo
|
61
|
-
assert_equal "TEST: foo", @
|
64
|
+
assert_equal "TEST: foo", @out1.to_s
|
65
|
+
@out1.clear
|
66
|
+
|
62
67
|
@b.foo
|
63
|
-
assert_equal "TEST: foo", @
|
68
|
+
assert_equal "TEST: foo", @out1.to_s
|
64
69
|
end
|
65
70
|
|
66
71
|
context "specialized logging" do
|
@@ -70,32 +75,50 @@ class TaggedLoggerTest < Test::Unit::TestCase
|
|
70
75
|
@logger2.formatter = @formatter
|
71
76
|
end
|
72
77
|
|
73
|
-
should "be possible to speialize logging for tag A" do
|
74
|
-
|
75
|
-
|
78
|
+
should "be possible to speialize logging for tag A by specifying different logger" do
|
79
|
+
logger2 = @logger2
|
80
|
+
TaggedLogger.rules do
|
81
|
+
out A => logger2
|
82
|
+
end
|
83
|
+
@a.foo
|
84
|
+
assert_equal "#{self.class}::A: foo", @out1.to_s
|
85
|
+
assert_equal "#{self.class}::A: foo", @out2.to_s
|
86
|
+
@out2.clear
|
87
|
+
@b.foo
|
88
|
+
assert_equal "#{self.class}::B: foo", @out1.to_s
|
89
|
+
assert_equal "", @out2.to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
should "be possible to speialize logging for tag A by providing block" do
|
93
|
+
logger2 = @logger2
|
94
|
+
TaggedLogger.rules do
|
95
|
+
out A do |level, tag, msg|
|
96
|
+
logger2.send(level, msg)
|
97
|
+
end
|
76
98
|
end
|
77
99
|
@a.foo
|
78
|
-
assert_equal "#{self.class}::A: foo", @
|
79
|
-
assert_equal "
|
100
|
+
assert_equal "#{self.class}::A: foo", @out1.to_s
|
101
|
+
assert_equal "foo", @out2.to_s
|
80
102
|
@out2.clear
|
81
103
|
@b.foo
|
82
|
-
assert_equal "#{self.class}::B: foo", @
|
104
|
+
assert_equal "#{self.class}::B: foo", @out1.to_s
|
83
105
|
assert_equal "", @out2.to_s
|
84
106
|
end
|
85
107
|
|
86
108
|
should "be possible to replace tags for A, B classes with single tag TEST and specialize logging for it" do
|
87
|
-
|
88
|
-
TaggedLogger.
|
89
|
-
|
109
|
+
logger2 = @logger2
|
110
|
+
TaggedLogger.rules do
|
111
|
+
rename [A, B] => :TEST
|
112
|
+
out :TEST => logger2
|
90
113
|
end
|
91
114
|
@a.foo
|
92
|
-
assert_equal "TEST: foo", @
|
93
|
-
assert_equal "
|
94
|
-
@
|
115
|
+
assert_equal "TEST: foo", @out1.to_s
|
116
|
+
assert_equal "TEST: foo", @out2.to_s
|
117
|
+
@out1.clear
|
95
118
|
@out2.clear
|
96
119
|
@b.foo
|
97
|
-
assert_equal "TEST: foo", @
|
98
|
-
assert_equal "
|
120
|
+
assert_equal "TEST: foo", @out1.to_s
|
121
|
+
assert_equal "TEST: foo", @out2.to_s
|
99
122
|
end
|
100
123
|
|
101
124
|
should "use default tag equal to class name for class methods" do
|
@@ -103,7 +126,7 @@ class TaggedLoggerTest < Test::Unit::TestCase
|
|
103
126
|
logger.info "bar"
|
104
127
|
end
|
105
128
|
A.bar
|
106
|
-
assert_equal "#{self.class}::A: bar", @
|
129
|
+
assert_equal "#{self.class}::A: bar", @out1.to_s
|
107
130
|
end
|
108
131
|
end
|
109
132
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tagged_logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fedor Kocherga
|
@@ -9,18 +9,73 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-20 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description:
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
description: |+
|
17
|
+
This gem supposed to help you to forget about how to expose logging
|
18
|
+
facitilities to the code you write. Any time you want to log something,
|
19
|
+
simply do one of:
|
20
|
+
logger.debug("verbose debug information") #or
|
21
|
+
logger.warn("warning") #or
|
22
|
+
logger.info("information you frequently want to see") #or
|
23
|
+
logger.error("errors") #or
|
24
|
+
logger.fatal("fatal errors")
|
25
|
+
|
26
|
+
and do not worry about where the '#logger' is and what it does at the moment,
|
27
|
+
you will have a chance to configure it in place where you confugure other things.
|
28
|
+
So you may focus on _what_ to put in the logging rather on how to set it up.
|
29
|
+
Later you may turn logging on for specific class or bunch of classes or in case
|
30
|
+
you have special logging demands for specific classes you also may specify it
|
31
|
+
in very simple way.
|
32
|
+
|
33
|
+
The simplest way to turn logging on for every class whose methods calls '#logger':
|
34
|
+
|
35
|
+
TaggedLogger.rules do
|
36
|
+
out_everything_to Logger.new(STDOUT)
|
37
|
+
end
|
38
|
+
|
39
|
+
or you may cook it in your special way:
|
40
|
+
|
41
|
+
TaggedLogger.rules do
|
42
|
+
out /.*/ do |level, tag, msg|
|
43
|
+
puts "#{level}-#{tag}: #{msg}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Where 'tag' is the simple class name whose method calls '#logger'. Note,
|
48
|
+
you do not have to implement '#logger' method anywhere. It gets
|
49
|
+
automatically generated by specifying any of 'out' rules.
|
50
|
+
You may be even more picky about what and where to log. Imagine
|
51
|
+
you have 'Network' and 'Database' classes and you want to have
|
52
|
+
separate log files for them, it is easy:
|
53
|
+
|
54
|
+
TaggedLogger.rules do
|
55
|
+
out Network => Logger.new("network.log")
|
56
|
+
out Database => Logger.new("database.log")
|
57
|
+
end
|
58
|
+
|
59
|
+
In case you want to define common log for several classes:
|
60
|
+
|
61
|
+
TaggedLogger.rules do
|
62
|
+
out [Ftp, Http, Sockets] => Logger.new("network.log")
|
63
|
+
end
|
64
|
+
|
65
|
+
Or if you want to have all these classes showing up under common
|
66
|
+
tag 'Network' in standard output:
|
67
|
+
|
68
|
+
TaggedLogger.rules do
|
69
|
+
out_everything_to Logger.new(STDOUT)
|
70
|
+
rename [Ftp, Http, Sockets] => :Network
|
71
|
+
end
|
72
|
+
|
73
|
+
You may also use regular expressions in your rules:
|
74
|
+
|
75
|
+
TaggedLogger.rules do
|
76
|
+
out /Active::/ => Logger.new("active.log")
|
77
|
+
end
|
78
|
+
|
24
79
|
email: fkocherga@gmail.com
|
25
80
|
executables: []
|
26
81
|
|
@@ -34,7 +89,16 @@ files:
|
|
34
89
|
- README.rdoc
|
35
90
|
- Rakefile
|
36
91
|
- VERSION
|
92
|
+
- active.log
|
93
|
+
- database.log
|
94
|
+
- examples/one_log_per_classes.rb
|
95
|
+
- examples/one_tag_per_classes.rb
|
96
|
+
- examples/per_class_customization.rb
|
97
|
+
- examples/rule_with_regex.rb
|
98
|
+
- examples/simplest_customization.rb
|
99
|
+
- examples/simplest_usage.rb
|
37
100
|
- lib/tagged_logger.rb
|
101
|
+
- network.log
|
38
102
|
- tagged_logger.gemspec
|
39
103
|
- tagged_logger.rb
|
40
104
|
- test/test.rb
|
@@ -65,6 +129,6 @@ rubyforge_project:
|
|
65
129
|
rubygems_version: 1.3.5
|
66
130
|
signing_key:
|
67
131
|
specification_version: 3
|
68
|
-
summary:
|
132
|
+
summary: Detaches _what_ is logged from _how_ it is logged.
|
69
133
|
test_files:
|
70
134
|
- test/test.rb
|