sawmill 0.0.4 → 0.0.5

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.
@@ -1,4 +1,11 @@
1
- === 0.0.4 / 2009-??-??
1
+ === 0.0.5 / 2009-11-08
2
+
3
+ * API CHANGE: Reworked how string encoding is specified. Default encoding for both reading and writing is now ASCII-8BIT unless specified in the API or within the file as a parser directive.
4
+ * Handle encoding errors more gracefully by replacing characters rather than raising exceptions.
5
+ * Added a parser directive to set logfile encoding.
6
+ * Versionomy is no longer a hard dependency-- it is now used only if available.
7
+
8
+ === 0.0.4 / 2009-11-06
2
9
 
3
10
  * API CHANGE: Renamed DateBasedLogFile options :prefix and :suffix to :path_prefix and :path_suffix
4
11
  * API CHANGE: Renamed ShiftingLogFile options :filepath and :max_logfile_size to :file_path and :max_file_size
@@ -26,7 +26,7 @@ Sawmill is an extension to the standard ruby Logger mechanism that enables autom
26
26
  === Requirements
27
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
- * versionomy gem.
29
+ * Blockenspiel 0.3.1 or later.
30
30
 
31
31
  === Installation
32
32
 
data/Rakefile CHANGED
@@ -88,8 +88,7 @@ gemspec_ = ::Gem::Specification.new do |s_|
88
88
  s_.has_rdoc = true
89
89
  s_.test_files = ::FileList['tests/tc_*.rb']
90
90
  s_.platform = ::Gem::Platform::RUBY
91
- s_.add_dependency('blockenspiel', '>= 0.3.0')
92
- s_.add_dependency('versionomy', '>= 0.2.0')
91
+ s_.add_dependency('blockenspiel', '>= 0.3.1')
93
92
  end
94
93
  ::Rake::GemPackageTask.new(gemspec_) do |task_|
95
94
  task_.need_zip = false
@@ -34,14 +34,7 @@
34
34
  ;
35
35
 
36
36
 
37
- begin
38
- require 'blockenspiel'
39
- require 'versionomy'
40
- rescue ::LoadError
41
- require 'rubygems'
42
- require 'blockenspiel'
43
- require 'versionomy'
44
- end
37
+ require 'blockenspiel'
45
38
 
46
39
 
47
40
  dir_ = ::File.expand_path('sawmill', ::File.dirname(__FILE__))
@@ -266,11 +266,13 @@ module Sawmill
266
266
  # <tt>:encoding</tt>::
267
267
  # Specify an encoding for file data. (Ruby 1.9 only.)
268
268
  # You may specify an encoding name or an encoding object.
269
- # If not specified, uses the default external encoding.
269
+ # If not specified, reads raw bytes (e.g. defaults to 'ASCII-8BIT').
270
+ # Note that the encoding may also be modified by the file itself,
271
+ # if an appropriate parser directive is encountered.
270
272
  # <tt>:internal_encoding</tt>::
271
273
  # Specify an encoding to transcode to. (Ruby 1.9 only.)
272
274
  # You may specify an encoding name or an encoding object.
273
- # If not specified, uses the default internal encoding.
275
+ # If not specified, uses the encoding as read from the file.
274
276
 
275
277
  def open_entries(globs_, opts_={}, &block_)
276
278
  processor_ = EntryProcessor.build(&block_)
@@ -297,11 +299,13 @@ module Sawmill
297
299
  # <tt>:encoding</tt>::
298
300
  # Specify an encoding for file data. (Ruby 1.9 only.)
299
301
  # You may specify an encoding name or an encoding object.
300
- # If not specified, uses the default external encoding.
302
+ # If not specified, reads raw bytes (e.g. defaults to 'ASCII-8BIT').
303
+ # Note that the encoding may also be modified by the file itself,
304
+ # if an appropriate parser directive is encountered.
301
305
  # <tt>:internal_encoding</tt>::
302
306
  # Specify an encoding to transcode to. (Ruby 1.9 only.)
303
307
  # You may specify an encoding name or an encoding object.
304
- # If not specified, uses the default internal encoding.
308
+ # If not specified, uses the encoding as read from the file.
305
309
 
306
310
  def open_records(globs_, opts_={}, &block_)
307
311
  processor_ = RecordProcessor.build(&block_)
@@ -331,11 +335,13 @@ module Sawmill
331
335
  # <tt>:encoding</tt>::
332
336
  # Specify an encoding for file data. (Ruby 1.9 only.)
333
337
  # You may specify an encoding name or an encoding object.
334
- # If not specified, uses the default external encoding.
338
+ # If not specified, reads raw bytes (e.g. defaults to 'ASCII-8BIT').
339
+ # Note that the encoding may also be modified by the file itself,
340
+ # if an appropriate parser directive is encountered.
335
341
  # <tt>:internal_encoding</tt>::
336
342
  # Specify an encoding to transcode to. (Ruby 1.9 only.)
337
343
  # You may specify an encoding name or an encoding object.
338
- # If not specified, uses the default internal encoding.
344
+ # If not specified, uses the encoding as read from the file.
339
345
 
340
346
  def open_files(globs_, processor_, opts_={})
341
347
  finish_opt_ = opts_.delete(:finish)
@@ -343,20 +349,17 @@ module Sawmill
343
349
  internal_encoding_ = opts_.delete(:internal_encoding)
344
350
  mode_ = 'r'
345
351
  if defined?(::Encoding)
346
- if encoding_
347
- encoding_ = ::Encoding.find(encoding_) unless encoding_.respond_to?(:name)
348
- encoding_ = nil if encoding_ == ::Encoding.default_external
352
+ if !encoding_
353
+ encoding_ = ::Encoding::ASCII_8BIT
354
+ elsif encoding_ && !encoding_.respond_to?(:name)
355
+ encoding_ = ::Encoding.find(encoding_)
349
356
  end
350
- if internal_encoding_
351
- internal_encoding_ = ::Encoding.find(internal_encoding_) unless internal_encoding_.respond_to?(:name)
352
- internal_encoding_ = nil if internal_encoding_ == ::Encoding.default_internal
357
+ if internal_encoding_ && !internal_encoding_.respond_to?(:name)
358
+ internal_encoding_ = ::Encoding.find(internal_encoding_)
353
359
  end
354
360
  if encoding_
355
361
  mode_ << ":#{encoding_.name}"
356
- elsif internal_encoding_
357
- mode_ << ":#{::Encoding.default_external.name}"
358
362
  end
359
- mode_ << ":#{internal_encoding_.name}" if internal_encoding_
360
363
  else
361
364
  encoding_ = nil
362
365
  internal_encoding_ = nil
@@ -376,7 +379,7 @@ module Sawmill
376
379
  else
377
380
  io_array_ << ::File.open(path_, mode_)
378
381
  encoding_array_ << nil
379
- internal_encoding_array_ << nil
382
+ internal_encoding_array_ << internal_encoding_
380
383
  end
381
384
  end
382
385
  end
@@ -46,6 +46,8 @@ module Sawmill
46
46
  LINE_REGEXP = /^\[\s*([[:graph:]]+)\s+(\d{4})-(\d{2})-(\d{2})(T|\s)(\d{2}):(\d{2}):(\d{2})(.(\d{1,6}))?Z?\s?([+-]\d{4})?\s+([[:graph:]]+)(\s+([[:graph:]]+))?\s+([\^$.=])\]\s(.*)$/
47
47
  DIRECTIVE_REGEXP = /^#\s+sawmill_format:\s+(\w+)=(.*)$/
48
48
  ATTRIBUTE_REGEXP = /^([[:graph:]]+)\s([=+\/-])\s/
49
+ SUPPORTS_ENCODING = defined?(::Encoding)
50
+ ENCODING_OPTS = {:invalid => :replace, :undef => :replace}
49
51
  # :startdoc:
50
52
 
51
53
 
@@ -65,6 +67,16 @@ module Sawmill
65
67
  # <tt>:emit_incomplete_records_at_eof</tt>
66
68
  # If set to true, causes any incomplete log records to be emitted
67
69
  # in their incomplete state when EOF is reached.
70
+ # <tt>:encoding</tt>
71
+ # Overrides the IO encoding. (Ruby 1.9 only). If specified, lines
72
+ # read from the stream are assumed to be in this encoding. If not
73
+ # specified, the IO's default encoding is honored.
74
+ # Note that the encoding may also be modified by the stream itself,
75
+ # if an appropriate parser directive is encountered.
76
+ # <tt>:internal_encoding</tt>
77
+ # Transcodes strings as they are read. (Ruby 1.9 only). If specified,
78
+ # lines are transcoded into this encoding after they are read from
79
+ # the stream. If not specified, no post-transcoding is done.
68
80
 
69
81
  def initialize(io_, processor_, opts_={})
70
82
  @io = io_
@@ -77,11 +89,10 @@ module Sawmill
77
89
  @levels = opts_[:levels] || STANDARD_LEVELS
78
90
  @emit_incomplete_records_at_eof = opts_[:emit_incomplete_records_at_eof]
79
91
  @current_record_id = nil
80
- @parser_directives = {}
81
- @encoding = opts_[:encoding]
82
- @internal_encoding = opts_[:internal_encoding]
83
- if defined?(::Encoding)
92
+ if SUPPORTS_ENCODING
93
+ @encoding = opts_[:encoding]
84
94
  @encoding = ::Encoding.find(@encoding) if @encoding && !@encoding.kind_of?(::Encoding)
95
+ @internal_encoding = opts_[:internal_encoding]
85
96
  @internal_encoding = ::Encoding.find(@internal_encoding) if @internal_encoding && !@internal_encoding.kind_of?(::Encoding)
86
97
  end
87
98
  end
@@ -158,7 +169,7 @@ module Sawmill
158
169
  end
159
170
  else
160
171
  if str_ =~ DIRECTIVE_REGEXP
161
- @parser_directives[$1] = $2
172
+ _set_parser_directive($1, $2)
162
173
  end
163
174
  entry_ = Entry::UnknownData.new(str_.chomp)
164
175
  @processor.unknown_data(entry_) if @processor.respond_to?(:unknown_data)
@@ -185,14 +196,25 @@ module Sawmill
185
196
 
186
197
  def _get_next_line # :nodoc:
187
198
  str_ = @io.gets
188
- if str_
199
+ if str_ && SUPPORTS_ENCODING
189
200
  str_.force_encoding(@encoding) if @encoding
190
- str_.encode!(@internal_encoding) if @internal_encoding
201
+ str_.encode!(@internal_encoding, ENCODING_OPTS) if @internal_encoding
191
202
  end
192
203
  str_
193
204
  end
194
205
 
195
206
 
207
+ def _set_parser_directive(key_, value_) # :nodoc:
208
+ case key_
209
+ when 'encoding'
210
+ if SUPPORTS_ENCODING
211
+ encoding_ = ::Encoding.find(value_) rescue nil
212
+ @encoding = encoding_ if encoding_
213
+ end
214
+ end
215
+ end
216
+
217
+
196
218
  end
197
219
 
198
220
 
@@ -59,6 +59,11 @@ module Sawmill
59
59
 
60
60
  class Rotater
61
61
 
62
+ # :stopdoc:
63
+ SUPPORTS_ENCODING = defined?(::Encoding)
64
+ ENCODING_OPTS = {:invalid => :replace, :undef => :replace}
65
+ # :startdoc:
66
+
62
67
 
63
68
  # Create a rotater using the given rotation strategy.
64
69
  # See Sawmill::Rotater::DateBasedLogFile and
@@ -70,9 +75,26 @@ module Sawmill
70
75
  #
71
76
  # <tt>:omit_directives</tt>::
72
77
  # If true, omit standard logfile directives. Default is false.
78
+ # <tt>:concurrent_writes</tt>::
79
+ # Set this to true if you expect multiple processes to attempt to
80
+ # write to the same log file simultaneously. This option causes the
81
+ # rotater to surround writes with an acquisition of the cooperative
82
+ # filesystem lock (if available) for the logfile, in an attempt to
83
+ # prevent lines from interleaving in one another. Default is false.
84
+ # <tt>:encoding</tt>::
85
+ # Specify an encoding for file data. (Ruby 1.9 only).
86
+ # You may pass either an encoding object or an encoding name.
87
+ # If not specified, writes raw bytes (e.g. defaults to ASCII-8BIT).
73
88
 
74
89
  def initialize(io_manager_, opts_={})
75
90
  @omit_directives = opts_.delete(:omit_directives)
91
+ @concurrent_writes = opts_.delete(:concurrent_writes)
92
+ if SUPPORTS_ENCODING
93
+ @encoding = opts_.delete(:encoding)
94
+ if @encoding && !@encoding.respond_to?(:name)
95
+ @encoding = ::Encoding.find(@encoding)
96
+ end
97
+ end
76
98
  if io_manager_.kind_of?(::Class)
77
99
  @io_manager = io_manager_.new(opts_)
78
100
  else
@@ -99,6 +121,23 @@ module Sawmill
99
121
  end
100
122
 
101
123
 
124
+ def _write_to_stream(io_, str_)
125
+ if SUPPORTS_ENCODING && @encoding
126
+ str_ = str_.encode(@encoding, ENCODING_OPTS)
127
+ end
128
+ if @concurrent_writes
129
+ begin
130
+ io_.flock(::File::LOCK_EX)
131
+ io_.write(str_)
132
+ ensure
133
+ io_.flock(::File::LOCK_UN)
134
+ end
135
+ else
136
+ io_.write(str_)
137
+ end
138
+ end
139
+
140
+
102
141
  def _obtain_handle # :nodoc:
103
142
  handle_ = @io_manager.preferred_handle
104
143
  if @handles.include?(handle_)
@@ -106,7 +145,13 @@ module Sawmill
106
145
  else
107
146
  io_ = @io_manager.open_handle(handle_)
108
147
  unless @omit_directives
109
- io_.write("# sawmill_format: version=1\n")
148
+ _write_to_stream(io_, "# sawmill_format: version=1\n")
149
+ if defined?(::Encoding)
150
+ encoding_ = io_.encoding
151
+ if encoding_
152
+ _write_to_stream(io_, "# sawmill_format: encoding=#{encoding_.name}\n")
153
+ end
154
+ end
110
155
  end
111
156
  @handles[handle_] = [handle_, io_, 1]
112
157
  end
@@ -149,7 +194,7 @@ module Sawmill
149
194
  handle_ = _check_rotate_handle(handle_)
150
195
  end
151
196
  info_ = @handles[handle_]
152
- info_[1].write(str_)
197
+ _write_to_stream(info_[1], str_)
153
198
  handle_
154
199
  end
155
200
  end
@@ -79,9 +79,6 @@ module Sawmill
79
79
  # <tt>:local_datestamps</tt>::
80
80
  # If true, use the local timezone to create datestamps.
81
81
  # The default is to use UTC.
82
- # <tt>:encoding</tt>::
83
- # Specify an encoding name for file data. (Ruby 1.9 only)
84
- # If not specified, uses the default external encoding.
85
82
 
86
83
  def initialize(options_)
87
84
  @turnover_frequency = options_[:turnover_frequency] || :none
@@ -97,10 +94,6 @@ module Sawmill
97
94
  when :hourly then "%Y-%m-%d-%H"
98
95
  else nil
99
96
  end
100
- @mode = 'a'
101
- if defined?(::Encoding) && (encoding_ = options_[:encoding])
102
- @mode << ":#{encoding_}"
103
- end
104
97
  end
105
98
 
106
99
 
@@ -125,7 +118,7 @@ module Sawmill
125
118
  else
126
119
  path_ = @prefix+@suffix
127
120
  end
128
- file_ = ::File.open(path_, @mode)
121
+ file_ = ::File.open(path_, 'a')
129
122
  file_.sync = true
130
123
  file_
131
124
  end
@@ -76,9 +76,6 @@ module Sawmill
76
76
  # The maximum number of old logfiles (files with indexes) to
77
77
  # keep. Files beyond this history size will be automatically
78
78
  # deleted. Default is 1. This value must be at least 1.
79
- # <tt>:encoding</tt>::
80
- # Specify an encoding name for file data. (Ruby 1.9 only)
81
- # If not specified, uses the default external encoding.
82
79
 
83
80
  def initialize(options_)
84
81
  @max_logfile_size = options_[:max_file_size] || options_[:max_logfile_size]
@@ -100,10 +97,6 @@ module Sawmill
100
97
  @preferred_handle = 0
101
98
  @open_handles = {}
102
99
  @last_shift = ::Time.now
103
- @mode = 'a'
104
- if defined?(::Encoding) && (encoding_ = options_[:encoding])
105
- @mode << ":#{encoding_}"
106
- end
107
100
  end
108
101
 
109
102
 
@@ -122,7 +115,7 @@ module Sawmill
122
115
  else
123
116
  path_ = "#{@normal_path}.#{@preferred_handle-handle_-1}"
124
117
  end
125
- file_ = ::File.open(path_, @mode)
118
+ file_ = ::File.open(path_, 'a')
126
119
  file_.sync = true
127
120
  @open_handles[handle_] = true
128
121
  file_
@@ -34,12 +34,19 @@
34
34
  ;
35
35
 
36
36
 
37
+ begin
38
+ require 'versionomy'
39
+ rescue ::LoadError
40
+ end
41
+
42
+
37
43
  module Sawmill
38
44
 
39
45
  # Current gem version, as a frozen string.
40
- VERSION_STRING = '0.0.4'.freeze
46
+ VERSION_STRING = '0.0.5'.freeze
41
47
 
42
- # Current gem version, as a Versionomy::Value.
43
- VERSION = ::Versionomy.parse(VERSION_STRING, :standard)
48
+ # Current gem version, as a Versionomy::Value if the versionomy library
49
+ # is available, or as a frozen string if not.
50
+ VERSION = defined?(::Versionomy) ? ::Versionomy.parse(VERSION_STRING, :standard) : VERSION_STRING
44
51
 
45
52
  end
@@ -33,6 +33,7 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
37
38
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
38
39
 
@@ -33,6 +33,7 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
37
38
  require 'stringio'
38
39
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
@@ -33,6 +33,7 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
37
38
  require 'logger'
38
39
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
@@ -33,6 +33,7 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
37
38
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
38
39
 
@@ -33,6 +33,7 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
37
38
  require 'stringio'
38
39
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
@@ -33,6 +33,7 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
37
38
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
38
39
 
@@ -33,7 +33,9 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
38
+ require 'set'
37
39
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
38
40
 
39
41
 
@@ -108,7 +110,7 @@ module Sawmill
108
110
  record_ = @records.dequeue
109
111
  assert_equal(0, record_.message_count)
110
112
  assert_equal(5, record_.entry_count)
111
- assert_equal(Set.new(['color', 'size']), Set.new(record_.attribute_keys))
113
+ assert_equal(::Set.new(['color', 'size']), ::Set.new(record_.attribute_keys))
112
114
  assert_equal('small', record_.attribute('size'))
113
115
  assert_equal('red', record_.attribute('color'))
114
116
  end
@@ -125,7 +127,7 @@ module Sawmill
125
127
  record_ = @records.dequeue
126
128
  assert_equal(0, record_.message_count)
127
129
  assert_equal(5, record_.entry_count)
128
- assert_equal(Set.new(['color', 'size']), Set.new(record_.attribute_keys))
130
+ assert_equal(::Set.new(['color', 'size']), ::Set.new(record_.attribute_keys))
129
131
  assert_equal(['small'], record_.attribute('size'))
130
132
  assert_equal(['blue', 'red'], record_.attribute('color'))
131
133
  end
@@ -33,6 +33,7 @@
33
33
  # -----------------------------------------------------------------------------
34
34
 
35
35
 
36
+ require 'rubygems'
36
37
  require 'test/unit'
37
38
  require 'stringio'
38
39
  require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sawmill
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-06 00:00:00 -08:00
12
+ date: 2009-11-08 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,17 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.3.0
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: versionomy
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 0.2.0
23
+ version: 0.3.1
34
24
  version:
35
25
  description: Sawmill is a logging and log analysis system for Ruby. It extends the basic Ruby logging facility with log records and parsing abilities.
36
26
  email: dazuma@gmail.com