tagged_logger 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ if defined?(Rails::Railtie)
2
+ module TaggedLogger
3
+ class Railtie < Rails::Railtie
4
+ ActiveSupport.on_load(:action_controller) {debugger; TaggedLogger.send(:inject_logger_method_in_call_chain, ActionController::Base)}
5
+ ActiveSupport.on_load(:active_record) {debugger; TaggedLogger.send(:inject_logger_method_in_call_chain, ActiveRecord::Base)}
6
+ ActiveSupport.on_load(:action_mailer) {debugger; TaggedLogger.send(:inject_logger_method_in_call_chain, ActionMailer::Base)}
7
+ end
8
+ end
9
+ end
10
+
11
+
@@ -0,0 +1,191 @@
1
+ require 'delegate'
2
+ require 'hashery/dictionary'
3
+
4
+ module TaggedLogger
5
+ @rename_rules = Dictionary.new
6
+ @tag_blocks = Dictionary.new
7
+ @overridees = []
8
+
9
+ class << self
10
+ def reset
11
+ @rename_rules = Dictionary.new
12
+ @tag_blocks = Dictionary.new
13
+ ObjectSpace.each_object(ClassSpecificLogger) { |obj| obj.detach }
14
+ init
15
+ end
16
+
17
+ def rules(options = {}, &block)
18
+ @options = options
19
+ @old_methods_restored = false
20
+ inject_logger_method_in_call_chain(Object)
21
+ instance_eval(&block)
22
+ end
23
+
24
+ def klass_has_method?(klass, method)
25
+ klass.instance_methods(false).include?(RUBY_VERSION >= '1.9' ? method.to_sym : method.to_s)
26
+ end
27
+
28
+ def restore_old_logger_methods
29
+ return if @old_methods_restored
30
+ @old_methods_restored = true
31
+ @overridees.each do |klass|
32
+ if klass_has_method?(klass, :tagged_logger_original_logger)
33
+ klass.class_eval {alias_method :logger, :tagged_logger_original_logger}
34
+ elsif klass_has_method?(klass, :logger)
35
+ klass.class_eval {remove_method :logger}
36
+ end
37
+ end
38
+ @overridees = []
39
+ end
40
+
41
+ def blocks_for(level, tag)
42
+ blocks = []
43
+ tag_aliases(tag) do |tag_alias|
44
+ tag_blocks(level, tag_alias) do |tag_block|
45
+ blocks << [tag_alias, tag_block]
46
+ end
47
+ end
48
+ blocks
49
+ end
50
+
51
+ def init
52
+ rules {}
53
+ end
54
+
55
+ def debug(what, where = {}, &block) output(:debug, what, where, &block) end
56
+ def info(what, where = {}, &block) output(:info, what, where, &block) end
57
+ def warn(what, where = {}, &block) output(:warn, what, where, &block) end
58
+ def error(what, where = {}, &block) output(:error, what, where, &block) end
59
+ def fatal(what, where = {}, &block) output(:fatal, what, where, &block) end
60
+
61
+ def format(&block)
62
+ @formatter = block
63
+ end
64
+
65
+ def formatter
66
+ @formatter = lambda { |level, tag, message| "#{message}\n"} unless @formatter
67
+ @formatter
68
+ end
69
+
70
+ def rename(renames)
71
+ renames.each { |from, to| @rename_rules[tag_matcher(from)] = to }
72
+ end
73
+
74
+ private
75
+ def output(level, what, where, &block)
76
+ logger = where[:to]
77
+ code = nil
78
+ if logger
79
+ #todo: hack - what about other logger classes?
80
+ logger.formatter = lambda {|severity, datetime, progname, msg| "#{msg}"} if logger.is_a? Logger
81
+ write = lambda { |level, tag, msg | logger.send(level, formatter.call(level, tag, msg)) }
82
+ code = block ? lambda { |l,t,m| write.call(l,t,m); block.call(l,t,m) } : write
83
+ elsif block
84
+ code = block
85
+ else
86
+ raise ArgumentError "Should be called with block or :to => <logger>"
87
+ end
88
+ @tag_blocks[tag_matcher(what, level)] = code
89
+ end
90
+
91
+ class TagMatcher
92
+ attr_reader :match_spec
93
+ LEVELS = { :debug => 1, :info => 2, :warn => 3, :error => 4, :fatal => 5}
94
+
95
+ def initialize(match_spec, level = nil)
96
+ @level = level || :debug
97
+ @match_spec = match_spec
98
+ end
99
+
100
+ def match?(tag, level = nil)
101
+ return false if level && !above_treshold(level)
102
+ self.class.match?(@match_spec, tag)
103
+ end
104
+
105
+ def above_treshold(level)
106
+ LEVELS[@level] <= LEVELS[level]
107
+ end
108
+
109
+ def self.match?(spec, tag)
110
+ t = tag.to_s
111
+ result = case spec
112
+ when Regexp
113
+ t =~ spec
114
+ when Class
115
+ t == spec.name
116
+ when Array
117
+ spec.any? {|s| match?(s, tag)}
118
+ else
119
+ spec.to_s == t
120
+ end
121
+ return result if result
122
+ self.match?(spec, tag.superclass) if tag.class == Class && tag.superclass != Class
123
+ end
124
+ end #TagMatcher
125
+
126
+ def tag_matcher(tag, level = nil)
127
+ TagMatcher.new(tag, level)
128
+ end
129
+
130
+ def tag_aliases(tag, &block)
131
+ current_name = tag
132
+ @rename_rules.each { |from, to| current_name = to if from.match?(tag) }
133
+ block.call(current_name)
134
+ end
135
+
136
+ def tag_blocks(level, tag, &block)
137
+ @tag_blocks.each do |matcher, block|
138
+ yield block if matcher.match?(tag, level)
139
+ end
140
+ end
141
+
142
+ def inject_logger_method_in_call_chain(definee_klass)
143
+ return if @overridees.include?(definee_klass)
144
+
145
+ if klass_has_method?(definee_klass, :logger)
146
+ return if !@options[:override]
147
+ #so we could resurrect old :logger method if we need
148
+ definee_klass.class_eval { alias_method :tagged_logger_original_logger, :logger }
149
+ end
150
+
151
+ @overridees << definee_klass
152
+
153
+ definee_klass.class_eval do
154
+ def logger
155
+ klass = self.class == Class ? self : self.class
156
+ result = klass.class_eval do
157
+ return @class_logger if @class_logger
158
+ @class_logger = ClassSpecificLogger.new(klass)
159
+ @class_logger
160
+ end
161
+ result
162
+ end
163
+ end
164
+
165
+ end
166
+
167
+ end # class methods
168
+
169
+ class ClassSpecificLogger
170
+ def eigenclass
171
+ class <<self; self; end
172
+ end
173
+
174
+ def initialize(klass)
175
+ @klass = klass
176
+ [:debug, :warn, :info, :error, :fatal].each do |level|
177
+ blocks = TaggedLogger.blocks_for(level, klass)
178
+ eigenclass.send(:define_method, level) do |msg|
179
+ blocks.each { |(tag_alias, block)| block.call(level, tag_alias, msg) }
180
+ end
181
+ end
182
+ end
183
+
184
+ def detach
185
+ @klass.class_eval do
186
+ @class_logger = nil
187
+ end
188
+ end
189
+ end
190
+
191
+ end
data/lib/tagged_logger.rb CHANGED
@@ -1,192 +1,4 @@
1
- require 'delegate'
2
- require 'hashery/dictionary'
3
-
4
- class TaggedLogger
5
- @rename_rules = Dictionary.new
6
- @tag_blocks = Dictionary.new
7
-
8
- class << self
9
- def reset
10
- @rename_rules = Dictionary.new
11
- @tag_blocks = Dictionary.new
12
- ObjectSpace.each_object(ClassSpecificLogger) { |obj| obj.detach }
13
- init
14
- end
15
-
16
- def rules(options = {}, &block)
17
- @old_methods_restored = false
18
- override = options.delete :override
19
- klasses = overridees
20
- klasses = klasses.select{ |klass| !klass.respond_to?(:logger, true)} if !override
21
- klasses.each{ |klass| inject_logger_method_in_call_chain(klass)}
22
- instance_eval(&block)
23
- end
24
-
25
- def klass_has_method?(klass, method)
26
- klass.instance_methods(false).include?(RUBY_VERSION >= '1.9' ? method.to_sym : method.to_s)
27
- end
28
-
29
- def restore_old_logger_methods
30
- return if @old_methods_restored
31
- @old_methods_restored = true
32
- overridees.each do |klass|
33
- if klass_has_method?(klass, :tagged_logger_original_logger)
34
- klass.class_eval {alias_method :logger, :tagged_logger_original_logger}
35
- elsif klass_has_method?(klass, :logger)
36
- klass.class_eval {remove_method :logger}
37
- end
38
- end
39
- end
40
-
41
- def overridees
42
- klasses = []
43
- klasses << ActionController::Base if Object.const_defined? :ActionController
44
- klasses << Object
45
- klasses
46
- end
47
-
48
-
49
- def blocks_for(level, tag)
50
- blocks = []
51
- tag_aliases(tag) do |tag_alias|
52
- tag_blocks(level, tag_alias) do |tag_block|
53
- blocks << [tag_alias, tag_block]
54
- end
55
- end
56
- blocks
57
- end
58
-
59
- def init
60
- rules {}
61
- end
62
-
63
- def debug(what, where = {}, &block) output(:debug, what, where, &block) end
64
- def info(what, where = {}, &block) output(:info, what, where, &block) end
65
- def warn(what, where = {}, &block) output(:warn, what, where, &block) end
66
- def error(what, where = {}, &block) output(:error, what, where, &block) end
67
- def fatal(what, where = {}, &block) output(:fatal, what, where, &block) end
68
-
69
- def format(&block)
70
- @formatter = block
71
- end
72
-
73
- def formatter
74
- @formatter = lambda { |level, tag, message| "#{message}\n"} unless @formatter
75
- @formatter
76
- end
77
-
78
- def rename(renames)
79
- renames.each { |from, to| @rename_rules[tag_matcher(from)] = to }
80
- end
81
-
82
- private
83
- def output(level, what, where, &block)
84
- logger = where[:to]
85
- code = nil
86
- if logger
87
- #todo: hack - what about other logger classes?
88
- logger.formatter = lambda {|severity, datetime, progname, msg| "#{msg}"} if logger.is_a? Logger
89
- write = lambda { |level, tag, msg | logger.send(level, formatter.call(level, tag, msg)) }
90
- code = block ? lambda { |l,t,m| write.call(l,t,m); block.call(l,t,m) } : write
91
- elsif block
92
- code = block
93
- else
94
- raise ArgumentError "Should be called with block or :to => <logger>"
95
- end
96
- @tag_blocks[tag_matcher(what, level)] = code
97
- end
98
-
99
- class TagMatcher
100
- attr_reader :match_spec
101
- LEVELS = { :debug => 1, :info => 2, :warn => 3, :error => 4, :fatal => 5}
102
-
103
- def initialize(match_spec, level = nil)
104
- @level = level || :debug
105
- @match_spec = match_spec
106
- end
107
-
108
- def match?(tag, level = nil)
109
- return false if level && !above_treshold(level)
110
- self.class.match?(@match_spec, tag)
111
- end
112
-
113
- def above_treshold(level)
114
- LEVELS[@level] <= LEVELS[level]
115
- end
116
-
117
- def self.match?(spec, tag)
118
- t = tag.to_s
119
- result = case spec
120
- when Regexp
121
- t =~ spec
122
- when Class
123
- t == spec.name
124
- when Array
125
- spec.any? {|s| match?(s, tag)}
126
- else
127
- spec.to_s == t
128
- end
129
- return result if result
130
- self.match?(spec, tag.superclass) if tag.class == Class && tag.superclass != Class
131
- end
132
- end #TagMatcher
133
-
134
- def tag_matcher(tag, level = nil)
135
- TagMatcher.new(tag, level)
136
- end
137
-
138
- def tag_aliases(tag, &block)
139
- current_name = tag
140
- @rename_rules.each { |from, to| current_name = to if from.match?(tag) }
141
- block.call(current_name)
142
- end
143
-
144
- def tag_blocks(level, tag, &block)
145
- @tag_blocks.each do |matcher, block|
146
- yield block if matcher.match?(tag, level)
147
- end
148
- end
149
-
150
- def inject_logger_method_in_call_chain(definee_klass)
151
- if klass_has_method?(definee_klass, :logger)
152
- #so we could resurrect old :logger method if we need
153
- definee_klass.class_eval { alias_method :tagged_logger_original_logger, :logger }
154
- end
155
- definee_klass.class_eval do
156
- def logger
157
- klass = self.class == Class ? self : self.class
158
- result = klass.class_eval do
159
- return @class_logger if @class_logger
160
- @class_logger = ClassSpecificLogger.new(klass)
161
- @class_logger
162
- end
163
- result
164
- end
165
- end
166
- end
167
-
168
- end # class methods
169
-
170
- class ClassSpecificLogger
171
- def eigenclass
172
- class <<self; self; end
173
- end
174
-
175
- def initialize(klass)
176
- @klass = klass
177
- [:debug, :warn, :info, :error, :fatal].each do |level|
178
- blocks = TaggedLogger.blocks_for(level, klass)
179
- eigenclass.send(:define_method, level) do |msg|
180
- blocks.each { |(tag_alias, block)| block.call(level, tag_alias, msg) }
181
- end
182
- end
183
- end
184
-
185
- def detach
186
- @klass.class_eval do
187
- @class_logger = nil
188
- end
189
- end
190
- end
191
-
192
- end
1
+ dir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
3
+ require 'tagged_logger/railtie'
4
+ require 'tagged_logger/tagged_logger'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tagged_logger
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 0
10
- version: 0.4.0
9
+ - 2
10
+ version: 0.4.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Aleksandr Furmanov
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-19 00:00:00 -05:00
18
+ date: 2010-10-21 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -90,7 +90,8 @@ files:
90
90
  - MIT-LICENSE
91
91
  - Rakefile
92
92
  - README.markdown
93
- - tagged_logger.rb
93
+ - lib/tagged_logger/railtie.rb
94
+ - lib/tagged_logger/tagged_logger.rb
94
95
  - lib/tagged_logger.rb
95
96
  - test/expected_examples_output.txt
96
97
  - test/test.rb
data/tagged_logger.rb DELETED
@@ -1 +0,0 @@
1
- require File.dirname(__FILE__) + '/lib/tagged_logger.rb'