catamaran 0.2.0 → 0.3.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.
data/README.md CHANGED
@@ -6,7 +6,7 @@ I think logging is a powerful and often undervalued tool in software development
6
6
  Gemfile
7
7
  -------
8
8
 
9
- gem 'catamaran', :git => 'git://github.com/jgithub/catamaran.git'
9
+ gem 'catamaran', '~> 0.2.0'
10
10
 
11
11
  Rails-related setup:
12
12
 
@@ -14,11 +14,56 @@ Rails-related setup:
14
14
 
15
15
  Now modify `development.rb` as needed
16
16
 
17
- Quickstart coding
18
- -----------------
17
+ Ruby Quickstart
18
+ -------------------------------
19
+ Catamaran::Manager.stderr = true
20
+ Catamaran::LogLevel.default_log_level = Catamaran::LogLevel::DEBUG
21
+ Catamaran::Manager.formatter_class = Catamaran::Formatter::NoCallerFormatter
19
22
 
20
- class WelcomeController < ApplicationController
21
- LOGGER = CatLogger.MyCompany.MyAppName.App.Controller.WelcomeController
23
+ class FirstRubyDemo
24
+ LOGGER = Catamaran.logger( "FirstRubyDemo" )
25
+
26
+ def run
27
+ LOGGER.debug( "Note that DEBUG messages are getting logged" ) if LOGGER.debug?
28
+ LOGGER.trace( "Note that TRACE messages are NOT getting logged" ) if LOGGER.trace?
29
+ end
30
+ end
31
+
32
+ class SecondRubyDemo
33
+ LOGGER = Catamaran.logger( { :class => name(), :file => __FILE__ } )
34
+
35
+ def run
36
+ LOGGER.debug( "Sample DEBUG statement", { :line => __LINE__, :method => 'run'} ) if LOGGER.debug?
37
+ end
38
+ end
39
+
40
+ class ThirdRubyDemo
41
+ LOGGER = Catamaran.logger( "com.mycompany.ThirdRubyDemo", { :class => name(), :file => __FILE__ } )
42
+
43
+ def run
44
+ LOGGER.debug( "Sample DEBUG statement", { :line => __LINE__, :method => 'run'} ) if LOGGER.debug?
45
+ end
46
+ end
47
+
48
+
49
+ puts "Catamaran VERSION = #{Catamaran::VERSION}"
50
+ FirstRubyDemo.new.run
51
+ SecondRubyDemo.new.run
52
+ ThirdRubyDemo.new.run
53
+
54
+ And the output
55
+
56
+ Catamaran VERSION = 0.3.0
57
+ DEBUG pid-2729 [2013-12-23 19:35:35:732] FirstRubyDemo - Note that DEBUG messages are getting logged
58
+ DEBUG pid-2729 [2013-12-23 19:35:35:732] - Sample DEBUG statement (catmaran_ruby_demos.rb:21:in `SecondRubyDemo.run')
59
+ DEBUG pid-2729 [2013-12-23 19:35:35:732] com.mycompany.ThirdRubyDemo - Sample DEBUG statement (catmaran_ruby_demos.rb:29:in `ThirdRubyDemo.run')
60
+
61
+
62
+ Rails Quickstart
63
+ --------------------------------
64
+
65
+ class PagesController < ApplicationController
66
+ LOGGER = Catamaran.logger.com.mycompany.myrailsapp.app.controllers.PagesController
22
67
 
23
68
  def index
24
69
  # LOGGER.io methods are reserved for logs related to entering and returning from methods
@@ -36,9 +81,10 @@ Quickstart coding
36
81
 
37
82
  Load the `index` page and check out your `development.log` file
38
83
 
39
- Sample log entry (in your development.log file)
40
- -----------------------------------------------
41
- IO pid-86000 [2013-12-17 17:26:39:176] MyAppName.App.Controller.WelcomeController - Entering with params = {"controller"=>"welcome", "action"=>"index"} (`/my_rails_project/app/controllers/welcome_controller.rb:7`:in `index`)
84
+ ### Sample log entry (in your development.log file)
85
+ IO pid-86000 [2013-12-17 17:26:39:176] pany.myrailsapp.app.controllers.PagesController - Entering with params = {"controller"=>"pages", "action"=>"index"} (`/myrailsapp/app/controllers/pages_controller.rb:7`:in `index`)
86
+
87
+
42
88
 
43
89
  Inspiration
44
90
  -----------
@@ -0,0 +1,68 @@
1
+ module Catamaran
2
+ module Formatter
3
+ ##
4
+ # Construct a properly formatted log message based
5
+
6
+ class BaseFormatter
7
+ def self.base_construct_formatted_message( log_level, path, msg, opts )
8
+ # Truncate on the left
9
+ if path.length > 47
10
+ updated_path = path.dup[-47,47]
11
+ else
12
+ updated_path = path
13
+ end
14
+
15
+ # TODO: Abstract out the logger so that it's easy to use different formats
16
+ # Implicit return
17
+ retval = sprintf( "%6s pid-#{Process.pid} [#{Time.now.strftime( "%G-%m-%d %H:%M:%S:%L" )}] %47s - #{msg}", LogLevel.to_s(log_level), updated_path )
18
+ end
19
+
20
+
21
+ def self.contruct_suffix_info( opts )
22
+ msg = ''
23
+
24
+ if opts
25
+ if opts[:file]
26
+ msg << "(#{opts[:file]}"
27
+
28
+ if opts[:line]
29
+ msg << ":#{opts[:line]}"
30
+ end
31
+
32
+ if opts[:class] || opts[:method]
33
+ msg << ":in `"
34
+
35
+ msg << construct_class_method_info( opts )
36
+
37
+ msg << "'"
38
+ end
39
+
40
+ msg << ')'
41
+ end
42
+ end
43
+
44
+ # Implicit return
45
+ msg
46
+ end
47
+
48
+
49
+ def self.construct_class_method_info( opts )
50
+ msg = ''
51
+ if opts
52
+ if opts[:class] || opts[:method]
53
+ if opts[:class]
54
+ msg << "#{opts[:class]}."
55
+ end
56
+
57
+ msg << "#{opts[:method]}" if opts[:method]
58
+ end
59
+ end
60
+
61
+ # Implicit Return
62
+ msg
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+
@@ -3,29 +3,9 @@ module Catamaran
3
3
  ##
4
4
  # Construct a properly formatted log message based
5
5
 
6
- class CallerFormatter
6
+ class CallerFormatter < BaseFormatter
7
7
  def self.construct_formatted_message( log_level, path, msg, opts )
8
-
9
- ##
10
- # If the client has specified a __FILE__ or a __LINE__ in the log opts, make use of them
11
-
12
- if opts
13
- if opts[:file] && opts[:line]
14
- path = path + " (#{opts[:file]}:#{opts[:line]})"
15
- end
16
- end
17
-
18
- # Truncate on the left
19
- if path.length > 42
20
- updated_path = path.dup[-42,42]
21
- else
22
- updated_path = path
23
- end
24
-
25
- # Making use of the caller here is slow.
26
- # TODO: Abstract out the logger so that it's easy to use different formats
27
- # Implicit return
28
- sprintf( "%6s pid-#{Process.pid} [#{Time.now.strftime( "%G-%m-%d %H:%M:%S:%L" )}] %42s - #{msg} (#{caller(3)[0]})", LogLevel.to_s(log_level), updated_path )
8
+ "#{base_construct_formatted_message( log_level, path, msg, opts )} (#{caller(3)[0]})"
29
9
  end
30
10
  end
31
11
  end
@@ -3,28 +3,14 @@ module Catamaran
3
3
  ##
4
4
  # Construct a properly formatted log message based
5
5
 
6
- class NoCallerFormatter
7
- def self.construct_formatted_message( log_level, path, msg, opts )
8
-
9
- ##
10
- # If the client has specified a __FILE__ or a __LINE__ in the log opts, make use of them
11
-
12
- if opts
13
- if opts[:file] && opts[:line]
14
- path = path + " (#{opts[:file]}:#{opts[:line]})"
15
- end
16
- end
17
-
18
- # Truncate on the left
19
- if path.length > 42
20
- updated_path = path.dup[-42,42]
6
+ class NoCallerFormatter < BaseFormatter
7
+ def self.construct_formatted_message( log_level, path, msg, opts )
8
+ suffix_info = contruct_suffix_info( opts )
9
+ if suffix_info && suffix_info.length > 0
10
+ base_construct_formatted_message( log_level, path, msg, opts ) + ' ' + suffix_info
21
11
  else
22
- updated_path = path
12
+ base_construct_formatted_message( log_level, path, msg, opts )
23
13
  end
24
-
25
- # TODO: Abstract out the logger so that it's easy to use different formats
26
- # Implicit return
27
- sprintf( "%6s pid-#{Process.pid} [#{Time.now.strftime( "%G-%m-%d %H:%M:%S:%L" )}] %42s - #{msg}", LogLevel.to_s(log_level), updated_path )
28
14
  end
29
15
  end
30
16
  end
@@ -3,6 +3,8 @@ module Catamaran
3
3
  attr_accessor :name
4
4
  attr_accessor :path
5
5
  attr_reader :parent
6
+ attr_reader :specified_file
7
+ attr_reader :specified_class
6
8
 
7
9
  ##
8
10
  # The getter associated with retrieving the current log level for this logger.
@@ -190,8 +192,13 @@ module Catamaran
190
192
  ##
191
193
  # Usually get_logger is a reference to self, unless a path has been specified as a parameter
192
194
 
193
- def get_logger( path = nil )
195
+ def get_logger( *args )
194
196
  current_logger = self
197
+
198
+ path, opts = determine_path_and_opts_arguments( *args )
199
+ Catamaran.debugging( "Catamaran::Logger#get_logger() - path = '#{path}' opts = #{opts} from args = #{args}" ) if Catamaran.debugging?
200
+
201
+
195
202
  if path
196
203
  method_names = path.split(/\./)
197
204
 
@@ -200,6 +207,16 @@ module Catamaran
200
207
  end
201
208
  end
202
209
 
210
+ if opts
211
+ if opts[:file]
212
+ current_logger.instance_variable_set( :@specified_file, opts[:file] )
213
+ end
214
+
215
+ if opts[:class]
216
+ current_logger.instance_variable_set( :@specified_class, opts[:class] )
217
+ end
218
+ end
219
+
203
220
  # Implicit return
204
221
  current_logger
205
222
  end
@@ -247,7 +264,7 @@ module Catamaran
247
264
  _path = self.path
248
265
  if _path
249
266
  # Implicit return
250
- _path.join( delimiter )
267
+ _path.join( Catamaran::Manager.delimiter )
251
268
  else
252
269
  # Implicit return
253
270
  nil
@@ -294,6 +311,38 @@ module Catamaran
294
311
  "#<#{self.class}:0x#{object_id.to_s(16)}>[name=#{self.name},path=#{path_to_s},depth=#{self.depth},log_level=#{@log_level}]"
295
312
  end
296
313
 
314
+ protected
315
+
316
+ def determine_path_and_opts_arguments( *args )
317
+ Catamaran.debugging( "Catamaran::Logger#reset() - Entering with args = #{args}" ) if Catamaran.debugging?
318
+
319
+ if ( args.length == 0 )
320
+ opts = nil
321
+ path = nil
322
+ elsif ( args.length == 1 )
323
+ argument1 = args[0]
324
+
325
+ if ( argument1.nil? )
326
+ path = nil
327
+ opts = nil
328
+ elsif ( argument1.kind_of?( String ) )
329
+ path = argument1
330
+ opts = nil
331
+ elsif ( argument1.kind_of?( Hash ) )
332
+ path = nil
333
+ opts = argument1
334
+ else
335
+ raise ArgumentError.new "Unsupported argument type"
336
+ end
337
+ elsif ( args.length == 2 )
338
+ path, opts = *args
339
+ else
340
+ raise ArgumentError.new "Unexpected number of arguments: #{args.length}"
341
+ end
342
+
343
+ [ path, opts ]
344
+ end
345
+
297
346
  private
298
347
 
299
348
  ##
@@ -330,6 +379,12 @@ module Catamaran
330
379
  # All log statements eventually call _write_to_log
331
380
 
332
381
  def _write_to_log( log_level, msg, opts )
382
+ if self.specified_file || self.specified_class
383
+ opts = {} unless opts
384
+ opts[:file] = self.specified_file if self.specified_file
385
+ opts[:class] = self.specified_class if self.specified_class
386
+ end
387
+
333
388
  formatted_msg = Manager.formatter_class.construct_formatted_message( log_level, self.path_to_s(), msg, opts )
334
389
  Outputter.write( formatted_msg )
335
390
  end
@@ -355,12 +410,5 @@ module Catamaran
355
410
  Catamaran.debugging( "Catamaran::Logger#initialize() - I am #{self.to_s}" ) if Catamaran.debugging?
356
411
  end
357
412
 
358
- ##
359
- # The delimiter is a period
360
-
361
- def delimiter
362
- "."
363
- end
364
-
365
413
  end
366
414
  end
@@ -18,9 +18,22 @@ module Catamaran
18
18
  def formatter_class=( value )
19
19
  @formatter_class = value
20
20
  end
21
+
22
+ ##
23
+ # The default delimiter
24
+ #
25
+ def delimiter
26
+ @delimiter || '.'
27
+ end
28
+
29
+ def delimiter=( value )
30
+ @delimiter = value
31
+ end
21
32
  end
22
33
 
23
34
 
35
+
36
+
24
37
  ##
25
38
  # Used to reset Catamaran
26
39
 
@@ -1,4 +1,4 @@
1
1
  module Catamaran
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
4
4
 
data/lib/catamaran.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'catamaran/logger'
2
2
  require 'catamaran/manager'
3
+ require 'catamaran/formatter/base_formatter'
3
4
  require 'catamaran/formatter/caller_formatter'
4
5
  require 'catamaran/formatter/no_caller_formatter'
5
6
  require 'catamaran/outputter'
@@ -22,8 +23,9 @@ module Catamaran
22
23
  @debugging = value
23
24
  end
24
25
 
25
- def self.logger( optional_string = nil )
26
- Catamaran::Manager.root_logger().get_logger( optional_string )
26
+ def self.logger( *args )
27
+ Catamaran.debugging( "Catamaran.logger() - Entering with args = #{args}" ) if Catamaran.debugging?
28
+ Catamaran::Manager.root_logger().get_logger( *args )
27
29
  end
28
30
 
29
31
  ##
@@ -13,8 +13,17 @@ describe Catamaran do
13
13
  Catamaran.logger.object_id.should == Catamaran.logger.object_id
14
14
  end
15
15
 
16
+ context "when working with a blank path" do
17
+ it "should reuse the same root logger instance" do
18
+ Catamaran.logger( '' ).object_id.should == Catamaran.logger.object_id
19
+ end
20
+ end
21
+
16
22
  it "should reuse the same logger instance when contextually the same" do
17
23
  Catamaran.logger.Company.Product.App.Model.User.object_id.should == Catamaran.logger.Company.Product.App.Model.User.object_id
24
+ end
25
+
26
+ it "should reuse the same logger instance when contextually the same regardless of if the logger was determined by a string or by sequential method calls" do
18
27
  Catamaran.logger( "Company.Product.App.Model.User" ).object_id.should == Catamaran.logger.Company.Product.App.Model.User.object_id
19
28
  end
20
29
 
@@ -169,6 +178,20 @@ describe Catamaran do
169
178
  Catamaran.logger.debug( "Testing a DEBUG log" )
170
179
  end
171
180
 
181
+ describe "#determine_path_and_opts_arguments" do
182
+ it "should return the correct path when one string parameter is specified" do
183
+ Catamaran.logger.send( :determine_path_and_opts_arguments, "Company.Product.App.Model.User" ).should == [ "Company.Product.App.Model.User", nil ]
184
+ end
185
+
186
+ it "should return the correct opts when one hash parameter is specified" do
187
+ Catamaran.logger.send( :determine_path_and_opts_arguments, {} ).should == [ nil, {} ]
188
+ end
189
+
190
+ it "should return the correct path and opts when two parameters are specified" do
191
+ Catamaran.logger.send( :determine_path_and_opts_arguments, "Company.Product.App.Model.User", {} ).should == [ "Company.Product.App.Model.User", {} ]
192
+ end
193
+ end
194
+
172
195
  context "when using smart_log_level" do
173
196
  it "should inherit the log level from a parent" do
174
197
  Catamaran::LogLevel.default_log_level = Catamaran::LogLevel::INFO
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: catamaran
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeano
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2013-12-20 00:00:00 -06:00
12
+ date: 2013-12-23 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -28,6 +28,7 @@ files:
28
28
  - catamaran.gemspec
29
29
  - init.rb
30
30
  - lib/catamaran.rb
31
+ - lib/catamaran/formatter/base_formatter.rb
31
32
  - lib/catamaran/formatter/caller_formatter.rb
32
33
  - lib/catamaran/formatter/no_caller_formatter.rb
33
34
  - lib/catamaran/integration/rails.rb