tagged_logger 0.1.1

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