catamaran 0.4.0 → 0.5.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ce160eae2640b8c7d690d9677b5440892b48dae1
4
+ data.tar.gz: 70e6fe894ef0216d45e5e0f837b94deb9a912b20
5
+ SHA512:
6
+ metadata.gz: a4ce49087602bed11ca7f627291829af5561ec6b21b0c46a1f7effac2b2f59ec8c1e34ad18ecc5e83e973c76e08b47efca2077fd55f2fe6685b9c84ea8a3c8b7
7
+ data.tar.gz: 3e4a99d0e26290c1be952b84d3acdc7a4847885acc3192184133dd8cff07b269f036a82d137c29f5172fd49b3f94b24dbd1ae3656fd5a07a294af8ac1b41f127
data/README.md CHANGED
@@ -1,18 +1,18 @@
1
1
  Catamaran
2
2
  =========
3
3
 
4
- I think logging is a powerful and often undervalued tool in software development. When done right, it's a great way to document code, and it provides a simple & effective way to solve problems when things go awry. All an important part of maintainable code.
4
+ Logging is a powerful and often undervalued tool in software development. When done right, it's a great way to document code, and it provides a simple & effective way to solve problems when things go awry. All an important part of maintainable code.
5
5
 
6
6
  Gemfile
7
7
  -------
8
8
 
9
- gem 'catamaran', '~> 0.3.0'
9
+ gem 'catamaran', '~> 0.4.0'
10
10
 
11
11
  Rails-related setup:
12
12
 
13
13
  rails g catamaran:install
14
14
 
15
- Now modify `development.rb` as needed
15
+ Now modify `config/initializers/catamaran/development.rb` as needed
16
16
 
17
17
  Ruby Quickstart
18
18
  ---------------
@@ -63,7 +63,7 @@ Load the `index` page and check out your `development.log` file
63
63
  Other Ruby Examples
64
64
  -------------------
65
65
  require 'catamaran'
66
-
66
+
67
67
  Catamaran::LogLevel.default_log_level = Catamaran::LogLevel::DEBUG
68
68
  Catamaran::Manager.formatter_class = Catamaran::Formatter::NoCallerFormatter
69
69
 
@@ -107,11 +107,14 @@ I'm looking for a logging utility that:
107
107
 
108
108
  Performance Considerations
109
109
  --------------------------
110
+
111
+ ### With or without `if LOGGER.debug?`
110
112
  require 'catamaran'
111
113
  require 'benchmark'
112
114
 
113
115
  Catamaran::LogLevel.default_log_level = Catamaran::LogLevel::INFO
114
116
  Catamaran::Manager.formatter_class = Catamaran::Formatter::NoCallerFormatter
117
+ Catamaran::Manager.stderr = false
115
118
 
116
119
  class CatamaranPerformanceTest
117
120
  LOGGER = Catamaran.logger( "CatamaranPerformanceTest" )
@@ -123,12 +126,12 @@ Performance Considerations
123
126
  Benchmark.bm(7) do |x|
124
127
  x.report("warn WITHOUT if LOGGER.warn? ") {
125
128
  n.times do |i|
126
- LOGGER.warn "This is a WARN"
129
+ LOGGER.warn "Based on the current log level, this log is being captured"
127
130
  end
128
131
  }
129
132
  x.report("warn WITH if LOGGER.warn? ") {
130
133
  n.times do |i|
131
- LOGGER.warn "This is a WARN" if LOGGER.warn?
134
+ LOGGER.warn "Based on the current log level, this log is being captured" if LOGGER.warn?
132
135
  end
133
136
  }
134
137
  end
@@ -136,26 +139,91 @@ Performance Considerations
136
139
  Benchmark.bm(7) do |x|
137
140
  x.report("debug WITHOUT if LOGGER.debug?") {
138
141
  n.times do |i|
139
- LOGGER.debug "This is a DEBUG"
142
+ LOGGER.debug "Based on the current log level, this log is NOT being captured"
140
143
  end
141
144
  }
142
145
  x.report("debug WITH if LOGGER.debug? ") {
143
146
  n.times do |i|
144
- LOGGER.debug "This is a DEBUG" if LOGGER.debug?
147
+ LOGGER.debug "Based on the current log level, this log is NOT being captured" if LOGGER.debug?
145
148
  end
146
149
  }
147
150
  end
148
151
 
149
152
  end
150
153
 
151
-
152
154
  # user system total real
153
- # warn WITHOUT if LOGGER.warn? 6.520000 0.020000 6.540000 ( 6.533741)
154
- # warn WITH if LOGGER.warn? 7.110000 0.020000 7.130000 ( 7.129708)
155
+ # warn WITHOUT if LOGGER.warn? 6.940000 0.010000 6.950000 ( 6.950691)
156
+ # warn WITH if LOGGER.warn? 7.650000 0.000000 7.650000 ( 7.658004)
155
157
  # user system total real
156
- # debug WITHOUT if LOGGER.debug? 0.610000 0.010000 0.620000 ( 0.623714)
157
- # debug WITH if LOGGER.debug? 0.530000 0.010000 0.540000 ( 0.544295)
158
+ # debug WITHOUT if LOGGER.debug? 0.660000 0.010000 0.670000 ( 0.665775)
159
+ # debug WITH if LOGGER.debug? 0.560000 0.010000 0.570000 ( 0.574397)
160
+
161
+ #### Summary
162
+
163
+ * For log messages that are usually *disabled* in the production environment ( TRACE, DEBUG ), it's generally better to invoke the log only after confirming that the log level is enabled
164
+
165
+ ex:
166
+
167
+ LOGGER.trace "This is a TRACE log" if LOGGER.trace?
168
+ LOGGER.debug "This is a DEBUG log" if LOGGER.debug?
169
+
170
+ * For log messages that are usually *enabled* in the production environment ( INFO, WARN, ERROR, SEVERE ), it's generally better to invoke the log WITHOUT first testing the log level
171
+
172
+ ex:
173
+
174
+ LOGGER.info "This is a INFO log"
175
+ LOGGER.warn "This is a WARN log"
176
+ LOGGER.error "This is a ERROR log"
177
+
178
+ ### NoCallerFormatter vs CallerFormatter
179
+
180
+ require 'catamaran'
181
+ require 'benchmark'
182
+
183
+ Catamaran::LogLevel.default_log_level = Catamaran::LogLevel::INFO
184
+ Catamaran::Manager.stderr = false
185
+
186
+ class CatamaranPerformanceTest
187
+ LOGGER = Catamaran.logger( "CatamaranPerformanceTest" )
188
+
189
+ n = 500000
190
+ Benchmark.bm(7) do |x|
191
+ Catamaran::Manager.formatter_class = Catamaran::Formatter::NoCallerFormatter
192
+
193
+ x.report("Using NoCallerFormatter") {
194
+ n.times do |i|
195
+ LOGGER.error "This is a ERROR log"
196
+ end
197
+ }
198
+
199
+ Catamaran::Manager.formatter_class = Catamaran::Formatter::CallerFormatter
200
+
201
+ x.report("Using CallerFormatter") {
202
+ n.times do |i|
203
+ LOGGER.error "This is a ERROR log"
204
+ end
205
+ }
206
+ end
207
+ end
208
+
209
+
210
+ # user system total real
211
+ # Using NoCallerFormatter 6.850000 0.010000 6.860000 ( 6.864649)
212
+ # Using CallerFormatter 14.700000 0.150000 14.850000 ( 14.867592)
213
+
214
+ #### Summary
215
+
216
+ `CallerFormatter` is slower but contains more details in the log statements as compared to `NoCallerFormatter`
217
+
218
+ ##### Sample log from NoCallerFormatter
219
+
220
+ WARN pid-4407 [2013-12-26 14:18:19:697] FirstRubyDemo - Note that WARN messages are getting logged
221
+
222
+ ##### Sample log from CallerFormatter
223
+
224
+ WARN pid-4410 [2013-12-26 14:18:38:276] FirstRubyDemo - Note that WARN messages are getting logged (catamaran_ruby_demos.rb:12:in `run')
158
225
 
226
+ Because of this performance difference, `NoCallerFormatter` is the Catamaran default. Though `CallerFormatter` tends to be especially useful in the development and test environments when debugging problems during the course of functional testing.
159
227
 
160
228
 
161
229
  Ideas around what's next
@@ -297,11 +297,66 @@ module Catamaran
297
297
  retval
298
298
  end
299
299
 
300
- def reset
301
- _reset()
302
- Catamaran.debugging( "Catamaran::Logger#reset() - Reset complete." ) if Catamaran.debugging?
300
+
301
+ ##
302
+ # I used to delete the root level logger, but now I reset it instead.
303
+ # Among other reasons, the CatLogger constant now works
304
+
305
+ def reset( opts = {} )
306
+ remove_instance_variable(:@memoized_log_level) if instance_variable_defined?( :@memoized_log_level )
307
+ remove_instance_variable(:@log_level) if instance_variable_defined?( :@log_level )
308
+
309
+ self.name = @initialized_name
310
+ self.path = @initialized_path_so_far ? @initialized_path_so_far.dup : []
311
+
312
+ if @initialized_name && @initialized_name.length > 0 # Root logger has no name
313
+ self.path << @initialized_name
314
+ end
315
+
316
+ @parent = @initialized_parent
317
+
318
+
319
+
320
+ if opts[:hard_reset]
321
+ ##
322
+ # Hard reset - delete the sub-loggers by removing references to them
323
+
324
+ # @sub_loggers already exist, iterate through each and undefine the associated method missing
325
+ @sub_loggers.keys.each do |method_name_as_symbol|
326
+ Catamaran.debugging( "Catamaran::Logger#reset() - Attempting to remove dynamically created method: #{method_name_as_symbol}" ) if Catamaran.debugging?
327
+ singleton = class << self; self end
328
+ singleton.send :remove_method, method_name_as_symbol
329
+ end if @sub_loggers
330
+
331
+ @sub_loggers = {}
332
+ Catamaran.debugging( "Catamaran::Logger#reset() - Hard reset complete for #{self}." ) if Catamaran.debugging?
333
+ else
334
+ ##
335
+ # Soft reset - reset each of the sub-loggers
336
+
337
+ # @sub_loggers already exist, iterate through each and reset them
338
+ @sub_loggers.values.each do |logger|
339
+ logger.reset()
340
+ end if @sub_loggers
341
+ Catamaran.debugging( "Catamaran::Logger#reset() - Soft reset complete for #{self}." ) if Catamaran.debugging?
342
+ end
343
+ end
344
+
345
+ def soft_reset( opts = {} )
346
+ # This is a soft reset
347
+ opts = opts.dup
348
+ opts[:hard_reset] = false
349
+ reset( opts )
303
350
  end
304
351
 
352
+ def hard_reset( opts = {} )
353
+ # This is a hard reset
354
+ opts = opts.dup
355
+ opts[:hard_reset] = true
356
+ reset( opts )
357
+ end
358
+
359
+
305
360
  def depth
306
361
  @depth
307
362
  end
@@ -345,35 +400,6 @@ module Catamaran
345
400
 
346
401
  private
347
402
 
348
- ##
349
- # I used to delete the root level logger, but now I reset it instead.
350
- # Among other reasons, the CatLogger constant now works
351
-
352
- def _reset
353
- remove_instance_variable(:@memoized_log_level) if instance_variable_defined?( :@memoized_log_level )
354
- remove_instance_variable(:@log_level) if instance_variable_defined?( :@log_level )
355
-
356
- self.name = @initialized_name
357
- self.path = @initialized_path_so_far ? @initialized_path_so_far.dup : []
358
-
359
- if @initialized_name && @initialized_name.length > 0 # Root logger has no name
360
- self.path << @initialized_name
361
- end
362
-
363
- @parent = @initialized_parent
364
-
365
- # @sub_loggers already exist, iterate through each and undefine the associated method missing
366
- if @sub_loggers
367
- @sub_loggers.keys.each do |method_name_as_symbol|
368
- Catamaran.debugging( "Catamaran::Logger#_reset() - Attempting to remove dynamically created method: #{method_name_as_symbol}" ) if Catamaran.debugging?
369
-
370
- singleton = class << self; self end
371
- singleton.send :remove_method, method_name_as_symbol
372
- end
373
- end
374
-
375
- @sub_loggers = {}
376
- end
377
403
 
378
404
  ##
379
405
  # All log statements eventually call _write_to_log
@@ -405,7 +431,10 @@ module Catamaran
405
431
  @depth = 0
406
432
  end
407
433
 
408
- _reset()
434
+ # Create the hash of sub_loggers as needed
435
+ @sub_loggers ||= {}
436
+
437
+ reset()
409
438
 
410
439
  Catamaran.debugging( "Catamaran::Logger#initialize() - I am #{self.to_s}" ) if Catamaran.debugging?
411
440
  end
@@ -37,15 +37,15 @@ module Catamaran
37
37
  ##
38
38
  # Used to reset Catamaran
39
39
 
40
- def self.reset
41
- Catamaran.debugging( "Catamaran::Manager#reset - Resetting Catamaran" ) if Catamaran.debugging?
40
+ def self.reset( opts = {} )
41
+ Catamaran.debugging( "Catamaran::Manager#reset - Resetting Catamaran with opts = #{opts}" ) if Catamaran.debugging?
42
42
 
43
43
  # Old way. I used to null-out the old logger. But resetting it is better for using the CatLogger constant
44
44
  # self.send( :_root_logger_instance=, nil )
45
45
 
46
46
  # New way
47
47
  root_logger = self.send( :_root_logger_instance )
48
- root_logger.reset if root_logger
48
+ root_logger.reset( opts ) if root_logger
49
49
 
50
50
  # Also reset the default log level
51
51
  Catamaran::LogLevel::reset
@@ -56,6 +56,15 @@ module Catamaran
56
56
  # self.send( :_output_files=, nil )
57
57
  end
58
58
 
59
+ def self.hard_reset( opts = {} )
60
+ opts = opts.dup
61
+ opts[:hard_reset] = true
62
+ self.reset( opts )
63
+ end
64
+
65
+
66
+
67
+
59
68
  ##
60
69
  # Allow the client to access the root logger
61
70
 
@@ -1,4 +1,4 @@
1
1
  module Catamaran
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
4
4
 
@@ -39,8 +39,9 @@ describe Catamaran do
39
39
  it "should provide access to loggers after a reset" do
40
40
  logger = Catamaran.logger.Company.Product.App.Model.User
41
41
  Catamaran::Manager.reset
42
- logger = Catamaran.logger.Company.Product.App.Model.User
43
- logger.should be_instance_of( Catamaran::Logger )
42
+ logger2 = Catamaran.logger.Company.Product.App.Model.User
43
+ logger2.should be_instance_of( Catamaran::Logger )
44
+ logger2.object_id.should == logger.object_id
44
45
  end
45
46
 
46
47
  it "should create a new loggers for each point in the path" do
@@ -92,7 +93,7 @@ describe Catamaran do
92
93
  Catamaran.logger.Company.Product.App.Model.User
93
94
  end
94
95
 
95
- context "after a reset" do
96
+ context "after a (soft) reset" do
96
97
  it "should have a default log level of INFO" do
97
98
  logger = Catamaran.logger
98
99
  logger.log_level.should == Catamaran::LogLevel::INFO
@@ -102,13 +103,13 @@ describe Catamaran do
102
103
  logger.log_level.should == Catamaran::LogLevel::INFO
103
104
  end
104
105
 
105
- it "should return the number of loggers to 1" do
106
+ it "should keep the number of loggers unchanged" do
106
107
  Catamaran.logger
107
108
  Catamaran::Manager.num_loggers.should == 1
108
109
  Catamaran.logger.Company.Product.App.Model.User
109
110
  Catamaran::Manager.num_loggers.should == 6
110
111
  Catamaran::Manager.reset
111
- Catamaran::Manager.num_loggers.should == 1
112
+ Catamaran::Manager.num_loggers.should == 6
112
113
  end
113
114
 
114
115
  it "should have the same root logger object before and after the reset" do
@@ -116,6 +117,44 @@ describe Catamaran do
116
117
  Catamaran::Manager.reset
117
118
  Catamaran.logger.object_id.should == before_logger.object_id
118
119
  end
120
+
121
+ it "should reuse the same logger non-root logger instance" do
122
+ before_logger = Catamaran.logger.Company.Product.App.Model.User
123
+ Catamaran::Manager.reset
124
+ before_logger.object_id.should == Catamaran.logger.Company.Product.App.Model.User.object_id
125
+ end
126
+ end
127
+
128
+ context "after a hard reset" do
129
+ it "should have a default log level of INFO" do
130
+ logger = Catamaran.logger
131
+ logger.log_level.should == Catamaran::LogLevel::INFO
132
+ logger.log_level = Catamaran::LogLevel::ERROR
133
+ logger.log_level.should == Catamaran::LogLevel::ERROR
134
+ Catamaran::Manager.hard_reset
135
+ logger.log_level.should == Catamaran::LogLevel::INFO
136
+ end
137
+
138
+ it "should reset the number of loggers to 1" do
139
+ Catamaran.logger
140
+ Catamaran::Manager.num_loggers.should == 1
141
+ Catamaran.logger.Company.Product.App.Model.User
142
+ Catamaran::Manager.num_loggers.should == 6
143
+ Catamaran::Manager.hard_reset
144
+ Catamaran::Manager.num_loggers.should == 1
145
+ end
146
+
147
+ it "should have the same root logger object before and after the reset" do
148
+ before_logger = Catamaran.logger
149
+ Catamaran::Manager.hard_reset
150
+ Catamaran.logger.object_id.should == before_logger.object_id
151
+ end
152
+
153
+ it "should NOT reuse the same non-root logger instance" do
154
+ before_logger = Catamaran.logger.Company.Product.App.Model.User
155
+ Catamaran::Manager.hard_reset
156
+ before_logger.object_id.should_not == Catamaran.logger.Company.Product.App.Model.User.object_id
157
+ end
119
158
  end
120
159
 
121
160
  describe Catamaran.logger do
@@ -127,13 +166,10 @@ describe Catamaran do
127
166
 
128
167
  describe Catamaran::Manager do
129
168
  describe "#reset" do
130
- it "should reset Catamaran" do
131
- before_reset_logger = Catamaran.logger.Company.Product.App.Model.User
132
- Catamaran.logger.num_loggers.should == 6
169
+ it "should call reset on the root logger" do
170
+ root_logger = Catamaran.logger
171
+ root_logger.should_receive( :reset ).once
133
172
  Catamaran::Manager.reset
134
- Catamaran.logger.num_loggers.should == 1
135
- after_reset_logger = Catamaran.logger.Company.Product.App.Model.User
136
- before_reset_logger.object_id.should_not == after_reset_logger.object_id
137
173
  end
138
174
  end
139
175
 
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,6 @@ RSpec.configure do |config|
5
5
  end
6
6
 
7
7
  config.before(:each) do
8
- Catamaran::Manager.reset
8
+ Catamaran::Manager.hard_reset
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,28 +1,22 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: catamaran
3
- version: !ruby/object:Gem::Version
4
- version: 0.4.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Jeano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2013-12-26 00:00:00 -06:00
13
- default_executable:
11
+ date: 2013-12-26 00:00:00.000000000 Z
14
12
  dependencies: []
15
-
16
13
  description: A logging utility
17
- email:
14
+ email:
18
15
  - catamaran@jeano.net
19
16
  executables: []
20
-
21
17
  extensions: []
22
-
23
18
  extra_rdoc_files: []
24
-
25
- files:
19
+ files:
26
20
  - .gitignore
27
21
  - README.md
28
22
  - catamaran.gemspec
@@ -46,33 +40,27 @@ files:
46
40
  - lib/generators/catamaran/templates/catamaran/test.rb
47
41
  - spec/catamaran_spec.rb
48
42
  - spec/spec_helper.rb
49
- has_rdoc: true
50
43
  homepage: http://github.com/jgithub/catamaran
51
44
  licenses: []
52
-
45
+ metadata: {}
53
46
  post_install_message:
54
47
  rdoc_options: []
55
-
56
- require_paths:
48
+ require_paths:
57
49
  - lib
58
- required_ruby_version: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: "0"
63
- version:
64
- required_rubygems_version: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: "0"
69
- version:
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
70
60
  requirements: []
71
-
72
61
  rubyforge_project:
73
- rubygems_version: 1.3.5
62
+ rubygems_version: 2.0.3
74
63
  signing_key:
75
- specification_version: 3
64
+ specification_version: 4
76
65
  summary: Catamaran Logger
77
66
  test_files: []
78
-