sawmill 0.1.11 → 0.1.12

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/History.rdoc CHANGED
@@ -1,3 +1,13 @@
1
+ === 0.1.12 / 2010-11-01
2
+
3
+ * A date-based rotater can now force log files to be written to by only one process. Useful in environments where you have an unknown number of processes(i.e. a Passenger-based deployment), each of which needs a separate log file.
4
+ * Provided a Railtie for easy integration into a Rails 3 application.
5
+ * The record_progname and attribute_level can now be set on a logger after creation.
6
+
7
+ === 0.1.11 / 2010-10-19
8
+
9
+ * Fixed a missing require.
10
+
1
11
  === 0.0.10 / 2010-01-31
2
12
 
3
13
  * Fixed a rotater issue that sometimes caused rotation to occur one record too late.
data/README.rdoc CHANGED
@@ -22,11 +22,12 @@ Sawmill is an extension to the standard ruby Logger mechanism that enables autom
22
22
  * Parse logfiles back into log entries and log records
23
23
  * Log analysis framework
24
24
  * Rack middleware for quick setup of web service logs
25
+ * Railtie for Rails 3 integration
25
26
 
26
27
  === Requirements
27
28
 
28
- * Ruby 1.8.6 or later (1.8.7 recommended), Ruby 1.9.1 or later, or JRuby 1.4 or later.
29
- * Blockenspiel 0.3.1 or later.
29
+ * Ruby 1.8.7 or later (Ruby 1.9.2 or later recommended), or JRuby 1.4 or later.
30
+ * Blockenspiel 0.4.1 or later.
30
31
 
31
32
  === Installation
32
33
 
@@ -48,11 +49,13 @@ Contact the author at dazuma at gmail dot com.
48
49
 
49
50
  === Author / Credits
50
51
 
51
- Lumber is written by Daniel Azuma (http://www.daniel-azuma.com/).
52
+ Sawmill is written by Daniel Azuma (http://www.daniel-azuma.com/).
52
53
 
53
- == LICENSE:
54
+ Development of Sawmill is sponsored by GeoPage (http://www.geopage.com/).
54
55
 
55
- Copyright 2009 Daniel Azuma.
56
+ === License
57
+
58
+ Copyright 2009-2010 Daniel Azuma.
56
59
 
57
60
  All rights reserved.
58
61
 
data/Version CHANGED
@@ -1 +1 @@
1
- 0.1.11
1
+ 0.1.12
@@ -67,6 +67,12 @@ module Sawmill
67
67
  end
68
68
 
69
69
 
70
+ # Could not open a log file because a uniquifier failed.
71
+
72
+ class NoUniqueLogFileError < SawmillError
73
+ end
74
+
75
+
70
76
  end
71
77
 
72
78
 
@@ -34,10 +34,7 @@
34
34
  ;
35
35
 
36
36
 
37
- begin
38
- require 'securerandom'
39
- rescue ::LoadError
40
- end
37
+ require 'securerandom'
41
38
 
42
39
 
43
40
  module Sawmill
@@ -254,6 +251,20 @@ module Sawmill
254
251
  end
255
252
 
256
253
 
254
+ # Get the current record progname setting for this logger
255
+
256
+ def record_progname
257
+ @record_progname
258
+ end
259
+
260
+
261
+ # Set the current record progname setting for this logger
262
+
263
+ def record_progname=(value_)
264
+ @record_progname = value_.to_s.gsub(/\s+/, '')
265
+ end
266
+
267
+
257
268
  # Get the current level setting for this logger as a Sawmill::Level.
258
269
 
259
270
  def level
@@ -282,6 +293,32 @@ module Sawmill
282
293
  alias_method :sev_threshold, :level
283
294
 
284
295
 
296
+ # Get the current attribute level setting for this logger as a
297
+ # Sawmill::Level.
298
+
299
+ def attribute_level
300
+ @attribute_level
301
+ end
302
+
303
+
304
+ # Set the current attribute level setting for this logger.
305
+ # You may specify the level as a string, a symbol, an integer, or a
306
+ # Sawmill::Level. Ruby's logger constants such as ::Logger::INFO
307
+ # will also work.
308
+
309
+ def attribute_level=(value_)
310
+ if value_.kind_of?(Level)
311
+ @attribute_level = value_
312
+ else
313
+ level_obj_ = @level_group.get(value_)
314
+ if level_obj_.nil?
315
+ raise Errors::UnknownLevelError, value_
316
+ end
317
+ @attribute_level = level_obj_
318
+ end
319
+ end
320
+
321
+
285
322
  # Get the LevelGroup in use by this Logger. This setting cannot be
286
323
  # changed once the logger is constructed.
287
324
 
@@ -348,32 +385,16 @@ module Sawmill
348
385
 
349
386
 
350
387
  def self._get_default_record_id_generator # :nodoc:
351
- unless @_default_generator
352
- if defined?(::SecureRandom)
353
- _random_hex32 = ::Proc.new do
354
- ::SecureRandom.hex(16)
355
- end
356
- elsif defined?(::ActiveSupport::SecureRandom)
357
- _random_hex32 = ::Proc.new do
358
- ::ActiveSupport::SecureRandom.hex(16)
359
- end
360
- else
361
- _random_hex32 = ::Proc.new do
362
- ::Kernel.rand(0x100000000000000000000000000000000).to_s(16).rjust(32, '0')
363
- end
364
- end
365
- @_default_generator = ::Proc.new do
366
- uuid_ = _random_hex32.call
367
- uuid_[12] = '4'
368
- uuid_[16] = (uuid_[16,1].to_i(16)&3|8).to_s(16)
369
- uuid_.insert(8, '-')
370
- uuid_.insert(13, '-')
371
- uuid_.insert(18, '-')
372
- uuid_.insert(23, '-')
373
- uuid_
374
- end
388
+ @_default_generator ||= ::Proc.new do
389
+ uuid_ = ::SecureRandom.hex(16)
390
+ uuid_[12] = '4'
391
+ uuid_[16] = (uuid_[16,1].to_i(16)&3|8).to_s(16)
392
+ uuid_.insert(8, '-')
393
+ uuid_.insert(13, '-')
394
+ uuid_.insert(18, '-')
395
+ uuid_.insert(23, '-')
396
+ uuid_
375
397
  end
376
- @_default_generator
377
398
  end
378
399
 
379
400
 
@@ -0,0 +1,153 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Sawmill railtie
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2009 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ require 'sawmill'
38
+ require 'rails/railtie'
39
+
40
+
41
+ module Sawmill
42
+
43
+
44
+ # Railtie that replaces the default Rails logger with a Sawmill logger.
45
+ # Sets the Rails logger to a Sawmill::Logger, and installs a
46
+ # Sawmill::LogRecordMiddleware to enable record-based logging.
47
+ #
48
+ # To install into a Rails app, include this line in your
49
+ # config/application.rb:
50
+ # require 'sawmill/railtie'
51
+ # It should appear before your application configuration.
52
+ #
53
+ # You can then configure sawmill using the standard rails configuration
54
+ # mechanism. The sawmill configuration lives in the config.sawmill
55
+ # configuration namespace. See Sawmill::Railtie::Configuration for the
56
+ # configuration options.
57
+
58
+ class Railtie < ::Rails::Railtie
59
+
60
+
61
+ # Configuration options. These are attributes of config.sawmill.
62
+
63
+ class Configuration
64
+
65
+ def initialize # :nodoc:
66
+ @logfile = ::STDERR
67
+ @formatter_options = {}
68
+ @logger_options = {}
69
+ @include_id = false
70
+ @fractional_second_digits = 2
71
+ @level_width = nil
72
+ @local_time = false
73
+ @iso_8601_time = false
74
+ @length_limit = nil
75
+ @level = :INFO
76
+ @attribute_level = nil
77
+ @progname = 'rails'
78
+ @record_progname = nil
79
+ @record_id_generator = nil
80
+ @request_id_key = 'sawmill.request_id'
81
+ @start_time_attribute = nil
82
+ @end_time_attribute = nil
83
+ end
84
+
85
+ # The log file to write to. This should be either an IO object, or
86
+ # a Sawmill::Rotater. Default is STDERR.
87
+ attr_accessor :logfile
88
+
89
+ # This option is passed to Sawmill::EntryProcessor::Format::new
90
+ attr_accessor :include_id
91
+ # This option is passed to Sawmill::EntryProcessor::Format::new
92
+ attr_accessor :fractional_second_digits
93
+ # This option is passed to Sawmill::EntryProcessor::Format::new
94
+ attr_accessor :level_width
95
+ # This option is passed to Sawmill::EntryProcessor::Format::new
96
+ attr_accessor :local_time
97
+ # This option is passed to Sawmill::EntryProcessor::Format::new
98
+ attr_accessor :iso_8601_time
99
+ # This option is passed to Sawmill::EntryProcessor::Format::new
100
+ attr_accessor :length_limit
101
+
102
+ # This option is passed to Sawmill::Logger::new
103
+ attr_accessor :level
104
+ # This option is passed to Sawmill::Logger::new
105
+ attr_accessor :attribute_level
106
+ # This option is passed to Sawmill::Logger::new
107
+ attr_accessor :progname
108
+ # This option is passed to Sawmill::Logger::new
109
+ attr_accessor :record_progname
110
+ # This option is passed to Sawmill::Logger::new
111
+ attr_accessor :record_id_generator
112
+
113
+ # This option is passed to Sawmill::LogRecordMiddleware::new
114
+ attr_accessor :request_id_key
115
+ # This option is passed to Sawmill::LogRecordMiddleware::new
116
+ attr_accessor :start_time_attribute
117
+ # This option is passed to Sawmill::LogRecordMiddleware::new
118
+ attr_accessor :end_time_attribute
119
+
120
+ end
121
+
122
+
123
+ config.sawmill = Configuration.new
124
+
125
+
126
+ initializer :initialize_sawmill, :before => :initialize_logger do |app_|
127
+ myconfig_ = app_.config.sawmill
128
+ formatter_ = Formatter.new(myconfig_.logfile || ::STDERR,
129
+ :include_id => myconfig_.include_id,
130
+ :fractional_second_digits => myconfig_.fractional_second_digits,
131
+ :level_width => myconfig_.level_width,
132
+ :local_time => myconfig_.local_time,
133
+ :iso_8601_time => myconfig_.iso_8601_time,
134
+ :length_limit => myconfig_.length_limit)
135
+ logger_ = Logger.new(:processor => formatter_,
136
+ :level => myconfig_.level,
137
+ :attribute_level => myconfig_.attribute_level,
138
+ :progname => myconfig_.progname,
139
+ :record_progname => myconfig_.record_progname,
140
+ :record_id_generator => myconfig_.record_id_generator)
141
+ app_.config.logger = logger_
142
+ app_.config.middleware.swap(::Rails::Rack::Logger,
143
+ ::Sawmill::LogRecordMiddleware, logger_,
144
+ :request_id_key => myconfig_.request_id_key,
145
+ :start_time_attribute => myconfig_.start_time_attribute,
146
+ :end_time_attribute => myconfig_.end_time_attribute)
147
+ end
148
+
149
+
150
+ end
151
+
152
+
153
+ end
@@ -76,15 +76,61 @@ module Sawmill
76
76
  # The logfile name prefix.
77
77
  # In the filename "rails.2009-10-11.log", the suffix is ".log".
78
78
  # If not specified, defaults to ".log".
79
+ # <tt>:uniquifier</tt>::
80
+ # If provided, log files are never reopened. (That is, they are
81
+ # opened with ::File::CREAT | ::File::EXCL.) The value of this
82
+ # parameter must be a proc that returns an actual file name to
83
+ # attempt to open. This proc is called repeatedly until it either
84
+ # returns a file path that does not yet exist, or signals failure
85
+ # by returning nil. See the session on Uniquifiers below.
79
86
  # <tt>:local_datestamps</tt>::
80
87
  # If true, use the local timezone to create datestamps.
81
88
  # The default is to use UTC.
89
+ #
90
+ # === Uniquifiers
91
+ #
92
+ # DateBasedLogFile provides a facility for ensuring that log files
93
+ # are written to by only one process, by generating unique file
94
+ # names for log files. This facility is useful, for example, if you
95
+ # are deploying via Phusion Passenger where you may have a variable
96
+ # number of rails processes, and you want each process to own its
97
+ # own logfile so entries in log records are not interleaved.
98
+ #
99
+ # To activate this feature, pass a proc to the <tt>:uniquifier</tt>
100
+ # option. When DateBasedLogFile wants to open a log file for
101
+ # writing, it first calls this proc. The proc should return a file
102
+ # path to try opening. DateBasedLogFile then tries to open the file
103
+ # with ::File::CREAT | ::File::EXCL, which will succeed only if the
104
+ # file has not already been created (e.g. by another process). If
105
+ # the file already exists, the proc will be called again, and
106
+ # repeatedly until it either returns a path that has not yet been
107
+ # created, or nil indicating that it has given up.
108
+ #
109
+ # The proc is passed a single hash that provides information about
110
+ # what path to generate, as well as space for the proc to store any
111
+ # state it wishes to persist through the process. These keys are
112
+ # given to the proc by DateBasedLogFile. Any other keys are
113
+ # available for use by the proc.
114
+ # <tt>:original_path</tt>::
115
+ # The original file path generated by DateBasedLogFile, which
116
+ # would have been used if there were no uniquifier.
117
+ # <tt>:last_path</tt>::
118
+ # The last path generated by the proc, or nil if this is the
119
+ # first time this proc is called for a particular logfile.
120
+ # <tt>:basedir</tt>::
121
+ # The basedir of the DateBasedLogFile.
122
+ # <tt>:path_prefix</tt>::
123
+ # The path_prefix of the DateBasedLogFile.
124
+ # <tt>:path_suffix</tt>::
125
+ # The path_suffix of the DateBasedLogFile.
82
126
 
83
127
  def initialize(options_)
84
128
  @turnover_frequency = options_[:turnover_frequency] || :none
85
- @prefix = ::File.expand_path(options_[:path_prefix] || options_[:prefix] || 'sawmill',
86
- options_[:basedir] || options_[:dirname] || ::Dir.getwd)
129
+ @basedir = options_[:basedir] || options_[:dirname] || ::Dir.getwd
130
+ @prefix = options_[:path_prefix] || options_[:prefix] || 'sawmill'
87
131
  @suffix = options_[:path_suffix] || options_[:suffix] || '.log'
132
+ @suffix = ".#{@suffix}" unless @suffix.length == 0 || @suffix[0,1] == '.'
133
+ @uniquifier = options_[:uniquifier]
88
134
  @local_datestamps = options_[:local_datestamps]
89
135
  @date_pattern =
90
136
  case @turnover_frequency
@@ -113,12 +159,24 @@ module Sawmill
113
159
  # Implements the rotation strategy contract.
114
160
 
115
161
  def open_handle(handle_)
116
- if @date_pattern
117
- path_ = "#{@prefix}.#{handle_}#{@suffix}"
162
+ path_ = ::File.expand_path(@date_pattern ? "#{@prefix}.#{handle_}#{@suffix}" : @prefix+@suffix, @basedir)
163
+ file_ = nil
164
+ if @uniquifier
165
+ hash_ = {:path_prefix => @prefix, :path_suffix => @suffix, :basedir => @basedir, :original_path => path_.dup, :last_path => nil}
166
+ until file_
167
+ path_ = @uniquifier.call(hash_)
168
+ unless path_
169
+ raise Errors::NoUniqueLogFileError, "Could not find a unique log file path for #{hash_.inspect}"
170
+ end
171
+ begin
172
+ file_ = ::File.open(path_, ::File::CREAT | ::File::EXCL | ::File::WRONLY)
173
+ rescue ::Errno::EEXIST
174
+ hash_[:last_path] = path_
175
+ end
176
+ end
118
177
  else
119
- path_ = @prefix+@suffix
178
+ file_ = ::File.open(path_, 'a')
120
179
  end
121
- file_ = ::File.open(path_, 'a')
122
180
  file_.sync = true
123
181
  file_
124
182
  end
@@ -137,6 +195,72 @@ module Sawmill
137
195
  end
138
196
 
139
197
 
198
+ class << self
199
+
200
+
201
+ # Returns a simple uniquifier that inserts an incrementing number
202
+ # before the path suffix. i.e. if the non-uniquified filename is
203
+ # "rails.2009-10-11.log", then these names are generated:
204
+ #
205
+ # rails.2009-10-11.0.log
206
+ # rails.2009-10-11.1.log
207
+ # rails.2009-10-11.2.log
208
+ # etc.
209
+ #
210
+ # The following options are available:
211
+ #
212
+ # <tt>:min_digits</tt>::
213
+ # If provided, indicates the minimum number of digits for the
214
+ # unique number. For example, if :digits is set to 2, these
215
+ # names are generated:
216
+ # rails.2009-10-11.00.log
217
+ # rails.2009-10-11.01.log
218
+ # rails.2009-10-11.02.log
219
+ # ...
220
+ # rails.2009-10-11.09.log
221
+ # rails.2009-10-11.10.log
222
+ # rails.2009-10-11.11.log
223
+ # ...
224
+ # rails.2009-10-11.99.log
225
+ # rails.2009-10-11.100.log
226
+ # rails.2009-10-11.101.log
227
+ # etc.
228
+ # The default is 1.
229
+ # <tt>:start_value</tt>::
230
+ # The first value for the unique number. Default is 0.
231
+
232
+ def simple_uniquifier(opts_={})
233
+ if (digits_ = opts_[:min_digits])
234
+ pattern_ = "%s.%0#{digits_.to_i}d%s"
235
+ else
236
+ pattern_ = "%s.%d%s"
237
+ end
238
+ ::Proc.new do |hash_|
239
+ if hash_[:last_path]
240
+ hash_[:value] += 1
241
+ else
242
+ suffix_ = hash_[:path_suffix]
243
+ orig_ = hash_[:original_path]
244
+ suffix_len_ = suffix_.length
245
+ if suffix_len_ > 0 && orig_[-suffix_len_, suffix_len_] == suffix_
246
+ pre_ = orig_[0, orig_.length - suffix_len_]
247
+ post_ = suffix_
248
+ else
249
+ pre_ = orig_
250
+ post_ = ''
251
+ end
252
+ hash_[:value] = opts_[:start_value].to_i
253
+ hash_[:pre] = pre_
254
+ hash_[:post] = post_
255
+ end
256
+ pattern_ % [hash_[:pre], hash_[:value], hash_[:post]]
257
+ end
258
+ end
259
+
260
+
261
+ end
262
+
263
+
140
264
  end
141
265
 
142
266
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 11
9
- version: 0.1.11
8
+ - 12
9
+ version: 0.1.12
10
10
  platform: ruby
11
11
  authors:
12
12
  - Daniel Azuma
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-19 00:00:00 -07:00
17
+ date: 2010-11-01 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -60,6 +60,7 @@ files:
60
60
  - lib/sawmill/logger.rb
61
61
  - lib/sawmill/multi_parser.rb
62
62
  - lib/sawmill/parser.rb
63
+ - lib/sawmill/railtie.rb
63
64
  - lib/sawmill/record.rb
64
65
  - lib/sawmill/record_processor/compile_report.rb
65
66
  - lib/sawmill/record_processor/conditionals.rb