lumber 1.0.3 → 1.1.0

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