tagged_logger 0.1.1
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/MIT-LICENSE +22 -0
- data/README.rdoc +63 -0
- data/Rakefile +33 -0
- data/VERSION +1 -0
- data/lib/tagged_logger.rb +98 -0
- data/tagged_logger.gemspec +49 -0
- data/tagged_logger.rb +1 -0
- data/test/test.rb +114 -0
- metadata +69 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2009, Fedor Kocherga <fkocherga@gmail.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
= TaggedLogger
|
2
|
+
Split your logging by using tags-based rules (tags are generated automatically)
|
3
|
+
|
4
|
+
== What is it for?
|
5
|
+
When you need to use logging for different code in different ways,
|
6
|
+
here is help for you: create tags-based rules for logging. Tags are
|
7
|
+
class names by default, so you do not have to specify them in
|
8
|
+
+logger.info+, +logger.warn+ and similar calls. Rules are just code blocks,
|
9
|
+
so any logging facility could be used underneath: standard library
|
10
|
+
+Logger+, +log4r+, writing to +STDOUT+ or something else.
|
11
|
+
|
12
|
+
|
13
|
+
== Installation
|
14
|
+
|
15
|
+
$ sudo gem install tagged_logger --source=http://gemcutter.org
|
16
|
+
|
17
|
+
== Usage
|
18
|
+
|
19
|
+
require 'rubygems'
|
20
|
+
require 'tagged_logger'
|
21
|
+
require 'logger'
|
22
|
+
|
23
|
+
#for class A the tag 'A' is used implicitly, no need to specify it
|
24
|
+
class A
|
25
|
+
def foo; logger.info("#{self.class}...".downcase); end
|
26
|
+
end
|
27
|
+
|
28
|
+
file_logger = Logger.new('my_log.log')
|
29
|
+
file_logger.formatter = lambda {|severity, datetime, progname, msg| "#{msg}"}
|
30
|
+
|
31
|
+
#If we want to have #logger in every class doing whatever we need
|
32
|
+
TaggedLogger.use_in_every_class do |level, tag, what|
|
33
|
+
file_logger.send(level, "#{tag}: #{what}\n")
|
34
|
+
end
|
35
|
+
A.new.foo #'A: a...' printed in 'my_log.log'
|
36
|
+
|
37
|
+
#Adding special logging for class A (or everything with tag 'A')
|
38
|
+
TaggedLogger.for_tag A do |level, tag, what|
|
39
|
+
STDOUT << "#{level}---#{tag}---#{what}\n"
|
40
|
+
end
|
41
|
+
A.new.foo #'A: a...' printed in 'my_log.log', 'info---A---a...' - in STDOUT
|
42
|
+
B = Class.new(A)
|
43
|
+
B.new.foo #'B: b...' printed in 'my_log.log', but not in STDOUT
|
44
|
+
|
45
|
+
#Rule for A and B says: logging within these classes happens with tag 'COMBINED':
|
46
|
+
TaggedLogger.replace_tags [A, B], :with => :COMBINED
|
47
|
+
A.new.foo #'COMBINED: a...' printed in 'my_log.log', but nothing in STDOUT
|
48
|
+
B.new.foo #'COMBINED: b...' printed in 'my_log.log'
|
49
|
+
|
50
|
+
#Adding special rule for 'COMBINED' tag
|
51
|
+
TaggedLogger.for_tag :COMBINED do |level, tag, what|
|
52
|
+
STDERR << "Oh my gosh!!! #{what}\n"
|
53
|
+
end
|
54
|
+
A.new.foo #'Oh my gosh!!! a...' printed in 'my_log.log' and in STDERR
|
55
|
+
B.new.foo #'Oh my gosh!!! b...' printed in 'my_log.log' and in STDERR
|
56
|
+
|
57
|
+
#Hope you've got the idea, do not hesitate to ask/fix me something...
|
58
|
+
|
59
|
+
== License
|
60
|
+
TaggedLogger is released under the MIT license.
|
61
|
+
|
62
|
+
= Shortcumings
|
63
|
+
Was not tested with log4r
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << "test"
|
7
|
+
t.test_files = FileList['test/test.rb']
|
8
|
+
t.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'jeweler'
|
13
|
+
gemspec = Gem::Specification.new do |s|
|
14
|
+
|
15
|
+
s.name = "tagged_logger"
|
16
|
+
s.summary = "Split your logging by using tags-based rules (tags are generated automatically)"
|
17
|
+
s.email = "fkocherga@gmail.com"
|
18
|
+
s.homepage = "http://github.com/fkocherga/tagged_logger"
|
19
|
+
s.description = <<END
|
20
|
+
When you need to use logging for different code in different ways,
|
21
|
+
here is help for you: create tags-based rules for logging. Tags are
|
22
|
+
class names by default, so you do not have to specify them in
|
23
|
+
logger's #info, #warn and similar calls. Rules are just code blocks,
|
24
|
+
so any logging facility could be used underneath: standard library
|
25
|
+
Logger, log4r, writing to STDOUT or something else.
|
26
|
+
END
|
27
|
+
s.authors = ["Fedor Kocherga"]
|
28
|
+
s.test_files = ['test/test.rb']
|
29
|
+
end
|
30
|
+
Jeweler::Tasks.new gemspec
|
31
|
+
rescue LoadError
|
32
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
33
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.2
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
class TaggedLogger
|
4
|
+
|
5
|
+
attr_reader :tags_map
|
6
|
+
def initialize()
|
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
|
16
|
+
|
17
|
+
def for_tag(*args, &block)
|
18
|
+
case args.first
|
19
|
+
when Regexp then rules[args.first] = block
|
20
|
+
when Class then rules[Regexp.new("^#{args.first.to_s}$")] = block
|
21
|
+
when Array then args.first.each {|e| for_tag(args.first, block)}
|
22
|
+
when Symbol then rules[Regexp.new("^#{args.first.to_s}$")] = block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
class << self
|
28
|
+
|
29
|
+
def replace_tags(tags, with)
|
30
|
+
with_tag = with[:with]
|
31
|
+
raise ArgumentError.new(":with => <tag> has to be specified") unless with_tag
|
32
|
+
@@tagged_logger.instance_eval do
|
33
|
+
tags.each {|t| @tags_map[t.to_s] = with_tag}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def reset
|
38
|
+
@@tagged_logger.instance_eval do
|
39
|
+
@rules = {}
|
40
|
+
@tags_map = {}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def use_in_every_class
|
45
|
+
#Object#logger when called generates <self.class>#logger (only once)
|
46
|
+
#returning logger knowing what tags to use for self.class and passing them to delegator which is
|
47
|
+
#instance (singleton) of TaggedLogger
|
48
|
+
Object.send(:define_method, "logger") do
|
49
|
+
self.class.class_eval do
|
50
|
+
attr_reader :class_logger
|
51
|
+
@class_logger = nil
|
52
|
+
def logger
|
53
|
+
return class_logger if class_logger
|
54
|
+
@class_logger = SimpleDelegator.new(@@tagged_logger)
|
55
|
+
class_logging_tag = self.class == Class ? self.to_s : self.class.to_s
|
56
|
+
[:debug, :warn, :info, :error, :fatal].each do |method|
|
57
|
+
(class << @class_logger;self;end).instance_eval do
|
58
|
+
define_method method do |msg|
|
59
|
+
__getobj__.log(method, class_logging_tag, msg)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@class_logger
|
64
|
+
end
|
65
|
+
end
|
66
|
+
logger
|
67
|
+
end
|
68
|
+
if block_given?
|
69
|
+
@@tagged_logger.for_tag /.*/ do |level, tag, what|
|
70
|
+
yield(level, tag, what)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def for_tag(*args, &block)
|
76
|
+
@@tagged_logger.for_tag(*args, &block)
|
77
|
+
end
|
78
|
+
end # class methods
|
79
|
+
|
80
|
+
private
|
81
|
+
def rules
|
82
|
+
@rules ||= {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def find_blocks(tag)
|
86
|
+
compare_with = tag.to_s
|
87
|
+
result = []
|
88
|
+
rules.each do |rule, block|
|
89
|
+
result << block if compare_with =~ rule
|
90
|
+
end
|
91
|
+
result
|
92
|
+
end
|
93
|
+
|
94
|
+
def remap(tag)
|
95
|
+
return tag unless @tags_map.key? tag
|
96
|
+
@tags_map[tag]
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{tagged_logger}
|
5
|
+
s.version = "0.1.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Fedor Kocherga"]
|
9
|
+
s.date = %q{2009-10-09}
|
10
|
+
s.description = %q{When you need to use logging for different code in different ways,
|
11
|
+
here is help for you: create tags-based rules for logging. Tags are
|
12
|
+
class names by default, so you do not have to specify them in
|
13
|
+
logger's #info, #warn and similar calls. Rules are just code blocks,
|
14
|
+
so any logging facility could be used underneath: standard library
|
15
|
+
Logger, log4r, writing to STDOUT or something else.
|
16
|
+
}
|
17
|
+
s.email = %q{fkocherga@gmail.com}
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"README.rdoc"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
"MIT-LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/tagged_logger.rb",
|
27
|
+
"tagged_logger.gemspec",
|
28
|
+
"tagged_logger.rb",
|
29
|
+
"test/test.rb"
|
30
|
+
]
|
31
|
+
s.homepage = %q{http://github.com/fkocherga/tagged_logger}
|
32
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = %q{1.3.5}
|
35
|
+
s.summary = %q{Split your logging by using tags-based rules (tags are generated automatically)}
|
36
|
+
s.test_files = [
|
37
|
+
"test/test.rb"
|
38
|
+
]
|
39
|
+
|
40
|
+
if s.respond_to? :specification_version then
|
41
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
42
|
+
s.specification_version = 3
|
43
|
+
|
44
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
45
|
+
else
|
46
|
+
end
|
47
|
+
else
|
48
|
+
end
|
49
|
+
end
|
data/tagged_logger.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/lib/tagged_logger.rb'
|
data/test/test.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
require File.dirname(__FILE__) + '/../tagged_logger'
|
7
|
+
|
8
|
+
class TestLogDevice
|
9
|
+
attr_reader :last
|
10
|
+
def write(msg); @last = msg; end
|
11
|
+
def close; end;
|
12
|
+
def to_s; @last || ""; end
|
13
|
+
def inspect; to_s; end
|
14
|
+
def clear; write(""); end
|
15
|
+
end
|
16
|
+
|
17
|
+
class TaggedLoggerTest < Test::Unit::TestCase
|
18
|
+
|
19
|
+
context "#logger() generated for every class, logging goes to String @out;" do
|
20
|
+
setup do
|
21
|
+
@out = TestLogDevice.new
|
22
|
+
@standard_logger = Logger.new(@out)
|
23
|
+
@formatter = lambda {|severity, datetime, progname, msg| "#{msg}"}
|
24
|
+
@standard_logger.formatter = @formatter
|
25
|
+
TaggedLogger.reset
|
26
|
+
TaggedLogger.use_in_every_class do |level, tag, what|
|
27
|
+
@standard_logger.send(level, "#{tag}: #{what}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
should "include #logger in every class" do
|
32
|
+
assert Class.new.methods.include? "logger"
|
33
|
+
end
|
34
|
+
|
35
|
+
should "do logging with different levels" do
|
36
|
+
NewClass = Class.new
|
37
|
+
obj = NewClass.new
|
38
|
+
%w[debug info warn error fatal].each do |method|
|
39
|
+
assert obj.logger.methods.include? method
|
40
|
+
obj.logger.send(method.intern, method)
|
41
|
+
assert_equal "#{obj.class}: #{method}", @out.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "class A and class B with logging;" do
|
46
|
+
setup do
|
47
|
+
module Foo
|
48
|
+
def foo
|
49
|
+
logger.info("foo")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
class A;include Foo; end
|
53
|
+
class B;include Foo; end
|
54
|
+
@a = A.new
|
55
|
+
@b = B.new
|
56
|
+
end
|
57
|
+
|
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.replace_tags [A, B], :with => :TEST
|
60
|
+
@a.foo
|
61
|
+
assert_equal "TEST: foo", @out.to_s
|
62
|
+
@b.foo
|
63
|
+
assert_equal "TEST: foo", @out.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
context "specialized logging" do
|
67
|
+
setup do
|
68
|
+
@out2 = TestLogDevice.new
|
69
|
+
@logger2 = Logger.new(@out2)
|
70
|
+
@logger2.formatter = @formatter
|
71
|
+
end
|
72
|
+
|
73
|
+
should "be possible to speialize logging for tag A" do
|
74
|
+
TaggedLogger.for_tag A do |level, tag, what|
|
75
|
+
@logger2.send(level, "#{level}---#{tag}---#{what}")
|
76
|
+
end
|
77
|
+
@a.foo
|
78
|
+
assert_equal "#{self.class}::A: foo", @out.to_s
|
79
|
+
assert_equal "info---#{self.class}::A---foo", @out2.to_s
|
80
|
+
@out2.clear
|
81
|
+
@b.foo
|
82
|
+
assert_equal "#{self.class}::B: foo", @out.to_s
|
83
|
+
assert_equal "", @out2.to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
should "be possible to replace tags for A, B classes with single tag TEST and specialize logging for it" do
|
87
|
+
TaggedLogger.replace_tags [A, B], :with => :TEST
|
88
|
+
TaggedLogger.for_tag :TEST do |level, tag, what|
|
89
|
+
@logger2.send(level, "#{level}---#{tag}---#{what}")
|
90
|
+
end
|
91
|
+
@a.foo
|
92
|
+
assert_equal "TEST: foo", @out.to_s
|
93
|
+
assert_equal "info---TEST---foo", @out2.to_s
|
94
|
+
@out.clear
|
95
|
+
@out2.clear
|
96
|
+
@b.foo
|
97
|
+
assert_equal "TEST: foo", @out.to_s
|
98
|
+
assert_equal "info---TEST---foo", @out2.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
should "use default tag equal to class name for class methods" do
|
102
|
+
def A.bar
|
103
|
+
logger.info "bar"
|
104
|
+
end
|
105
|
+
A.bar
|
106
|
+
assert_equal "#{self.class}::A: bar", @out.to_s
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tagged_logger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fedor Kocherga
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-09 00:00:00 +04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: |
|
17
|
+
When you need to use logging for different code in different ways,
|
18
|
+
here is help for you: create tags-based rules for logging. Tags are
|
19
|
+
class names by default, so you do not have to specify them in
|
20
|
+
logger's #info, #warn and similar calls. Rules are just code blocks,
|
21
|
+
so any logging facility could be used underneath: standard library
|
22
|
+
Logger, log4r, writing to STDOUT or something else.
|
23
|
+
|
24
|
+
email: fkocherga@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files:
|
30
|
+
- README.rdoc
|
31
|
+
files:
|
32
|
+
- MIT-LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- VERSION
|
36
|
+
- lib/tagged_logger.rb
|
37
|
+
- tagged_logger.gemspec
|
38
|
+
- tagged_logger.rb
|
39
|
+
- test/test.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/fkocherga/tagged_logger
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --charset=UTF-8
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.3.5
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: Split your logging by using tags-based rules (tags are generated automatically)
|
68
|
+
test_files:
|
69
|
+
- test/test.rb
|