sawmill 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/History.rdoc +17 -0
  2. data/lib/sawmill/entry.rb +17 -1
  3. data/lib/sawmill/entry_processor/build_records.rb +10 -7
  4. data/lib/sawmill/entry_processor/compile_report.rb +115 -0
  5. data/lib/sawmill/entry_processor/conditionals.rb +22 -23
  6. data/lib/sawmill/entry_processor/count_entries.rb +112 -0
  7. data/lib/sawmill/entry_processor/{filter_basic_fields.rb → filter_by_basic_fields.rb} +3 -3
  8. data/lib/sawmill/entry_processor/filter_by_block.rb +96 -0
  9. data/lib/sawmill/entry_processor/format.rb +9 -1
  10. data/lib/sawmill/entry_processor/simple_queue.rb +2 -1
  11. data/lib/sawmill/entry_processor.rb +68 -5
  12. data/lib/sawmill/errors.rb +7 -0
  13. data/lib/sawmill/interface.rb +324 -0
  14. data/lib/sawmill/logger.rb +8 -7
  15. data/lib/sawmill/record.rb +14 -0
  16. data/lib/sawmill/record_processor/compile_report.rb +113 -0
  17. data/lib/sawmill/record_processor/conditionals.rb +12 -13
  18. data/lib/sawmill/record_processor/count_records.rb +84 -0
  19. data/lib/sawmill/record_processor/decompose.rb +2 -2
  20. data/lib/sawmill/record_processor/filter_by_attributes.rb +2 -1
  21. data/lib/sawmill/record_processor/filter_by_block.rb +95 -0
  22. data/lib/sawmill/record_processor/filter_by_record_id.rb +2 -1
  23. data/lib/sawmill/record_processor/format.rb +8 -2
  24. data/lib/sawmill/record_processor/simple_queue.rb +2 -1
  25. data/lib/sawmill/record_processor.rb +69 -5
  26. data/lib/sawmill/rotater/date_based_log_file.rb +8 -8
  27. data/lib/sawmill/rotater/shifting_log_file.rb +7 -6
  28. data/lib/sawmill/util/processor_tools.rb +71 -0
  29. data/lib/sawmill/version.rb +1 -3
  30. data/lib/sawmill.rb +9 -1
  31. data/tests/tc_entry_processors.rb +7 -7
  32. data/tests/tc_reports.rb +101 -0
  33. metadata +13 -3
data/History.rdoc CHANGED
@@ -1,3 +1,20 @@
1
+ === 0.0.3 / 2009-10-31
2
+
3
+ * API CHANGE: Renamed processor close methods to "finish" and introduced return value semantics for passing "final" information back up the processor tree.
4
+ * API CHANGE: Renamed :dirname options to :basedir on both rotater strategies
5
+ * API CHANGE: Renamed :filename option to :filepath on ShiftingLogFile
6
+ * API CHANGE: Renamed :local_timezone option to :local_datestamps on DateBasedLogFile
7
+ * API CHANGE: Renamed FilterBasicFields to FilterByBasicFields
8
+ * Added FilterByBlock processors
9
+ * Added CompileReport processors
10
+ * Processors can now add custom methods to the processor building DSL.
11
+ * Added a bunch of convenience methods to the toplevel Sawmill module.
12
+ * Entries can be truncated at a particular length when formatting.
13
+ * Records can compute and cache values.
14
+ * Support length limits when formatting entries.
15
+ * Fixed a few more bugs related to processors.
16
+ * More work on the RDocs
17
+
1
18
  === 0.0.2 / 2009-10-28
2
19
 
3
20
  * Added multi-parser utility.
data/lib/sawmill/entry.rb CHANGED
@@ -103,12 +103,16 @@ module Sawmill
103
103
 
104
104
  # The log level as a Sawmill::Level object
105
105
  attr_reader :level
106
+
106
107
  # The timestamp as a Time object
107
108
  attr_reader :timestamp
109
+
108
110
  # The progname as a string
109
111
  attr_reader :progname
112
+
110
113
  # The record ID as a string
111
114
  attr_reader :record_id
115
+
112
116
  # The message as a string
113
117
  attr_reader :message
114
118
 
@@ -157,10 +161,13 @@ module Sawmill
157
161
 
158
162
  # The log level as a Sawmill::Level object
159
163
  attr_reader :level
164
+
160
165
  # The timestamp as a Time object
161
166
  attr_reader :timestamp
167
+
162
168
  # The progname as a string
163
169
  attr_reader :progname
170
+
164
171
  # The record ID as a string
165
172
  attr_reader :record_id
166
173
 
@@ -207,10 +214,13 @@ module Sawmill
207
214
 
208
215
  # The log level as a Sawmill::Level object
209
216
  attr_reader :level
217
+
210
218
  # The timestamp as a Time object
211
219
  attr_reader :timestamp
220
+
212
221
  # The progname as a string
213
222
  attr_reader :progname
223
+
214
224
  # The record ID as a string
215
225
  attr_reader :record_id
216
226
 
@@ -263,16 +273,22 @@ module Sawmill
263
273
 
264
274
  # The log level as a Sawmill::Level object
265
275
  attr_reader :level
276
+
266
277
  # The timestamp as a Time object
267
278
  attr_reader :timestamp
279
+
268
280
  # The progname as a string
269
281
  attr_reader :progname
282
+
270
283
  # The record ID as a string
271
284
  attr_reader :record_id
272
- # The operation, which can be :set, :append, :remove, :unset
285
+
286
+ # The operation, which can currently be :set or :append
273
287
  attr_reader :operation
288
+
274
289
  # The attribute key as a string
275
290
  attr_reader :key
291
+
276
292
  # The attribute value as a string
277
293
  attr_reader :value
278
294
 
@@ -49,15 +49,15 @@ module Sawmill
49
49
  #
50
50
  # Recognized options include:
51
51
  #
52
- # <tt>:emit_incomplete_records_on_close</tt>::
53
- # When the processor is closed, any records that are still not
52
+ # <tt>:emit_incomplete_records_on_finish</tt>::
53
+ # When the processor is finished, any records that are still not
54
54
  # complete will be emitted to the record processor anyway, even
55
55
  # in their incomplete state.
56
56
 
57
57
  def initialize(processor_, opts_={})
58
58
  @processor = processor_
59
59
  @records = {}
60
- @emit_incomplete_records_on_close = opts_[:emit_incomplete_records_on_close]
60
+ @emit_incomplete_records_on_finish = opts_[:emit_incomplete_records_on_finish]
61
61
  end
62
62
 
63
63
 
@@ -135,11 +135,14 @@ module Sawmill
135
135
  end
136
136
 
137
137
 
138
- def close
139
- if @records && @emit_incomplete_records_on_close
140
- emit_incomplete_records
138
+ def finish
139
+ if @records
140
+ emit_incomplete_records if @emit_incomplete_records_on_close
141
+ @records = nil
142
+ @processor.finish
143
+ else
144
+ nil
141
145
  end
142
- @records = nil
143
146
  end
144
147
 
145
148
 
@@ -0,0 +1,115 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Sawmill entry processor that generates reports
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
+ module Sawmill
38
+
39
+
40
+ module EntryProcessor
41
+
42
+
43
+ # This processor collects and formats reports from descendant
44
+ # entry processors.
45
+
46
+ class CompileReport < All
47
+
48
+
49
+ # Create a report collection.
50
+ #
51
+ # Recognized options include:
52
+ #
53
+ # <tt>:postprocessor</tt>::
54
+ # Postprocessor proc for individual reports.
55
+ # See to_postprocess_value.
56
+ # <tt>:separator</tt>::
57
+ # Separator string to be inserted between individual reports.
58
+ # Default is a single newline.
59
+ # <tt>:header</tt>::
60
+ # Header string for the final compiled report.
61
+ # Default is the empty string.
62
+ # <tt>:footer</tt>::
63
+ # Footer string for the final compiled report.
64
+ # Default is the empty string.
65
+
66
+ def initialize(*children_)
67
+ opts_ = children_.last.kind_of?(::Hash) ? children_.pop : {}
68
+ @postprocessor = opts_[:postprocessor]
69
+ @separator = opts_[:separator] || "\n"
70
+ @header = opts_[:header] || ''
71
+ @footer = opts_[:footer] || ''
72
+ super(*children_)
73
+ end
74
+
75
+
76
+ # Separator string to be inserted between individual reports.
77
+ attr_accessor :separator
78
+
79
+ # Header string for the final compiled report.
80
+ attr_accessor :header
81
+
82
+ # Footer string for the final compiled report.
83
+ attr_accessor :footer
84
+
85
+
86
+ # Provide a postprocessor block for individual report values.
87
+ # This block should take a single parameter and return a string
88
+ # that should be included in the compiled report. It may also
89
+ # return nil to indicate that the data should not be included.
90
+
91
+ def to_postprocess_value(&block_)
92
+ @postprocessor = block_
93
+ end
94
+
95
+
96
+ # On finish, this processor calls finish on its descendants, converts
97
+ # their values into strings and compiles them into a report. It then
98
+ # returns that report as a string.
99
+
100
+ def finish
101
+ values_ = super || []
102
+ values_ = [values_] unless values_.kind_of?(::Array)
103
+ values_.map!{ |val_| @postprocessor.call(val_) } if @postprocessor
104
+ values_.compact!
105
+ "#{@header}#{values_.join(@separator)}#{@footer}"
106
+ end
107
+
108
+
109
+ end
110
+
111
+
112
+ end
113
+
114
+
115
+ end
@@ -48,7 +48,7 @@ module Sawmill
48
48
  # to STDOUT only if their level is at least INFO:
49
49
  #
50
50
  # processor = Sawmill::EntryProcessor.build do
51
- # If(FilterBasicFields(:level => :INFO), Format(STDOUT))
51
+ # If(FilterByBasicFields(:level => :INFO), Format(STDOUT))
52
52
  # end
53
53
 
54
54
  class If < Base
@@ -108,9 +108,8 @@ module Sawmill
108
108
  end
109
109
  end
110
110
 
111
- def close
112
- @on_true.close
113
- @on_false.close if @on_false
111
+ def finish
112
+ Util::ProcessorTools.collect_finish_values([@on_true, @on_false])
114
113
  end
115
114
 
116
115
 
@@ -124,7 +123,7 @@ module Sawmill
124
123
  # to STDOUT only if their level is NOT at least INFO:
125
124
  #
126
125
  # processor = Sawmill::EntryProcessor.build do
127
- # If(Not(FilterBasicFields(:level => :INFO)), Format(STDOUT))
126
+ # If(Not(FilterByBasicFields(:level => :INFO)), Format(STDOUT))
128
127
  # end
129
128
 
130
129
  class Not < Base
@@ -158,8 +157,8 @@ module Sawmill
158
157
  !@child.unknown_data(entry_)
159
158
  end
160
159
 
161
- def close
162
- @child.close
160
+ def finish
161
+ @child.finish
163
162
  end
164
163
 
165
164
 
@@ -176,8 +175,8 @@ module Sawmill
176
175
  # is "rails":
177
176
  #
178
177
  # processor = Sawmill::EntryProcessor.build do
179
- # If(And(FilterBasicFields(:level => :INFO),
180
- # FilterBasicFields(:progname => 'rails')),
178
+ # If(And(FilterByBasicFields(:level => :INFO),
179
+ # FilterByBasicFields(:progname => 'rails')),
181
180
  # Format(STDOUT))
182
181
  # end
183
182
 
@@ -227,8 +226,8 @@ module Sawmill
227
226
  true
228
227
  end
229
228
 
230
- def close
231
- @children.each{ |forward_| forward_.close }
229
+ def finish
230
+ Util::ProcessorTools.collect_finish_values(@children)
232
231
  end
233
232
 
234
233
 
@@ -245,8 +244,8 @@ module Sawmill
245
244
  # "rails":
246
245
  #
247
246
  # processor = Sawmill::EntryProcessor.build do
248
- # If(Or(FilterBasicFields(:level => :INFO),
249
- # FilterBasicFields(:progname => 'rails')),
247
+ # If(Or(FilterByBasicFields(:level => :INFO),
248
+ # FilterByBasicFields(:progname => 'rails')),
250
249
  # Format(STDOUT))
251
250
  # end
252
251
 
@@ -296,8 +295,8 @@ module Sawmill
296
295
  false
297
296
  end
298
297
 
299
- def close
300
- @children.each{ |forward_| forward_.close }
298
+ def finish
299
+ Util::ProcessorTools.collect_finish_values(@children)
301
300
  end
302
301
 
303
302
 
@@ -315,8 +314,8 @@ module Sawmill
315
314
  # "rails":
316
315
  #
317
316
  # processor = Sawmill::EntryProcessor.build do
318
- # If(All(FilterBasicFields(:level => :INFO),
319
- # FilterBasicFields(:progname => 'rails')),
317
+ # If(All(FilterByBasicFields(:level => :INFO),
318
+ # FilterByBasicFields(:progname => 'rails')),
320
319
  # Format(STDOUT))
321
320
  # end
322
321
  #
@@ -367,8 +366,8 @@ module Sawmill
367
366
  end
368
367
  end
369
368
 
370
- def close
371
- @children.each{ |forward_| forward_.close }
369
+ def finish
370
+ Util::ProcessorTools.collect_finish_values(@children)
372
371
  end
373
372
 
374
373
 
@@ -385,8 +384,8 @@ module Sawmill
385
384
  # "rails":
386
385
  #
387
386
  # processor = Sawmill::EntryProcessor.build do
388
- # If(Any(FilterBasicFields(:level => :INFO),
389
- # FilterBasicFields(:progname => 'rails')),
387
+ # If(Any(FilterByBasicFields(:level => :INFO),
388
+ # FilterByBasicFields(:progname => 'rails')),
390
389
  # Format(STDOUT))
391
390
  # end
392
391
 
@@ -431,8 +430,8 @@ module Sawmill
431
430
  end
432
431
  end
433
432
 
434
- def close
435
- @children.each{ |forward_| forward_.close }
433
+ def finish
434
+ Util::ProcessorTools.collect_finish_values(@children)
436
435
  end
437
436
 
438
437
 
@@ -0,0 +1,112 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Sawmill entry processor that generates reports
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
+ module Sawmill
38
+
39
+ module EntryProcessor
40
+
41
+
42
+ # This processor reports the number of entries processed.
43
+
44
+ class CountEntries < Base
45
+
46
+
47
+ # Create a count-entries report.
48
+ #
49
+ # Recognized options include:
50
+ #
51
+ # <tt>:label</tt>::
52
+ # Label to use for the report.
53
+ # If provided, the report is returned as a string of the form
54
+ # "#{label}#{value}"
55
+ # If set to nil or absent, the report is returned as an integer.
56
+ # <tt>:omit_unknown_data</tt>::
57
+ # If set to true, omits unknown_data from the count.
58
+ # Default is false.
59
+ # <tt>:omit_attributes</tt>::
60
+ # If set to true, omits attributes from the count.
61
+ # Default is false.
62
+ # <tt>:omit_record_delimiters</tt>::
63
+ # If set to true, omits begin_record and end_record from the count.
64
+ # Default is false.
65
+
66
+ def initialize(opts_={})
67
+ @label = opts_[:label]
68
+ @omit_unknown_data = opts_[:omit_unknown_data]
69
+ @omit_attributes = opts_[:omit_attributes]
70
+ @omit_record_delimiters = opts_[:omit_record_delimiters]
71
+ @finished = false
72
+ @count = 0
73
+ end
74
+
75
+
76
+ def begin_record(entry_)
77
+ @count += 1 unless @finished || @omit_record_delimiters
78
+ true
79
+ end
80
+
81
+ def end_record(entry_)
82
+ @count += 1 unless @finished || @omit_record_delimiters
83
+ true
84
+ end
85
+
86
+ def message(entry_)
87
+ @count += 1 unless @finished
88
+ true
89
+ end
90
+
91
+ def attribute(entry_)
92
+ @count += 1 unless @finished || @omit_attributes
93
+ true
94
+ end
95
+
96
+ def unknown_data(entry_)
97
+ @count += 1 unless @finished || @omit_unknown_data
98
+ true
99
+ end
100
+
101
+ def finish
102
+ @finished = true
103
+ @label ? "#{@label}#{@count}" : @count
104
+ end
105
+
106
+
107
+ end
108
+
109
+
110
+ end
111
+
112
+ end
@@ -45,7 +45,7 @@ module Sawmill
45
45
  # on the filter result. Use this in conjunction with an If processor to
46
46
  # actually perform other actions based on the result.
47
47
 
48
- class FilterBasicFields < Base
48
+ class FilterByBasicFields < Base
49
49
 
50
50
 
51
51
  # Create a new filter.
@@ -108,8 +108,8 @@ module Sawmill
108
108
  @accept_unknown
109
109
  end
110
110
 
111
-
112
- def close
111
+ def finish
112
+ nil
113
113
  end
114
114
 
115
115
 
@@ -0,0 +1,96 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Sawmill entry processor that calls a block
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
+ module Sawmill
38
+
39
+ module EntryProcessor
40
+
41
+
42
+ # A entry filter that calls a block to perform its check.
43
+ #
44
+ # This is a boolean processor, so it merely returns true or false based
45
+ # on the filter result. Use this in conjunction with an If processor to
46
+ # actually perform other actions based on the result.
47
+
48
+ class FilterByBlock < Base
49
+
50
+
51
+ # Create a new filter. Provide the block, which should take an entry
52
+ # object as the parameter and return a boolean.
53
+
54
+ def initialize(&block_)
55
+ to_filter_entry(&block_)
56
+ end
57
+
58
+
59
+ # Provide a block to filter entries. It should take an entry object
60
+ # as the parameter, and return a boolean.
61
+
62
+ def to_filter_entry(&block_)
63
+ @block = block_ || Proc.new{ |entry_| false }
64
+ end
65
+
66
+
67
+ def begin_record(entry_)
68
+ @block.call(entry_)
69
+ end
70
+
71
+ def end_record(entry_)
72
+ @block.call(entry_)
73
+ end
74
+
75
+ def message(entry_)
76
+ @block.call(entry_)
77
+ end
78
+
79
+ def attribute(entry_)
80
+ @block.call(entry_)
81
+ end
82
+
83
+ def unknown_data(entry_)
84
+ @block.call(entry_)
85
+ end
86
+
87
+ def finish
88
+ nil
89
+ end
90
+
91
+ end
92
+
93
+
94
+ end
95
+
96
+ end
@@ -65,6 +65,9 @@ module Sawmill
65
65
  # <tt>:iso_8601_time</tt>::
66
66
  # If true, outputs time in strict ISO 8601 format.
67
67
  # If false (the default), outputs a slightly more readable format.
68
+ # <tt>:length_limit</tt>::
69
+ # Limit to the entry length. Entries are truncated to this length
70
+ # when written. If not specified, entries are not truncated.
68
71
 
69
72
  def initialize(destination_, opts_={})
70
73
  if destination_.kind_of?(Rotater)
@@ -83,6 +86,7 @@ module Sawmill
83
86
  @usec_factor = 1
84
87
  (6 - @fractional_second_digits).times{ @usec_factor *= 10 }
85
88
  @level_width = opts_[:level_width]
89
+ @length_limit = opts_[:length_limit]
86
90
  end
87
91
 
88
92
 
@@ -143,7 +147,7 @@ module Sawmill
143
147
  true
144
148
  end
145
149
 
146
- def close
150
+ def finish
147
151
  if @rotater
148
152
  @default_channel.close
149
153
  @channels.values.each{ |channel_| channel_.close }
@@ -152,6 +156,7 @@ module Sawmill
152
156
  @io.close
153
157
  @io = nil
154
158
  end
159
+ nil
155
160
  end
156
161
 
157
162
  private
@@ -211,6 +216,9 @@ module Sawmill
211
216
  end
212
217
  levelstr_ = entry_.level.name.to_s
213
218
  levelstr_ = levelstr_.rjust(@level_width) if @level_width
219
+ if @length_limit && @length_limit < str_.length
220
+ str_ = str_[0, @length_limit] + "... (and #{str_.length-@length_limit} more characters) ..."
221
+ end
214
222
  "[#{levelstr_} #{timestr_} #{entry_.progname}#{id_} #{marker_}] #{str_}\n"
215
223
  end
216
224
 
@@ -109,8 +109,9 @@ module Sawmill
109
109
  !@closed
110
110
  end
111
111
 
112
- def close
112
+ def finish
113
113
  @closed = true
114
+ nil
114
115
  end
115
116
 
116
117