loggability 0.1.0 → 0.2.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/ChangeLog CHANGED
@@ -1,8 +1,68 @@
1
+ 2012-05-10 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ * .rvm.gems, README.rdoc, Rakefile, lib/loggability.rb,
4
+ spec/lib/helpers.rb, spec/loggability/logger_spec.rb,
5
+ spec/loggability_spec.rb:
6
+ Add Configurability support.
7
+ [555511f82876] [tip]
8
+
9
+ * lib/loggability/logger.rb:
10
+ Make Logger#inspect output a bit more terse
11
+ [fbddf3595a38]
12
+
13
+ 2012-05-08 Michael Granger <ged@FaerieMUD.org>
14
+
15
+ * .hgtags:
16
+ Added tag v0.1.0 for changeset 929216c0ffee
17
+ [65953fe69af2]
18
+
19
+ * .hgsigs:
20
+ Added signature for changeset ea1633c450be
21
+ [929216c0ffee] [v0.1.0]
22
+
23
+ * History.rdoc, lib/loggability.rb:
24
+ Bump minor version, update history.
25
+ [ea1633c450be]
26
+
27
+ * .hgignore, Rakefile, lib/loggability.rb,
28
+ lib/loggability/constants.rb, lib/loggability/formatter/color.rb,
29
+ lib/loggability/logger.rb, spec/loggability/formatter/html_spec.rb,
30
+ spec/loggability/formatter_spec.rb, spec/loggability/logger_spec.rb:
31
+ Remove all 1.9isms so it works under 1.8.x.
32
+
33
+ I've been trying to do everything in 1.9 first, but it turns out
34
+ there's still some 1.8 stuff that I need to support that I'd like to
35
+ use this with.
36
+ [e702bbec7c9d]
37
+
38
+ * lib/loggability/formatter/color.rb:
39
+ Fix the docs for the color formatter
40
+ [4191fb2e0d14]
41
+
42
+ 2012-05-07 Michael Granger <ged@FaerieMUD.org>
43
+
44
+ * .hgtags:
45
+ Added tag v0.0.2 for changeset 9a502152869e
46
+ [984798ba8ace]
47
+
48
+ * .hgsigs:
49
+ Added signature for changeset 1099204b229f
50
+ [9a502152869e] [v0.0.2]
51
+
52
+ * History.rdoc, lib/loggability.rb:
53
+ Bumped the patch version, updated History.
54
+ [1099204b229f]
55
+
56
+ * lib/loggability/formatter/html.rb, spec/lib/helpers.rb,
57
+ spec/loggability/formatter/html_spec.rb:
58
+ Fix escaping of the 'progname' in the HTML log formatter.
59
+ [748e600c8037]
60
+
1
61
  2012-05-06 Michael Granger <ged@FaerieMUD.org>
2
62
 
3
63
  * README.rdoc:
4
64
  Add some stuff to the README.
5
- [711c4dff84cf] [tip]
65
+ [711c4dff84cf] [github/master]
6
66
 
7
67
  * .hgtags:
8
68
  Added tag v0.0.1 for changeset 6dc36a56ff79
data/History.rdoc CHANGED
@@ -1,3 +1,8 @@
1
+ == v0.2.0 [2012-05-10] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Add Configurability support.
4
+
5
+
1
6
  == v0.1.0 [2012-05-08] Michael Granger <ged@FaerieMUD.org>
2
7
 
3
8
  - Add Ruby 1.8.7 support.
data/README.rdoc CHANGED
@@ -45,6 +45,43 @@ An example:
45
45
  Loggability.level = :info
46
46
 
47
47
 
48
+ === Configurability
49
+
50
+ Loggability has support for the Configurability[https://rubygems.org/gems/configurability]
51
+ library, which does the same thing for configuration that Loggability does for
52
+ logging.
53
+
54
+ You can configure all registered loggers from the 'logging' section of the config:
55
+
56
+ logging:
57
+ __default__: warn STDERR
58
+ mongrel2: info STDOUT (html)
59
+ strelka: debug (html)
60
+ inversion: error /var/log/templating.log (default)
61
+
62
+ The format of the value of each logger is:
63
+
64
+ SEVERITY [TARGET] [(FORMAT)]
65
+
66
+ where:
67
+
68
+ [+SEVERITY+]
69
+ The log level; one of: +debug+, +info+, +warn+, +error+, or +fatal+
70
+ [+TARGET+]
71
+ The destination for log messages. This can be the path to a log file, or
72
+ one of <tt>'STDOUT'</tt> or <tt>'STDERR'</tt>, which get mapped to the
73
+ equivalent filehandle. Optional.
74
+ [+FORMAT+]
75
+ The name of one of the formatters. Loggability comes with +default+ (plaintext),
76
+ +color+ (ANSI colored text), and +html+ formatters.
77
+
78
+ If the special key <tt>__default__</tt> is included, its config will be used to set
79
+ global defaults before the individual configs are applied.
80
+
81
+ If either of the optional values is unspecified, it is left unchanged from what it
82
+ was before configuration.
83
+
84
+
48
85
  == Prerequisites
49
86
 
50
87
  * Ruby 1.9.3 or better, Rubinius 2.0 or better
data/Rakefile CHANGED
@@ -21,10 +21,11 @@ hoespec = Hoe.spec 'loggability' do
21
21
 
22
22
  self.developer 'Michael Granger', 'ged@FaerieMUD.org'
23
23
 
24
- self.dependency 'pluginfactory', '~> 1.0'
24
+ self.dependency 'pluginfactory', '~> 1.0'
25
25
 
26
- self.dependency 'hoe-deveiate', '~> 0.1', :developer
27
- self.dependency 'simplecov', '~> 0.6', :developer
26
+ self.dependency 'hoe-deveiate', '~> 0.1', :developer
27
+ self.dependency 'simplecov', '~> 0.6', :developer
28
+ self.dependency 'configurability', '~> 1.2', :developer
28
29
 
29
30
  self.spec_extras[:licenses] = ["Ruby"]
30
31
  self.spec_extras[:rdoc_options] = ['-f', 'fivefish', '-t', 'Loggability Toolkit']
@@ -33,6 +33,15 @@ class Loggability::Logger < ::Logger
33
33
  @target = target
34
34
  end
35
35
 
36
+
37
+ ######
38
+ public
39
+ ######
40
+
41
+ # The target of the log device
42
+ attr_reader :target
43
+
44
+
36
45
  ### Append the specified +message+ to the target.
37
46
  def write( message )
38
47
  @target << message
@@ -128,6 +137,24 @@ class Loggability::Logger < ::Logger
128
137
  public
129
138
  ######
130
139
 
140
+ ### Return a human-readable representation of the object suitable for debugging.
141
+ def inspect
142
+ dev = if self.logdev.respond_to?( :dev )
143
+ self.logdev.dev.class
144
+ else
145
+ self.logdev.target.class
146
+ end
147
+
148
+ return "#<%p:%#x severity: %s, formatter: %s, outputting to: %p>" % [
149
+ self.class,
150
+ self.object_id * 2,
151
+ self.level,
152
+ self.formatter.class.name.sub( /.*::/, '' ).downcase,
153
+ dev,
154
+ ]
155
+ end
156
+
157
+
131
158
  #
132
159
  # :section: Severity Level
133
160
  #
data/lib/loggability.rb CHANGED
@@ -5,15 +5,14 @@
5
5
  require 'logger'
6
6
  require 'date'
7
7
 
8
-
9
8
  # A mixin that provides a top-level logging subsystem based on Logger.
10
9
  module Loggability
11
10
 
12
11
  # Package version constant
13
- VERSION = '0.1.0'
12
+ VERSION = '0.2.0'
14
13
 
15
14
  # VCS revision
16
- REVISION = %q$Revision: ea1633c450be $
15
+ REVISION = %q$Revision: 4c9840dcb9fd $
17
16
 
18
17
  # The key for the global logger (Loggability's own logger)
19
18
  GLOBAL_KEY = :__global__
@@ -21,6 +20,30 @@ module Loggability
21
20
  # The methods that are delegated across all loggers
22
21
  AGGREGATE_METHODS = [ :level=, :output_to, :write_to, :format_with, :format_as, :formatter= ]
23
22
 
23
+ # Configuration defaults
24
+ CONFIG_DEFAULTS = {
25
+ :defaults => {
26
+ :severity => 'warn',
27
+ :formatter => 'default',
28
+ :output => 'STDERR',
29
+ },
30
+ }
31
+
32
+ # Regexp for parsing logspec lines in the config
33
+ LOGSPEC_PATTERN = %r{
34
+ ^
35
+ \s*
36
+ ((?i:debug|info|warn|error|fatal)) # severity
37
+ (?:
38
+ \s+
39
+ ((?:[\w\-/:\.]|\\[ ])+)
40
+ )?
41
+ (?: \s+\(
42
+ (\w+)
43
+ \) )?
44
+ \s*
45
+ $
46
+ }x
24
47
 
25
48
  require 'loggability/constants'
26
49
  include Loggability::Constants
@@ -56,9 +79,26 @@ module Loggability
56
79
  end
57
80
 
58
81
 
82
+ ### Return the log host key for +object+, using its #log_host_key method
83
+ ### if it has one, or returning it as a Symbol if it responds to #to_sym. Returns
84
+ ### +nil+ if no key could be derived.
85
+ def self::log_host_key_for( object )
86
+ return object.log_host_key if object.respond_to?( :log_host_key )
87
+ return object.to_sym if object.respond_to?( :to_sym )
88
+ return nil
89
+ end
90
+
91
+
92
+ ### Returns +true+ if there is a log host associated with the given +object+.
93
+ def self::log_host?( object )
94
+ key = self.log_host_key_for( object ) or return false
95
+ return self.log_hosts.key?( key )
96
+ end
97
+
98
+
59
99
  ### Return the Loggability::Logger for the loghost associated with +logclient+.
60
100
  def self::[]( logclient )
61
- key = logclient.log_host_key if logclient.respond_to?( :log_host_key )
101
+ key = self.log_host_key_for( logclient )
62
102
  key ||= GLOBAL_KEY
63
103
 
64
104
  return self.log_hosts[ key ].logger
@@ -79,7 +119,10 @@ module Loggability
79
119
  ### Call the method with the given +methodname+ across the loggers of all loghosts with
80
120
  ### the given +arg+ and/or +block+.
81
121
  def self::aggregate( methodname, arg, &block )
122
+ # self.log.debug "Aggregating a call to %p with %p to %d log hosts" %
123
+ # [ methodname, arg, Loggability.log_hosts.length ]
82
124
  Loggability.log_hosts.values.each do |loghost|
125
+ # self.log.debug " %p.logger.%s( %p )" % [ loghost, methodname, arg ]
83
126
  loghost.logger.send( methodname, arg, &block )
84
127
  end
85
128
  end
@@ -221,17 +264,80 @@ module Loggability
221
264
  ### either the +key+ the host registered with, or the log host object itself. Log messages
222
265
  ### can be written to the loghost via the LogClient API, which is automatically included.
223
266
  def log_to( loghost )
224
- self.extend( Loggability::LogClient )
225
- self.log_host_key = if loghost.respond_to?( :log_host_key )
226
- loghost.log_host_key
267
+ extend( Loggability::LogClient )
268
+ include( Loggability::LogClient::InstanceMethods ) if self.is_a?( Class )
269
+
270
+ self.log_host_key = Loggability.log_host_key_for( loghost )
271
+ end
272
+
273
+
274
+ #
275
+ # :section: Configurability Support
276
+ #
277
+
278
+ # Load the Configurability library if it's installed
279
+ begin
280
+ require 'configurability'
281
+ rescue LoadError
282
+ end
283
+
284
+
285
+ # Configurability support -- load Loggability configuration from the 'logging' section
286
+ # of the config.
287
+ if defined?( Configurability )
288
+ extend Configurability
289
+ config_key :logging if respond_to?( :config_key )
290
+ end
291
+
292
+ ### Configurability API -- configure logging.
293
+ def self::configure( config=nil )
294
+ if config
295
+ self.log.debug "Configuring Loggability with custom config."
296
+
297
+ # Set up all loggers with defaults first
298
+ if defaultspec = config.delete( :__default__ ) || config.delete( '__default__' )
299
+ level, format, target = self.parse_config_spec( defaultspec )
300
+ Loggability.level = level if level
301
+ Loggability.format_as( format ) if format
302
+ Loggability.output_to( target ) if target
303
+ end
304
+
305
+ # Then let individual configs override.
306
+ config.each do |key, logspec|
307
+ unless Loggability.log_host?( key )
308
+ self.log.debug " no such log host %p; skipping" % [ key ]
309
+ next
310
+ end
311
+
312
+ self.log.debug " configuring logger for %p: %s" % [ key, logspec ]
313
+ level, format, target = self.parse_config_spec( logspec )
314
+ Loggability[ key ].level = level if level
315
+ Loggability[ key ].format_with( format ) if format
316
+ Loggability[ key ].output_to( target ) if target
317
+ end
318
+ else
319
+ self.log.debug "Configuring Loggability with defaults."
320
+ end
321
+ end
322
+
323
+
324
+ ### Parse the specified +spec+ into level,
325
+ def self::parse_config_spec( spec )
326
+ match = LOGSPEC_PATTERN.match( spec ) or
327
+ raise ArgumentError, "Couldn't parse logspec: %p" % [ spec ]
328
+ self.log.error " parsed config spec %p -> %p" % [ spec, match ]
329
+ severity, target, format = match.captures
330
+
331
+ target = case target
332
+ when 'STDOUT' then $stdout
333
+ when 'STDERR' then $stderr
227
334
  else
228
- loghost.to_sym
335
+ target
229
336
  end
230
337
 
231
- # For objects that also can be instantiated
232
- include( Loggability::LogClient::InstanceMethods ) if self.is_a?( Class )
338
+ return severity, format, target
233
339
  end
234
340
 
235
341
 
236
- end # module Strelka
342
+ end # module Loggability
237
343
 
data/spec/lib/helpers.rb CHANGED
@@ -28,9 +28,34 @@ require 'loggability' unless defined?( Loggability )
28
28
  #
29
29
  module Loggability::SpecHelpers
30
30
 
31
+ ### Reset the logging subsystem to its default state.
32
+ def reset_logging
33
+ Loggability.formatter = nil
34
+ Loggability.output_to( $stderr )
35
+ Loggability.level = :fatal
36
+ end
37
+
38
+
39
+ ### Alter the output of the default log formatter to be pretty in SpecMate output
40
+ def setup_logging( level=:fatal )
41
+
42
+ # Only do this when executing from a spec in TextMate
43
+ if ENV['HTML_LOGGING'] || (ENV['TM_FILENAME'] && ENV['TM_FILENAME'] =~ /_spec\.rb/)
44
+ logarray = []
45
+ Thread.current['logger-output'] = logarray
46
+ Loggability.output_to( logarray )
47
+ Loggability.format_as( :html )
48
+ Loggability.level = :debug
49
+ else
50
+ Loggability.level = level
51
+ end
52
+ end
53
+
54
+
31
55
  end # Loggability::SpecHelpers
32
56
 
33
57
 
58
+
34
59
  ### Mock with RSpec
35
60
  RSpec.configure do |c|
36
61
  c.mock_with( :rspec )
@@ -31,6 +31,10 @@ describe Loggability::Logger do
31
31
  end
32
32
 
33
33
 
34
+ it "has a less-verbose inspection format than that of its parent" do
35
+ @logger.inspect.should =~ /severity: \S+ formatter: \S+ outputting to: \S+/
36
+ end
37
+
34
38
  describe "severity level API" do
35
39
 
36
40
  it "defaults to :warn level" do
@@ -145,6 +149,12 @@ describe Loggability::Logger do
145
149
  messages.first.should =~ /DEBUG \{Object:0x[[:xdigit:]]+\} -- A debug message.\n/
146
150
  end
147
151
 
152
+ it "has a terse inspection format" do
153
+ object = Object.new
154
+ @logger.proxy_for( object ).inspect.
155
+ should =~ /ObjectNameProxy.* for Object/
156
+ end
157
+
148
158
  end
149
159
 
150
160
  end
@@ -13,12 +13,19 @@ require 'loggability/logger'
13
13
 
14
14
  describe Loggability do
15
15
 
16
+ before( :each ) do
17
+ setup_logging( :fatal )
18
+ end
19
+
20
+ after( :each ) do
21
+ reset_logging()
22
+ end
23
+
16
24
  it "is itself a log host for the global logger" do
17
25
  described_class.logger.should be_a( Loggability::Logger )
18
26
  described_class.log_hosts.should include( Loggability::GLOBAL_KEY => Loggability )
19
27
  end
20
28
 
21
-
22
29
  describe "version methods" do
23
30
  it "returns a version string if asked" do
24
31
  described_class.version_string.should =~ /\w+ [\d.]+/
@@ -46,6 +53,8 @@ describe Loggability do
46
53
  Loggability.log_hosts.should include( :testing => @class )
47
54
  @class.logger.should be_a( Loggability::Logger )
48
55
  @class.default_logger.should be( @class.logger )
56
+ Loggability[ @class ].should be( @class.logger )
57
+ Loggability[ :testing ].should be( @class.logger )
49
58
  end
50
59
 
51
60
  it "allows it to designate itself as a logging client" do
@@ -55,8 +64,12 @@ describe Loggability do
55
64
  end
56
65
  @class.log_to( :testing )
57
66
  @class.log.logger.should be( origin.logger )
67
+ Loggability[ @class ].should be( origin.logger )
58
68
 
59
- @class.new.log.logger.should be( origin.logger )
69
+ obj = @class.new
70
+
71
+ obj.log.logger.should be( origin.logger )
72
+ Loggability[ obj ].should be( origin.logger )
60
73
  end
61
74
 
62
75
  end
@@ -80,5 +93,87 @@ describe Loggability do
80
93
 
81
94
  end
82
95
 
96
+
97
+ describe "Configurability support" do
98
+
99
+ after( :each ) do
100
+ File.delete( 'spec-error.log' ) if File.exist?( 'spec-error.log' )
101
+ end
102
+
103
+ it "can parse a logging config spec with just a severity" do
104
+ Loggability.parse_config_spec( 'debug' ).should == [ 'debug', nil, nil ]
105
+ end
106
+
107
+ it "can parse a logging config spec with a severity and STDERR" do
108
+ Loggability.parse_config_spec( 'fatal STDERR' ).should == [ 'fatal', nil, $stderr ]
109
+ end
110
+
111
+ it "can parse a logging config spec with a severity and STDOUT" do
112
+ Loggability.parse_config_spec( 'error STDOUT' ).should == [ 'error', nil, $stdout ]
113
+ end
114
+
115
+ it "can parse a logging config spec with a severity and a path" do
116
+ Loggability.parse_config_spec( 'debug /var/log/debug.log' ).
117
+ should == [ 'debug', nil, '/var/log/debug.log' ]
118
+ end
119
+
120
+ it "can parse a logging config spec with a severity and a path with escaped spaces" do
121
+ Loggability.parse_config_spec( 'debug /store/media/Stormcrow\\ and\\ Raven/dl.log' ).
122
+ should == [ 'debug', nil, '/store/media/Stormcrow\\ and\\ Raven/dl.log' ]
123
+ end
124
+
125
+ it "can parse a logging config spec with a severity and a formatter" do
126
+ Loggability.parse_config_spec( 'warn (html)' ).
127
+ should == [ 'warn', 'html', nil ]
128
+ end
129
+
130
+ it "can parse a logging config spec with a severity, a path, and a formatter" do
131
+ Loggability.parse_config_spec( 'info /usr/local/www/htdocs/log.html (html)' ).
132
+ should == [ 'info', 'html', '/usr/local/www/htdocs/log.html' ]
133
+ end
134
+
135
+ it "can configure loghosts via its ::configure method" do
136
+ class1 = Class.new { extend Loggability; log_as :class1 }
137
+ class2 = Class.new { extend Loggability; log_as :class2 }
138
+
139
+ config = {'class1' => 'debug (html)', 'class2' => 'error spec-error.log'}
140
+ Loggability.configure( config )
141
+
142
+ Loggability[ class1 ].level.should == :debug
143
+ Loggability[ class1 ].formatter.should be_a( Loggability::Formatter::HTML )
144
+ Loggability[ class2 ].level.should == :error
145
+ Loggability[ class2 ].logdev.dev.should be_a( File )
146
+ Loggability[ class2 ].logdev.dev.path.should == 'spec-error.log'
147
+ end
148
+
149
+ it "can configure all loghosts with a config key of __default__" do
150
+ Loggability.configure( '__default__' => 'debug STDERR (html)' )
151
+
152
+ all_loggers = Loggability.log_hosts.values.map( &:logger )
153
+ all_loggers.all? {|lh| lh.level == :debug }.should be_true()
154
+ all_loggers.all? {|lh| lh.formatter.class == Loggability::Formatter::HTML }.should be_true()
155
+ all_loggers.all? {|lh| lh.logdev.dev.should == $stderr }.should be_true()
156
+ end
157
+
158
+ it "raises an error if configured with a logspec with an invalid severity" do
159
+ expect {
160
+ Loggability.configure( 'class1' => 'awesome /var/log/awesome.log' )
161
+ }.to raise_error( ArgumentError, /couldn't parse/i )
162
+ end
163
+
164
+ it "raises an error if configured with a logspec with an malformed filename" do
165
+ expect {
166
+ Loggability.configure( 'class1' => 'info Kitchen!!' )
167
+ }.to raise_error( ArgumentError, /couldn't parse/i )
168
+ end
169
+
170
+ it "raises an error if configured with a bogus formatter" do
171
+ expect {
172
+ Loggability.configure( 'class1' => 'debug (mindwaves)' )
173
+ }.to raise_error( FactoryError, /couldn't find a formatter/i )
174
+ end
175
+
176
+ end
177
+
83
178
  end
84
179
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loggability
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -36,7 +36,7 @@ cert_chain:
36
36
  YUhDS0xaZFNLai9SSHVUT3QrZ2JsUmV4OEZBaDhOZUEKY21saFhlNDZwWk5K
37
37
  Z1dLYnhaYWg4NWpJang5NWhSOHZPSStOQU01aUg5a09xSzEzRHJ4YWNUS1Bo
38
38
  cWo1UGp3RgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
39
- date: 2012-05-08 00:00:00.000000000 Z
39
+ date: 2012-05-11 00:00:00.000000000 Z
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pluginfactory
@@ -134,6 +134,22 @@ dependencies:
134
134
  - - ~>
135
135
  - !ruby/object:Gem::Version
136
136
  version: '0.6'
137
+ - !ruby/object:Gem::Dependency
138
+ name: configurability
139
+ requirement: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ~>
143
+ - !ruby/object:Gem::Version
144
+ version: '1.2'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ~>
151
+ - !ruby/object:Gem::Version
152
+ version: '1.2'
137
153
  - !ruby/object:Gem::Dependency
138
154
  name: hoe
139
155
  requirement: !ruby/object:Gem::Requirement
metadata.gz.sig CHANGED
@@ -1,3 +1 @@
1
- `�UJ�-�j|�`�(CG8p[��vj'���X5{6;o�Y���(ni3q
2
- �������ɏ<o�@
3
- e��<��]�B��� ���>
1
+ �� hZ���u�ҹ>|�"O'E���@�}I{��Yzw�諸g�<�H4� l���+����L�*�����o���NJ�Ɗ>��N>��_�!�a[