tagged_logger 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|