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 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