lumber 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46565c6578428e0fd2b235b3c342958c1bdd2ca2
4
- data.tar.gz: f6d4b6262295e7e8f7eb9ffac68ae180ae9329c0
3
+ metadata.gz: 39acf970ab7a4cba53d738adec952246cdb7e36d
4
+ data.tar.gz: 84b4141111b47aafb6a133913f4d118c6ba7bacf
5
5
  SHA512:
6
- metadata.gz: 252efef13b42f54c839d9b9b20908df2e6902a9b657c9452283e9dde81600ce63ebb95f9d9f2878b65eead7e2d6da8279761e00bdfb9a63a7ffba5117dec48f8
7
- data.tar.gz: 3110b279693bea1ad2a1b522aff0c9c9ab6c57090e1a1c6b3f44adda84748af326f44a84f994144d9e296c5d05888bd621d8feed5062f5cc8108e11b4d848629
6
+ metadata.gz: d59e9dea06165dea70ad6d4f49e7e271065452c8c58c7656fbcac166dc20d792f2033219416941abe28e2274308945f6b88fea7c1c9c8643b1362397681dc1e1
7
+ data.tar.gz: 6a2a398953b7f856988abcf74950d3e50086647b3d1b8e4ec95aadb2a93e3548f15d1e889306ab5afa1a0b44956ea5f62fd4d105320aa85fe338b763d3511397
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ 1.1.0 (11/10/2013)
2
+ ------------------
3
+
4
+ Make loggers get created lazily, refactoring to support this behavior and (hopefully) make the code more understandable <8c2bd7b> [Matt Conway]
5
+ disable coveralls for jruby <9a1ff9b> [Matt Conway]
6
+ fix jruby <71dc96f> [Matt Conway]
7
+ fix rails generator <164c9ed> [Matt Conway]
8
+ fix tests for move of log4r.yml in generators <319fc3d> [Matt Conway]
9
+ more readable <20a9666> [Matt Conway]
10
+ refactor a bit to add more thread safety <3712ee1> [Matt Conway]
11
+ try and fix travis error <7a4e59e> [Matt Conway]
12
+
1
13
  1.0.3 (10/11/2013)
2
14
  ------------------
3
15
 
@@ -0,0 +1,10 @@
1
+
2
+ class LumberGenerator < Rails::Generators::Base
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ desc "This generator adds a log4r.yml in config/"
6
+ def create_log4r_yml
7
+ copy_file "log4r.yml", "config/log4r.yml"
8
+ end
9
+
10
+ end
data/lib/lumber.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
 
3
3
  # before config block
4
+ require "monitor"
4
5
  require "lumber/lumber"
6
+ require "lumber/inheritance_registry"
5
7
  require "lumber/logger_support"
8
+ require "lumber/prevent_rails_override"
6
9
  require "lumber/log4r"
7
10
  require "lumber/level_util"
8
11
  require "lumber/json_formatter"
@@ -0,0 +1,85 @@
1
+ module Lumber
2
+
3
+ module InheritanceRegistry
4
+ extend MonitorMixin
5
+ extend self
6
+
7
+ @mapping = {}
8
+
9
+ def []=(class_name, logger_fullname)
10
+ synchronize do
11
+ @mapping[class_name] = logger_fullname
12
+ end
13
+ end
14
+
15
+ def [](class_name)
16
+ synchronize do
17
+ @mapping[class_name]
18
+ end
19
+ end
20
+
21
+ def clear
22
+ synchronize do
23
+ @mapping.clear
24
+ end
25
+ end
26
+
27
+ def find_registered_logger(clazz)
28
+ synchronize do
29
+ return nil unless clazz
30
+ logger_name = self[clazz.name]
31
+ logger_name || find_registered_logger(clazz.superclass)
32
+ end
33
+ end
34
+
35
+ def remove_inheritance_handler
36
+ synchronize do
37
+
38
+ return unless defined?(Object.inherited_with_lumber_registry)
39
+
40
+ Object.class_eval do
41
+ class << self
42
+ remove_method :inherited_with_lumber_registry
43
+ remove_method :inherited
44
+ alias_method :inherited, :inherited_without_lumber_registry
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ # Adds a inheritance handler to Object so we can add loggers for registered classes
52
+ def register_inheritance_handler
53
+ synchronize do
54
+
55
+ return if defined?(Object.inherited_with_lumber_registry)
56
+
57
+ Object.class_eval do
58
+
59
+ class << self
60
+
61
+ def inherited_with_lumber_registry(subclass)
62
+ inherited_without_lumber_registry(subclass)
63
+
64
+ # Add a logger to 'subclass' if it is directly in the registry
65
+ # No need to check full inheritance chain LoggerSupport handles it
66
+ # Also prevent rails from subsequently overriding our logger when rails
67
+ # is loaded after registering logger inheritance
68
+ if Lumber::InheritanceRegistry[subclass.name]
69
+ subclass.send(:include, Lumber::LoggerSupport)
70
+ subclass.send(:include, Lumber::PreventRailsOverride)
71
+ end
72
+ end
73
+
74
+ alias_method_chain :inherited, :lumber_registry
75
+
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ end
@@ -1,11 +1,35 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/module/delegation'
3
+
1
4
  module Lumber
2
5
 
3
6
  # Include this module to add a logger accessible from both class and instance methods.
4
- # A logger heirarchy will be created if the class including this module is nested
7
+ # A logger hierarchy will be created if the class including this module is nested
5
8
  module LoggerSupport
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+
13
+ delegate :logger, :to => "self.class"
14
+
15
+ end
16
+
17
+ module ClassMethods
18
+
19
+
20
+ def logger
21
+ # This should probably be synchronized, but don't want to
22
+ # incur the performance hit on such a heavily used method.
23
+ # I think the worst case is that it'll just get assigned
24
+ # multiple times, but it'll get the same reference because
25
+ # Lumber.logger has a lock
26
+ @lumber_logger ||= Lumber.logger_for(self)
27
+ end
28
+
29
+ def logger=(logger)
30
+ @lumber_logger = logger
31
+ end
6
32
 
7
- def self.included(receiver)
8
- Lumber.setup_logger_hierarchy(receiver.name, "#{Lumber::BASE_LOGGER}::#{receiver.name}")
9
33
  end
10
34
 
11
35
  end
data/lib/lumber/lumber.rb CHANGED
@@ -25,6 +25,9 @@ module Lumber
25
25
  # name of top level logger (can't be root as you can't have outputters on root)
26
26
  BASE_LOGGER= 'rails'
27
27
 
28
+ extend MonitorMixin
29
+ extend self
30
+
28
31
  # Initializes log4r system. Needs to happen in
29
32
  # config/environment.rb before Rails::Initializer.run
30
33
  #
@@ -41,7 +44,7 @@ module Lumber
41
44
  # All config options get passed through to the log4r
42
45
  # configurator for use in defining outputters
43
46
  #
44
- def self.init(opts = {})
47
+ def init(opts = {})
45
48
  opts[:root] ||= RAILS_ROOT.to_s if defined?(RAILS_ROOT)
46
49
  opts[:env] ||= RAILS_ENV if defined?(RAILS_ENV)
47
50
  opts[:config_file] ||= "#{opts[:root]}/config/log4r.yml"
@@ -63,11 +66,10 @@ module Lumber
63
66
  if defined?(RAILS_DEFAULT_LOGGER)
64
67
  Object.send(:remove_const, :RAILS_DEFAULT_LOGGER)
65
68
  end
66
- Object.const_set('RAILS_DEFAULT_LOGGER', Log4r::Logger[BASE_LOGGER])
69
+ Object.const_set('RAILS_DEFAULT_LOGGER', find_or_create_logger(BASE_LOGGER))
70
+
71
+ Lumber::InheritanceRegistry.clear
67
72
 
68
- self.registered_loggers.clear
69
- self.register_inheritance_handler()
70
-
71
73
  if opts[:monitor_store]
72
74
  # Setting to Rails.cache handled by a post initialize_cache rails initializer
73
75
  # since Rails.cache is not available when lumber is initialized
@@ -76,12 +78,50 @@ module Lumber
76
78
  LevelUtil.start_monitor(opts[:monitor_interval]) if opts[:monitor_enabled]
77
79
  end
78
80
 
79
- def self.find_or_create_logger(fullname)
80
- Log4r::Logger[fullname] || Log4r::Logger.new(fullname)
81
+ def logger_name(clazz)
82
+ # Use the registered logger name if this class is in the registry
83
+ logger_name = Lumber::InheritanceRegistry[clazz.name]
84
+ if logger_name.nil?
85
+ # if not, find the first registered logger name in the superclass chain, if any
86
+ logger_name = Lumber::InheritanceRegistry.find_registered_logger(clazz.superclass)
87
+ if logger_name.nil?
88
+ # use name from clazz as we aren't inheriting
89
+ logger_name = "#{Lumber::BASE_LOGGER}#{Log4r::Log4rConfig::LoggerPathDelimiter}#{clazz.name}"
90
+ else
91
+ # base name on inherited logger and clazz since we are inheriting
92
+ # In log4r, a logger's parent is looked up from the name, and
93
+ # Lumber.find_or_create_logger ensures that loggers are created for
94
+ # all pieces of the name
95
+ logger_name = "#{logger_name}#{Log4r::Log4rConfig::LoggerPathDelimiter}#{clazz.name}"
96
+ end
97
+ end
98
+ logger_name
81
99
  end
82
-
83
- def self.registered_loggers
84
- @registered_loggers ||= {}
100
+
101
+ def logger_for(clazz)
102
+ synchronize do
103
+ Lumber.find_or_create_logger(logger_name(clazz))
104
+ end
105
+ end
106
+
107
+ def find_or_create_logger(fullname)
108
+ synchronize do
109
+ logger = Log4r::Logger[fullname]
110
+ if logger.nil?
111
+ # build the loggers from the lhs up to ensure the name based logger inheritance gets applied
112
+ parts = fullname.split(Log4r::Log4rConfig::LoggerPathDelimiter)
113
+ aggregate_name = nil
114
+ parts.each do |part|
115
+ if aggregate_name.nil?
116
+ aggregate_name = part
117
+ else
118
+ aggregate_name = "#{aggregate_name}#{Log4r::Log4rConfig::LoggerPathDelimiter}#{part}"
119
+ end
120
+ logger = Log4r::Logger[aggregate_name] || Log4r::Logger.new(aggregate_name)
121
+ end
122
+ end
123
+ logger
124
+ end
85
125
  end
86
126
 
87
127
  # Makes :logger exist independently for subclasses and sets that logger
@@ -99,109 +139,24 @@ module Lumber
99
139
  # output will include "<class_name>" on every log from this class
100
140
  # so that you can tell where a log statement came from
101
141
  #
102
- def self.setup_logger_hierarchy(class_name, class_logger_fullname)
103
- Lumber.registered_loggers[class_name] = class_logger_fullname
142
+ def setup_logger_hierarchy(class_name, class_logger_fullname)
143
+ Lumber::InheritanceRegistry.register_inheritance_handler
144
+ Lumber::InheritanceRegistry[class_name] = class_logger_fullname
104
145
 
105
146
  begin
106
147
  clazz = class_name.constantize
107
-
108
- # ActiveSupport 3.2 introduced class_attribute, which is supposed to be used instead of class_inheritable_accessor if available
109
- [:class_attribute, :class_inheritable_accessor].each do |class_attribute_method|
110
-
111
- if clazz.respond_to? class_attribute_method
112
- clazz.class_eval do
113
- send class_attribute_method, :logger
114
- self.logger = Lumber.find_or_create_logger(class_logger_fullname)
115
- end
116
-
117
- break
118
- end
119
- end
120
-
148
+ clazz.send(:include, Lumber::LoggerSupport)
121
149
  rescue NameError
122
- # The class hasn't been defined yet. No problem, we've registered the logger for when the class is created.
150
+ # The class hasn't been defined yet. No problem, we've registered
151
+ # the logger for when the class is created.
123
152
  end
124
153
  end
125
154
 
126
155
  # Helper to make it easier to log context through log4r.yml
127
- def self.format_mdc()
156
+ def format_mdc()
128
157
  ctx = Log4r::MDC.get_context.collect {|k, v| k.to_s + "=" + v.to_s }.join(" ")
129
158
  ctx.gsub!('%', '%%')
130
159
  return ctx
131
160
  end
132
-
133
- private
134
-
135
- # Adds a inheritance handler to Object so we can know to add loggers
136
- # for classes as they get defined.
137
- def self.register_inheritance_handler()
138
- return if defined?(Object.inherited_with_lumber_log4r)
139
-
140
- Object.class_eval do
141
-
142
- class << self
143
-
144
- def inherited_with_lumber_log4r(subclass)
145
- inherited_without_lumber_log4r(subclass)
146
-
147
- # if the new class is in the list that were registered directly,
148
- # then create their logger attribute directly, otherwise derive it
149
- logger_name = Lumber.registered_loggers[subclass.name]
150
- if logger_name
151
- Lumber.add_lumber_logger(subclass, logger_name)
152
- else
153
- Lumber.derive_lumber_logger(subclass)
154
- end
155
- end
156
-
157
- alias_method_chain :inherited, :lumber_log4r
158
-
159
- end
160
-
161
- end
162
-
163
- end
164
-
165
- def self.add_lumber_logger(clazz, logger_name)
166
- clazz.class_eval do
167
- # ActiveSupport 3.2 introduced class_attribute, which is supposed to be used instead of class_inheritable_accessor if available
168
- if respond_to? :class_attribute
169
- class_attribute :logger
170
- else
171
- class_inheritable_accessor :logger
172
- end
173
-
174
- self.logger = Lumber.find_or_create_logger(logger_name)
175
-
176
- class << self
177
-
178
- # Prevent rails from overwriting our logger
179
- def cattr_accessor_with_lumber_log4r(*syms)
180
- without_logger = syms.reject {|s| s == :logger}
181
- cattr_accessor_without_lumber_log4r(*without_logger)
182
- end
183
- alias_method_chain :cattr_accessor, :lumber_log4r
184
-
185
- end
186
-
187
- end
188
- end
189
161
 
190
- def self.derive_lumber_logger(clazz)
191
- # otherwise, walk up the classes hierarchy till you find a logger
192
- # that was registered, and use that logger as the parent for the
193
- # logger of the new class
194
- parent = clazz.superclass
195
- while ! parent.nil?
196
- parent_logger_name = (parent.respond_to?(:logger) && parent.logger.respond_to?(:fullname)) ? parent.logger.fullname : ''
197
- parent_is_registered = Lumber.registered_loggers.values.find {|v| parent_logger_name.index(v) == 0}
198
- if parent_is_registered && parent.method_defined?(:logger=)
199
- fullname = "#{parent_logger_name}::#{clazz.name.nil? ? 'anonymous' : clazz.name.split('::').last}"
200
- clazz.logger = Lumber.find_or_create_logger(fullname)
201
- break
202
- end
203
- parent = parent.superclass
204
- end
205
- end
206
-
207
- end
162
+ end
@@ -0,0 +1,25 @@
1
+ require 'active_support/concern'
2
+
3
+ module Lumber
4
+
5
+ # Include this module to add a logger accessible from both class and instance methods.
6
+ # A logger hierarchy will be created if the class including this module is nested
7
+ module PreventRailsOverride
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+
12
+ class << self
13
+ # Prevent rails from overwriting our logger
14
+ def cattr_accessor_with_lumber(*syms)
15
+ without_logger = syms.reject {|s| s == :logger}
16
+ cattr_accessor_without_lumber(*without_logger)
17
+ end
18
+ alias_method_chain :cattr_accessor, :lumber
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -15,7 +15,7 @@ module Lumber
15
15
  Lumber.setup_logger_hierarchy("ActionController::Base", "rails::controllers")
16
16
  Lumber.setup_logger_hierarchy("ActionMailer::Base", "rails::mailers")
17
17
  end
18
- app.config.logger = Log4r::Logger[Lumber::BASE_LOGGER]
18
+ app.config.logger = Lumber.find_or_create_logger(Lumber::BASE_LOGGER)
19
19
 
20
20
  config_level = app.config.log_level
21
21
  if config_level.present?
@@ -1,3 +1,3 @@
1
1
  module Lumber
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lumber::InheritanceRegistry do
4
+
5
+ before(:each) do
6
+ InheritanceRegistry.clear
7
+ end
8
+
9
+ it "allows registering a class" do
10
+ InheritanceRegistry['Foo'] = 'root::Foo'
11
+ InheritanceRegistry['Foo'].should == 'root::Foo'
12
+ end
13
+
14
+ it "allows clearing registry" do
15
+ InheritanceRegistry['Foo'] = 'root::Foo'
16
+ InheritanceRegistry['Foo'].should == 'root::Foo'
17
+ InheritanceRegistry.clear
18
+ InheritanceRegistry['Foo'].should be_nil
19
+ end
20
+
21
+ describe "#find_registered_logger" do
22
+
23
+ it "returns nil if clazz is nil" do
24
+ InheritanceRegistry.find_registered_logger(nil).should be_nil
25
+ end
26
+
27
+ it "returns the registered name if clazz is registered" do
28
+ class Foo; end
29
+ InheritanceRegistry['Foo'] = 'root::Foo'
30
+ InheritanceRegistry.find_registered_logger(Foo).should == "root::Foo"
31
+ end
32
+
33
+ it "returns the registered name if superclass is registered" do
34
+ class Foo; end
35
+ class Bar < Foo; end
36
+ InheritanceRegistry['Foo'] = 'root::Foo'
37
+ InheritanceRegistry.find_registered_logger(Bar).should == "root::Foo"
38
+ end
39
+
40
+ it "returns the registered name if superclass is registered" do
41
+ class Foo1; end
42
+ class Foo2 < Foo1; end
43
+ class Foo3 < Foo2; end
44
+ class Bar < Foo3; end
45
+ InheritanceRegistry['Foo1'] = 'root::Foo1'
46
+ InheritanceRegistry.find_registered_logger(Bar).should == "root::Foo1"
47
+ end
48
+
49
+ it "doesn't use classes past first registered superclass" do
50
+ class Foo1; end
51
+ class Foo2 < Foo1; end
52
+ class Foo3 < Foo2; end
53
+ class Bar < Foo3; end
54
+ InheritanceRegistry['Foo1'] = 'root::Foo1'
55
+ InheritanceRegistry['Foo2'] = 'root::Foo2'
56
+ InheritanceRegistry.find_registered_logger(Bar).should == "root::Foo2"
57
+ end
58
+
59
+ end
60
+
61
+ describe "#remove_inheritance_handler" do
62
+
63
+ it "should remove the handler" do
64
+ defined?(Object.inherited_with_lumber_registry).should be_false
65
+ InheritanceRegistry.register_inheritance_handler
66
+ defined?(Object.inherited_with_lumber_registry).should be_true
67
+ InheritanceRegistry.remove_inheritance_handler
68
+ defined?(Object.inherited_with_lumber_registry).should be_false
69
+ end
70
+
71
+ end
72
+
73
+ describe "#register_inheritance_handler" do
74
+
75
+ before(:each) do
76
+ InheritanceRegistry.remove_inheritance_handler
77
+ end
78
+
79
+ it "adds an inheritance handler" do
80
+ defined?(Object.inherited_with_lumber_registry).should be_false
81
+ InheritanceRegistry.register_inheritance_handler
82
+ defined?(Object.inherited_with_lumber_registry).should be_true
83
+ end
84
+
85
+ it "doesn't add an inheritance handler multiple times" do
86
+ Object.singleton_class.should_receive(:alias_method_chain).once.and_call_original
87
+ defined?(Object.inherited_with_lumber_registry).should be_false
88
+ InheritanceRegistry.register_inheritance_handler
89
+ defined?(Object.inherited_with_lumber_registry).should be_true
90
+ InheritanceRegistry.register_inheritance_handler
91
+ defined?(Object.inherited_with_lumber_registry).should be_true
92
+ end
93
+
94
+ it "doesn't change classes that aren't registered" do
95
+ InheritanceRegistry.register_inheritance_handler
96
+ class Foo; end
97
+ Foo.ancestors.should_not include(Lumber::LoggerSupport)
98
+ Foo.ancestors.should_not include(Lumber::PreventRailsOverride)
99
+ end
100
+
101
+ it "adds logger support for classes that are registered" do
102
+ InheritanceRegistry.register_inheritance_handler
103
+ InheritanceRegistry["Foo"] = "root::Foo"
104
+ class Foo; end
105
+ Foo.ancestors.should include(Lumber::LoggerSupport)
106
+ Foo.ancestors.should include(Lumber::PreventRailsOverride)
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -7,7 +7,7 @@ describe Lumber::LevelUtil do
7
7
  root = "#{File.dirname(__FILE__)}/.."
8
8
  Lumber.init(:root => root,
9
9
  :env => 'test',
10
- :config_file => "#{root}/generators/lumber/templates/log4r.yml",
10
+ :config_file => "#{root}/lib/generators/lumber/templates/log4r.yml",
11
11
  :log_file => "/tmp/lumber-test.log")
12
12
 
13
13
  @name = "foo_#{Time.now.to_f}"
@@ -6,34 +6,36 @@ describe Lumber::LoggerSupport do
6
6
  root = "#{File.dirname(__FILE__)}/.."
7
7
  Lumber.init(:root => root,
8
8
  :env => 'test',
9
- :config_file => "#{root}/generators/lumber/templates/log4r.yml",
9
+ :config_file => "#{root}/lib/generators/lumber/templates/log4r.yml",
10
10
  :log_file => "/tmp/lumber-test.log")
11
11
  end
12
12
 
13
- after(:each) do
14
- self.class.constants.grep(/^Foo/).each do |c|
15
- self.send(:remove_const, c)
16
- end
13
+ it "should memoize logger" do
14
+ class Foo; include Lumber::LoggerSupport; end
15
+ Lumber.should_receive(:logger_for).once.and_call_original
16
+
17
+ Foo.logger.fullname.should == "rails::Foo"
18
+ Foo.logger.fullname.should == "rails::Foo"
17
19
  end
18
20
 
19
- it "should create logger for chain" do
21
+ it "makes a logger available for subclasses" do
20
22
  class Foo; include Lumber::LoggerSupport; end
21
23
  class Bar < Foo; end;
22
- Foo.logger.should == Log4r::Logger["rails::Foo"]
23
- Bar.logger.should == Log4r::Logger["rails::Foo::Bar"]
24
- Bar.logger.parent.should == Log4r::Logger["rails::Foo"]
24
+ Foo.logger.fullname.should == "rails::Foo"
25
+ Bar.logger.fullname.should == "rails::Bar"
26
+ Bar.logger.parent.fullname.should == "rails"
25
27
  end
26
28
 
27
29
  it "should have a logger instance accessible from an instance method" do
28
30
  class Foo; include Lumber::LoggerSupport; def member_method; logger.debug('hi'); end; end
29
- logger = Log4r::Logger["rails::Foo"]
31
+ logger = Lumber.find_or_create_logger("rails::Foo")
30
32
  logger.should_receive(:debug).with('hi')
31
33
  Foo.new.member_method
32
34
  end
33
35
 
34
36
  it "should have a logger instance accessible from a class method " do
35
37
  class Foo; include Lumber::LoggerSupport; def self.class_method; logger.debug('hi'); end; end
36
- logger = Log4r::Logger["rails::Foo"]
38
+ logger = Lumber.find_or_create_logger("rails::Foo")
37
39
  logger.should_receive(:debug).with('hi')
38
40
  Foo.class_method
39
41
  end
@@ -52,7 +54,7 @@ describe Lumber::LoggerSupport do
52
54
 
53
55
  cfg = Log4r::YamlConfigurator
54
56
  cfg.load_yaml_string(yml)
55
- logger = Log4r::Logger['rails::Foo']
57
+ logger = Lumber.find_or_create_logger("rails::Foo")
56
58
  sio = StringIO.new
57
59
  logger.outputters = [Log4r::IOOutputter.new("sbout", sio)]
58
60
  class Foo; include Lumber::LoggerSupport; end
data/spec/lumber_spec.rb CHANGED
@@ -1,157 +1,194 @@
1
1
  require 'spec_helper'
2
2
  require 'delegate'
3
3
 
4
- def new_class(class_name, super_class=nil, super_module=nil)
5
- s = "class #{class_name}"
6
- s << " < #{super_class}" if super_class
7
- s << "; end"
8
-
9
- s = "module #{super_module}; #{s}; end" if super_module
10
-
11
- eval s
12
- end
13
-
14
4
  describe Lumber do
15
5
 
16
6
  before(:each) do
17
7
  root = "#{File.dirname(__FILE__)}/.."
18
8
  Lumber.init(:root => root,
19
9
  :env => 'test',
20
- :config_file => "#{root}/generators/lumber/templates/log4r.yml",
10
+ :config_file => "#{root}/lib/generators/lumber/templates/log4r.yml",
21
11
  :log_file => "/tmp/lumber-test.log")
22
12
  end
23
13
 
24
- after(:each) do
25
- Object.constants.grep(/^Foo/).each do |c|
26
- Object.send(:remove_const, c)
14
+ describe "#logger_name" do
15
+
16
+ it "generates a name for a simple class" do
17
+ new_class('Foo')
18
+ Lumber.logger_name(Foo).should == "rails::Foo"
27
19
  end
28
- end
29
20
 
30
- def assert_valid_logger(class_name, logger_name)
31
- clazz = eval class_name
32
- clazz.should_not be_nil
33
- clazz.respond_to?(:logger).should be_true
34
- lgr = clazz.logger
35
- lgr.should be_an_instance_of(Log4r::Logger)
36
- lgr.fullname.should == logger_name
37
- end
21
+ it "generates a name for a registered class" do
22
+ Lumber.setup_logger_hierarchy("Foo", "root::foo")
23
+ new_class('Foo')
24
+ Lumber.logger_name(Foo).should == "root::foo"
25
+ end
38
26
 
39
- it "should not do anything if no loggers registered" do
40
- defined?(Object.inherited_with_lumber_log4r).should be_true
41
- defined?(Object.logger).should be_false
42
- end
27
+ it "generates a name for a subclass" do
28
+ Lumber.setup_logger_hierarchy("Foo", "root::foo")
29
+ new_class('Foo')
30
+ new_class('Bar', 'Foo')
31
+ Lumber.logger_name(Bar).should == "root::foo::Bar"
32
+ end
43
33
 
44
- it "should allow registering logger for a class before the class is defined" do
45
- defined?(Foo1).should be_false
46
- Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
47
- new_class('Foo1')
48
- assert_valid_logger('Foo1', "root::foo1")
49
- end
34
+ it "generates a name for a deep subclass" do
35
+ Lumber.setup_logger_hierarchy("Foo", "root::foo")
36
+ new_class('Foo')
37
+ new_class('Foo1', 'Foo')
38
+ new_class('Bar', 'Foo1')
39
+ Lumber.logger_name(Bar).should == "root::foo::Bar"
40
+ end
50
41
 
51
- it "should not register new logger for subclasses of classes that delegate logger" do
52
- defined?(Foo1).should be_false # ActionController::Base
53
- defined?(Foo2).should be_false # ActionView::Base
54
- defined?(Foo3).should be_false # Subclass of ActionView::Base
55
- Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
56
- eval "class ::Foo1; end"
57
- eval "class ::Foo2; delegate :logger, :to => Foo1; end"
58
- eval "class ::Foo3 < Foo2; end"
59
- assert_valid_logger('Foo1', "root::foo1")
60
- Foo2.new.logger.should == Foo1.logger
61
- Foo3.new.logger.should == Foo1.logger
62
42
  end
63
43
 
64
- it "should no logger when parent is via delegate class" do
65
- defined?(Foo1).should be_false
66
- defined?(Foo2).should be_false
67
- defined?(Foo3).should be_false
68
- Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
69
- eval "class ::Foo1; end"
70
- eval "class ::Foo2 < DelegateClass(Foo1); end"
71
- eval "class ::Foo3 < Foo2; end"
72
- assert_valid_logger('Foo1', "root::foo1")
73
- defined?(Foo3.logger).should be_false
74
- end
44
+ describe "#logger_for" do
45
+
46
+ it "gets the logger" do
47
+ new_class('Foo')
48
+ Lumber.logger_for(Foo).fullname.should == "rails::Foo"
49
+ end
75
50
 
76
- it "should allow registering independent loggers for classes in a hierarchy" do
77
- defined?(Foo1).should be_false
78
- defined?(Foo2).should be_false
79
- Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
80
- Lumber.setup_logger_hierarchy("Foo2", "root::foo2")
81
- new_class('Foo1')
82
- new_class('Foo2', 'Foo1')
83
- assert_valid_logger('Foo1', "root::foo1")
84
- assert_valid_logger('Foo2', "root::foo2")
85
51
  end
86
52
 
87
- it "should prevent cattr_accessor for a class registered before the class is defined" do
88
- defined?(Foo1).should be_false
89
- Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
90
- new_class('Foo1')
91
- Foo1.class_eval do
92
- cattr_accessor :logger, :foo
53
+ describe "#find_or_create_logger" do
54
+
55
+ it "creates loggers for each segment" do
56
+ Log4r::Logger['foo1'].should be_nil
57
+ Log4r::Logger['foo1::foo2'].should be_nil
58
+ Log4r::Logger['foo1::foo2::foo3'].should be_nil
59
+ Log4r::Logger['foo1::foo2::foo3::bar'].should be_nil
60
+
61
+ Lumber.find_or_create_logger("foo1::foo2::foo3::bar")
62
+
63
+ Log4r::Logger['foo1'].should_not be_nil
64
+ Log4r::Logger['foo1'].parent.should == Log4r::Logger['root']
65
+ Log4r::Logger['foo1::foo2'].should_not be_nil
66
+ Log4r::Logger['foo1::foo2'].parent.should == Log4r::Logger['foo1']
67
+ Log4r::Logger['foo1::foo2::foo3'].should_not be_nil
68
+ Log4r::Logger['foo1::foo2::foo3'].parent.should == Log4r::Logger['foo1::foo2']
69
+ Log4r::Logger['foo1::foo2::foo3::bar'].should_not be_nil
70
+ Log4r::Logger['foo1::foo2::foo3::bar'].parent.should == Log4r::Logger['foo1::foo2::foo3']
71
+ end
72
+
73
+ it "only creates loggers once" do
74
+ Log4r::Logger.should_receive(:new).twice.and_call_original
75
+ Lumber.find_or_create_logger("bar1::bar2")
76
+ Lumber.find_or_create_logger("bar1::bar2")
93
77
  end
94
- defined?(Foo1.foo).should be_true
95
- assert_valid_logger('Foo1', "root::foo1")
96
- end
97
78
 
98
- it "should allow registering logger for a nested class before the class is defined" do
99
- defined?(Bar1::Foo1).should be_false
100
- Lumber.setup_logger_hierarchy("Bar1::Foo1", "root::foo1")
101
- new_class('Foo1', nil, 'Bar1')
102
- assert_valid_logger('Bar1::Foo1', "root::foo1")
103
79
  end
104
80
 
105
- it "should allow registering logger for a class after the class is defined" do
106
- defined?(Foo1).should be_false
107
- new_class('Foo1')
108
- defined?(Foo1).should be_true
81
+ describe "#setup_logger_hierarchy" do
109
82
 
110
- Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
111
- assert_valid_logger('Foo1', "root::Foo1")
112
- end
83
+ it "should allow registering logger for a class before the class is defined" do
84
+ defined?(Foo1).should be_false
85
+ Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
86
+ new_class('Foo1')
87
+ assert_valid_logger('Foo1', "root::foo1")
88
+ end
113
89
 
114
- it "should register loggers for subclasses of registered classes" do
115
- defined?(Foo1).should be_false
116
- defined?(Foo2).should be_false
117
- defined?(Foo3).should be_false
118
- Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
119
- new_class('Foo1')
120
- new_class('Foo2', 'Foo1')
121
- new_class('Foo3')
122
- assert_valid_logger('Foo1', "root::Foo1")
123
- assert_valid_logger('Foo2', "root::Foo1::Foo2")
124
- defined?(Foo3.logger).should be_false
125
- end
90
+ it "should not register new logger for subclasses of classes that delegate logger" do
91
+ defined?(Foo1).should be_false # ActionController::Base
92
+ defined?(Foo2).should be_false # ActionView::Base
93
+ defined?(Foo3).should be_false # Subclass of ActionView::Base
94
+ Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
95
+ eval "class ::Foo1; end"
96
+ eval "class ::Foo2; delegate :logger, :to => Foo1; end"
97
+ eval "class ::Foo3 < Foo2; end"
98
+ assert_valid_logger('Foo1', "root::foo1")
99
+ Foo2.new.logger.should == Foo1.logger
100
+ Foo3.new.logger.should == Foo1.logger
101
+ end
126
102
 
127
- it "should register loggers for sub-subclasses of registered classes" do
128
- defined?(Foo1).should be_false
129
- defined?(Foo2).should be_false
130
- defined?(Foo3).should be_false
131
- Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
132
- new_class('Foo1')
133
- new_class('Foo2', 'Foo1')
134
- new_class('Foo3', 'Foo2')
135
- assert_valid_logger('Foo1', "root::Foo1")
136
- assert_valid_logger('Foo2', "root::Foo1::Foo2")
137
- assert_valid_logger('Foo3', "root::Foo1::Foo2::Foo3")
138
- end
103
+ it "should no logger when parent is via delegate class" do
104
+ defined?(Foo1).should be_false
105
+ defined?(Foo2).should be_false
106
+ defined?(Foo3).should be_false
107
+ Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
108
+ eval "class ::Foo1; end"
109
+ eval "class ::Foo2 < DelegateClass(Foo1); end"
110
+ eval "class ::Foo3 < Foo2; end"
111
+ assert_valid_logger('Foo1', "root::foo1")
112
+ defined?(Foo3.logger).should be_false
113
+ end
114
+
115
+ it "should allow registering independent loggers for classes in a hierarchy" do
116
+ defined?(Foo1).should be_false
117
+ defined?(Foo2).should be_false
118
+ Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
119
+ Lumber.setup_logger_hierarchy("Foo2", "root::foo2")
120
+ new_class('Foo1')
121
+ new_class('Foo2', 'Foo1')
122
+ assert_valid_logger('Foo1', "root::foo1")
123
+ assert_valid_logger('Foo2', "root::foo2")
124
+ end
125
+
126
+ it "should prevent cattr_accessor for a class registered before the class is defined" do
127
+ defined?(Foo1).should be_false
128
+ Lumber.setup_logger_hierarchy("Foo1", "root::foo1")
129
+ new_class('Foo1')
130
+ Foo1.class_eval do
131
+ cattr_accessor :logger, :foo
132
+ end
133
+ defined?(Foo1.foo).should be_true
134
+ assert_valid_logger('Foo1', "root::foo1")
135
+ end
136
+
137
+ it "should allow registering logger for a nested class before the class is defined" do
138
+ defined?(Bar1::Foo1).should be_false
139
+ Lumber.setup_logger_hierarchy("Bar1::Foo1", "root::foo1")
140
+ new_class('Foo1', nil, 'Bar1')
141
+ assert_valid_logger('Bar1::Foo1', "root::foo1")
142
+ end
143
+
144
+ it "should allow registering logger for a class after the class is defined" do
145
+ defined?(Foo1).should be_false
146
+ new_class('Foo1')
147
+ defined?(Foo1).should be_true
148
+
149
+ Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
150
+ assert_valid_logger('Foo1', "root::Foo1")
151
+ end
152
+
153
+ it "should register loggers for subclasses of registered classes" do
154
+ defined?(Foo1).should be_false
155
+ defined?(Foo2).should be_false
156
+ defined?(Foo3).should be_false
157
+ Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
158
+ new_class('Foo1')
159
+ new_class('Foo2', 'Foo1')
160
+ new_class('Foo3')
161
+ assert_valid_logger('Foo1', "root::Foo1")
162
+ assert_valid_logger('Foo2', "root::Foo1::Foo2")
163
+ defined?(Foo3.logger).should be_false
164
+ end
165
+
166
+ it "should register loggers for sub-subclasses of registered classes" do
167
+ defined?(Foo1).should be_false
168
+ defined?(Foo2).should be_false
169
+ defined?(Foo3).should be_false
170
+ Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
171
+ new_class('Foo1')
172
+ new_class('Foo2', 'Foo1')
173
+ new_class('Foo3', 'Foo2')
174
+ assert_valid_logger('Foo1', "root::Foo1")
175
+ assert_valid_logger('Foo2', "root::Foo1::Foo2")
176
+ assert_valid_logger('Foo3', "root::Foo1::Foo3")
177
+ end
178
+
179
+ it "should register loggers for sub-subclasses of registered classes even when middle class not a logger" do
180
+ defined?(Foo1).should be_false
181
+ defined?(Foo2).should be_false
182
+ defined?(Foo3).should be_false
183
+ new_class('Foo1')
184
+ new_class('Foo2', 'Foo1')
185
+ Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
186
+ new_class('Foo3', 'Foo2')
187
+ assert_valid_logger('Foo1', "root::Foo1")
188
+ assert_valid_logger('Foo3', "root::Foo1::Foo3")
189
+ assert_valid_logger('Foo2', "root::Foo1::Foo2")
190
+ end
139
191
 
140
- it "should register loggers for sub-subclasses of registered classes even when middle class not a logger" do
141
- defined?(Foo1).should be_false
142
- defined?(Foo2).should be_false
143
- defined?(Foo3).should be_false
144
- new_class('Foo1')
145
- new_class('Foo2', 'Foo1')
146
- Lumber.setup_logger_hierarchy("Foo1", "root::Foo1")
147
- new_class('Foo3', 'Foo2')
148
- assert_valid_logger('Foo1', "root::Foo1")
149
- # this will behave differently depending on the version of ActiveSupport being used. on ActiveSupport >= 3.2, we use class_attribute to define
150
- # the logger method, which will cause subclasses to fall back to the parent class's logger if one isn't defined (Foo2.logger == Foo1.logger)
151
- # if on ActiveSupport < 3.2, we use class_inheritable_accessor, which will leave the logger undefined in the subclass unless LoggerSupport
152
- # is explicitly included
153
- ((!defined?(Foo2.logger) || Foo2.logger.nil?) || (Foo2.logger == Foo1.logger)).should be_true
154
- assert_valid_logger('Foo3', "root::Foo1::Foo3")
155
192
  end
156
193
 
157
194
  context "formatted MDC context" do
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lumber::PreventRailsOverride do
4
+
5
+ it "should prevent cattr_accessor for :logger" do
6
+ new_class('Foo1')
7
+ Foo1.send(:include, Lumber::PreventRailsOverride)
8
+ Foo1.class_eval do
9
+ cattr_accessor :logger
10
+ end
11
+ defined?(Foo1.logger).should be_false
12
+ end
13
+
14
+ it "should allow cattr_accessor for attrs other than :logger" do
15
+ new_class('Foo1')
16
+ Foo1.send(:include, Lumber::PreventRailsOverride)
17
+ Foo1.class_eval do
18
+ cattr_accessor :foo
19
+ end
20
+ defined?(Foo1.foo).should be_true
21
+ end
22
+
23
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  ENV['RACK_ENV'] = 'test'
2
2
 
3
- if ENV['CI']
3
+ # coveralls+rspec+java causes exit code of 1 even when specs pass
4
+ if ENV['CI'] && RUBY_ENGINE != 'jruby'
4
5
  require 'coveralls'
5
6
  Coveralls.wear!
6
7
  end
@@ -24,3 +25,30 @@ include Lumber
24
25
  require 'capybara/rspec'
25
26
  require 'capybara/poltergeist'
26
27
  Capybara.javascript_driver = :poltergeist
28
+
29
+ def new_class(class_name, super_class=nil, super_module=nil)
30
+ s = "class #{class_name}"
31
+ s << " < #{super_class}" if super_class
32
+ s << "; end"
33
+
34
+ s = "module #{super_module}; #{s}; end" if super_module
35
+
36
+ eval s
37
+ end
38
+
39
+ def assert_valid_logger(class_name, logger_name)
40
+ clazz = eval class_name
41
+ clazz.should_not be_nil
42
+ clazz.respond_to?(:logger).should be_true
43
+ lgr = clazz.logger
44
+ lgr.should be_an_instance_of(Log4r::Logger)
45
+ lgr.fullname.should == logger_name
46
+ end
47
+
48
+ RSpec.configure do |config|
49
+ config.before(:each) do
50
+ Object.constants.grep(/^(Foo|Bar)/).each do |c|
51
+ Object.send(:remove_const, c)
52
+ end
53
+ end
54
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Conway
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-11 00:00:00.000000000 Z
11
+ date: 2013-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: log4r
@@ -171,15 +171,16 @@ files:
171
171
  - README.md
172
172
  - Rakefile
173
173
  - TODO
174
- - generators/lumber/USAGE
175
- - generators/lumber/lumber_generator.rb
176
- - generators/lumber/templates/log4r.yml
174
+ - lib/generators/lumber/lumber_generator.rb
175
+ - lib/generators/lumber/templates/log4r.yml
177
176
  - lib/lumber.rb
177
+ - lib/lumber/inheritance_registry.rb
178
178
  - lib/lumber/json_formatter.rb
179
179
  - lib/lumber/level_util.rb
180
180
  - lib/lumber/log4r.rb
181
181
  - lib/lumber/logger_support.rb
182
182
  - lib/lumber/lumber.rb
183
+ - lib/lumber/prevent_rails_override.rb
183
184
  - lib/lumber/railtie.rb
184
185
  - lib/lumber/server.rb
185
186
  - lib/lumber/server/public/lib/bootstrap/css/bootstrap-responsive.css
@@ -196,10 +197,12 @@ files:
196
197
  - lib/lumber/server/views/levels.erb
197
198
  - lib/lumber/version.rb
198
199
  - lumber.gemspec
200
+ - spec/inheritance_registry_spec.rb
199
201
  - spec/json_formatter_spec.rb
200
202
  - spec/level_util_spec.rb
201
203
  - spec/logger_support_spec.rb
202
204
  - spec/lumber_spec.rb
205
+ - spec/prevent_rails_override_spec.rb
203
206
  - spec/server_spec.rb
204
207
  - spec/spec.opts
205
208
  - spec/spec_helper.rb
@@ -228,10 +231,12 @@ signing_key:
228
231
  specification_version: 4
229
232
  summary: Lumber integrates the log4r logging system within your application.
230
233
  test_files:
234
+ - spec/inheritance_registry_spec.rb
231
235
  - spec/json_formatter_spec.rb
232
236
  - spec/level_util_spec.rb
233
237
  - spec/logger_support_spec.rb
234
238
  - spec/lumber_spec.rb
239
+ - spec/prevent_rails_override_spec.rb
235
240
  - spec/server_spec.rb
236
241
  - spec/spec.opts
237
242
  - spec/spec_helper.rb
@@ -1,5 +0,0 @@
1
- Description:
2
- Prepares the rails application for using log4 by installing sample configuration
3
-
4
- Examples:
5
- ./script/generate lumber
@@ -1,19 +0,0 @@
1
- require 'fileutils'
2
- require 'find'
3
-
4
- class LumberGenerator < Rails::Generator::Base
5
-
6
- def manifest
7
- record do |m|
8
- m.file('log4r.yml', 'config/log4r.yml')
9
- end
10
- end
11
-
12
- protected
13
-
14
- def banner
15
- usage = "Usage: #{$0} lumber\n"
16
- usage << " Install configuration files for lumber\n"
17
- return usage
18
- end
19
- end