sawmill 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +6 -0
- data/Rakefile +8 -8
- data/lib/sawmill/entry_processor/filter_basic_fields.rb +1 -1
- data/lib/sawmill/entry_processor/format.rb +2 -2
- data/lib/sawmill/entry_processor/simple_queue.rb +7 -0
- data/lib/sawmill/entry_processor.rb +2 -2
- data/lib/sawmill/log_record_middleware.rb +3 -3
- data/lib/sawmill/logger.rb +27 -24
- data/lib/sawmill/multi_parser.rb +127 -0
- data/lib/sawmill/parser.rb +6 -7
- data/lib/sawmill/record.rb +12 -2
- data/lib/sawmill/record_processor/decompose.rb +1 -1
- data/lib/sawmill/record_processor/filter_by_attributes.rb +2 -2
- data/lib/sawmill/record_processor/simple_queue.rb +14 -0
- data/lib/sawmill/record_processor.rb +2 -2
- data/lib/sawmill/rotater/base.rb +1 -1
- data/lib/sawmill/rotater/date_based_log_file.rb +4 -4
- data/lib/sawmill/rotater/shifting_log_file.rb +11 -11
- data/lib/sawmill/rotater.rb +2 -2
- data/lib/sawmill/util/heap.rb +153 -0
- data/lib/sawmill/util/queue.rb +27 -1
- data/lib/sawmill/version.rb +1 -1
- data/lib/sawmill.rb +2 -0
- data/tests/tc_multi_parser.rb +88 -0
- metadata +8 -4
data/History.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -80,7 +80,7 @@ gemspec_ = ::Gem::Specification.new do |s_|
|
|
80
80
|
s_.author = 'Daniel Azuma'
|
81
81
|
s_.email = 'dazuma@gmail.com'
|
82
82
|
s_.description = 'Sawmill is a logging and log analysis system for Ruby. It extends the basic Ruby logging facility with log records and parsing abilities.'
|
83
|
-
s_.homepage = 'http://
|
83
|
+
s_.homepage = 'http://virtuoso.rubyforge.org/sawmill'
|
84
84
|
s_.rubyforge_project = 'virtuoso'
|
85
85
|
s_.required_ruby_version = '>= 1.8.6'
|
86
86
|
s_.files = ::FileList['lib/**/*.rb', 'tests/**/*.rb', '*.rdoc', 'Rakefile'].to_a
|
@@ -88,8 +88,8 @@ 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.2.
|
92
|
-
s_.add_dependency('versionomy', '>= 0.1.
|
91
|
+
s_.add_dependency('blockenspiel', '>= 0.2.2')
|
92
|
+
s_.add_dependency('versionomy', '>= 0.1.2')
|
93
93
|
end
|
94
94
|
::Rake::GemPackageTask.new(gemspec_) do |task_|
|
95
95
|
task_.need_zip = false
|
@@ -106,8 +106,8 @@ task :publish_rdoc_to_rubyforge => [:rerdoc] do
|
|
106
106
|
end
|
107
107
|
|
108
108
|
|
109
|
-
#
|
110
|
-
task :
|
109
|
+
# Release gem ro rubyforge
|
110
|
+
task :release_gem_to_rubyforge => [:package] do |t_|
|
111
111
|
v_ = ::ENV["VERSION"]
|
112
112
|
abort "Must supply VERSION=x.y.z" unless v_
|
113
113
|
if v_ != ::Sawmill::VERSION_STRING
|
@@ -131,8 +131,8 @@ task :publish_gem_to_rubyforge => [:package] do |t_|
|
|
131
131
|
end
|
132
132
|
|
133
133
|
|
134
|
-
#
|
135
|
-
task :
|
134
|
+
# Release gem to gemcutter
|
135
|
+
task :release_gem_to_gemcutter => [:package] do |t_|
|
136
136
|
v_ = ::ENV["VERSION"]
|
137
137
|
abort "Must supply VERSION=x.y.z" unless v_
|
138
138
|
if v_ != ::Sawmill::VERSION_STRING
|
@@ -144,4 +144,4 @@ end
|
|
144
144
|
|
145
145
|
|
146
146
|
# Publish everything
|
147
|
-
task :
|
147
|
+
task :release => [:release_gem_to_gemcutter, :release_gem_to_rubyforge, :publish_rdoc_to_rubyforge]
|
@@ -119,7 +119,7 @@ module Sawmill
|
|
119
119
|
def _check_filter(entry_) # :nodoc:
|
120
120
|
if @level
|
121
121
|
level_ = entry_.level
|
122
|
-
if @level.kind_of?(
|
122
|
+
if @level.kind_of?(Level)
|
123
123
|
check_level_ = @level
|
124
124
|
if level_.group != check_level_.group
|
125
125
|
return false unless @accept_incomparable_levels
|
@@ -74,7 +74,7 @@ module Sawmill
|
|
74
74
|
elsif destination_.respond_to?(:close) && destination_.respond_to?(:write)
|
75
75
|
@io = destination_
|
76
76
|
else
|
77
|
-
raise ArgumentError, "Unknown destination type"
|
77
|
+
raise ::ArgumentError, "Unknown destination type"
|
78
78
|
end
|
79
79
|
@include_id = opts_[:include_id]
|
80
80
|
@fractional_second_digits = (opts_[:fractional_second_digits] || 2).to_i
|
@@ -139,7 +139,7 @@ module Sawmill
|
|
139
139
|
|
140
140
|
def unknown_data(entry_)
|
141
141
|
return false unless @io || @rotater
|
142
|
-
_write_str(entry_.line+"\n",
|
142
|
+
_write_str(entry_.line+"\n", nil)
|
143
143
|
true
|
144
144
|
end
|
145
145
|
|
@@ -130,12 +130,12 @@ module Sawmill
|
|
130
130
|
|
131
131
|
def _interpret_processor(param_) # :nodoc:
|
132
132
|
case param_
|
133
|
-
when Class
|
133
|
+
when ::Class
|
134
134
|
param_.new
|
135
135
|
when Base
|
136
136
|
param_
|
137
137
|
else
|
138
|
-
raise ArgumentError, "Unknown processor object of type #{param_.class.name}"
|
138
|
+
raise ::ArgumentError, "Unknown processor object of type #{param_.class.name}"
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
@@ -62,7 +62,7 @@ module Sawmill
|
|
62
62
|
|
63
63
|
def initialize(app_, logger_=nil, opts_={})
|
64
64
|
@app = app_
|
65
|
-
@logger = logger_ || Logger.new(:progname => 'rack', :processor =>
|
65
|
+
@logger = logger_ || Logger.new(:progname => 'rack', :processor => Formatter.new(::STDOUT))
|
66
66
|
@request_id_key = opts_[:request_id_key] || 'sawmill.request_id'
|
67
67
|
@start_time_attribute = opts_[:start_time_attribute]
|
68
68
|
@end_time_attribute = opts_[:end_time_attribute]
|
@@ -72,14 +72,14 @@ module Sawmill
|
|
72
72
|
def call(env_)
|
73
73
|
env_[@request_id_key] = @logger.begin_record
|
74
74
|
if @start_time_attribute
|
75
|
-
time_ = Time.now.utc
|
75
|
+
time_ = ::Time.now.utc
|
76
76
|
@logger.set_attribute(@start_time_attribute, time_.strftime('%Y-%m-%dT%H:%M:%S.') + ('%06d' % time_.usec) + 'Z')
|
77
77
|
end
|
78
78
|
begin
|
79
79
|
return @app.call(env_)
|
80
80
|
ensure
|
81
81
|
if @end_time_attribute
|
82
|
-
time_ = Time.now.utc
|
82
|
+
time_ = ::Time.now.utc
|
83
83
|
@logger.set_attribute(@end_time_attribute, time_.strftime('%Y-%m-%dT%H:%M:%S.') + ('%06d' % time_.usec) + 'Z')
|
84
84
|
end
|
85
85
|
@logger.end_record
|
data/lib/sawmill/logger.rb
CHANGED
@@ -34,8 +34,9 @@
|
|
34
34
|
;
|
35
35
|
|
36
36
|
|
37
|
-
|
37
|
+
begin
|
38
38
|
require 'securerandom'
|
39
|
+
rescue ::LoadError
|
39
40
|
end
|
40
41
|
|
41
42
|
|
@@ -80,7 +81,7 @@ module Sawmill
|
|
80
81
|
# If not specified, log entries are written out to STDOUT.
|
81
82
|
|
82
83
|
def initialize(opts_={})
|
83
|
-
@levels = opts_[:levels] ||
|
84
|
+
@levels = opts_[:levels] || STANDARD_LEVELS
|
84
85
|
@level = @levels.get(opts_[:level])
|
85
86
|
if opts_.include?(:attribute_level)
|
86
87
|
@attribute_level = @levels.get(opts_[:attribute_level])
|
@@ -89,8 +90,8 @@ module Sawmill
|
|
89
90
|
end
|
90
91
|
@progname = opts_[:progname] || 'sawmill'
|
91
92
|
@record_progname = opts_[:record_progname] || @progname
|
92
|
-
@record_id_generator = opts_[:record_id_generator] || _get_default_record_id_generator
|
93
|
-
@processor = opts_[:processor] ||
|
93
|
+
@record_id_generator = opts_[:record_id_generator] || Logger._get_default_record_id_generator
|
94
|
+
@processor = opts_[:processor] || Formatter.new(::STDOUT)
|
94
95
|
@current_record_id = nil
|
95
96
|
end
|
96
97
|
|
@@ -122,7 +123,7 @@ module Sawmill
|
|
122
123
|
else
|
123
124
|
message_ = message_.inspect
|
124
125
|
end
|
125
|
-
@processor.message(Entry::Message.new(level_obj_, Time.now, progname_, @current_record_id, message_))
|
126
|
+
@processor.message(Entry::Message.new(level_obj_, ::Time.now, progname_, @current_record_id, message_))
|
126
127
|
true
|
127
128
|
end
|
128
129
|
alias_method :log, :add
|
@@ -161,7 +162,7 @@ module Sawmill
|
|
161
162
|
def begin_record(id_=nil)
|
162
163
|
end_record if @current_record_id
|
163
164
|
@current_record_id = (id_ || @record_id_generator.call).to_s
|
164
|
-
@processor.begin_record(Entry::BeginRecord.new(@levels.highest, Time.now, @record_progname, @current_record_id))
|
165
|
+
@processor.begin_record(Entry::BeginRecord.new(@levels.highest, ::Time.now, @record_progname, @current_record_id))
|
165
166
|
@current_record_id
|
166
167
|
end
|
167
168
|
|
@@ -180,7 +181,7 @@ module Sawmill
|
|
180
181
|
|
181
182
|
def end_record
|
182
183
|
if @current_record_id
|
183
|
-
@processor.end_record(Entry::EndRecord.new(@levels.highest, Time.now, @record_progname, @current_record_id))
|
184
|
+
@processor.end_record(Entry::EndRecord.new(@levels.highest, ::Time.now, @record_progname, @current_record_id))
|
184
185
|
id_ = @current_record_id
|
185
186
|
@current_record_id = nil
|
186
187
|
id_
|
@@ -209,7 +210,7 @@ module Sawmill
|
|
209
210
|
end
|
210
211
|
end
|
211
212
|
return true if level_obj_ < @level
|
212
|
-
@processor.attribute(Entry::Attribute.new(level_obj_, Time.now, progname_ || @record_progname, @current_record_id, key_, value_, operation_))
|
213
|
+
@processor.attribute(Entry::Attribute.new(level_obj_, ::Time.now, progname_ || @record_progname, @current_record_id, key_, value_, operation_))
|
213
214
|
true
|
214
215
|
end
|
215
216
|
|
@@ -288,7 +289,7 @@ module Sawmill
|
|
288
289
|
# a default generator which uses the variant 4 (random) UUID standard.
|
289
290
|
|
290
291
|
def to_generate_record_id(&block_)
|
291
|
-
@record_id_generator = block_ || _get_default_record_id_generator
|
292
|
+
@record_id_generator = block_ || Logger._get_default_record_id_generator
|
292
293
|
end
|
293
294
|
|
294
295
|
|
@@ -339,21 +340,23 @@ module Sawmill
|
|
339
340
|
end
|
340
341
|
|
341
342
|
|
342
|
-
def _get_default_record_id_generator # :nodoc:
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
343
|
+
def self._get_default_record_id_generator # :nodoc:
|
344
|
+
unless @_default_generator
|
345
|
+
if defined?(::SecureRandom)
|
346
|
+
def self._random_hex32
|
347
|
+
::SecureRandom.hex(32)
|
348
|
+
end
|
349
|
+
elsif defined?(::ActiveSupport::SecureRandom)
|
350
|
+
def self._random_hex32
|
351
|
+
::ActiveSupport::SecureRandom.hex(32)
|
352
|
+
end
|
353
|
+
else
|
354
|
+
def self._random_hex32
|
355
|
+
::Kernel.rand(0x100000000000000000000000000000000).to_s(16).rjust(32, '0')
|
356
|
+
end
|
353
357
|
end
|
354
|
-
|
355
|
-
|
356
|
-
uuid_ = Kernel.rand(0x100000000000000000000000000000000).to_s(16).rjust(32, '0')
|
358
|
+
@_default_generator = ::Proc.new do
|
359
|
+
uuid_ = _random_hex32
|
357
360
|
uuid_[12] = '4'
|
358
361
|
uuid_[16] = (uuid_[16,1].to_i(16)&3|8).to_s(16)
|
359
362
|
uuid_.insert(8, '-')
|
@@ -363,8 +366,8 @@ module Sawmill
|
|
363
366
|
uuid_
|
364
367
|
end
|
365
368
|
end
|
369
|
+
@_default_generator
|
366
370
|
end
|
367
|
-
private :_get_default_record_id_generator
|
368
371
|
|
369
372
|
|
370
373
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Sawmill multi-stream parser utility
|
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
|
+
# A logfile parser that parses log entries from multiple logfile streams,
|
41
|
+
# sorts by timestamp, and sends them to a processor.
|
42
|
+
|
43
|
+
class MultiParser
|
44
|
+
|
45
|
+
|
46
|
+
# Create a new parser that reads from the given streams.
|
47
|
+
#
|
48
|
+
# You should provide a processor to receive the data from the logfile.
|
49
|
+
# The processor may be either an entry processor or a record processor.
|
50
|
+
# You may also pass nil for the processor. In this case, the generated
|
51
|
+
# log entries will not be sent to a processor but will still be returned
|
52
|
+
# by the parse_one_entry method.
|
53
|
+
#
|
54
|
+
# Recognized options include:
|
55
|
+
#
|
56
|
+
# <tt>:levels</tt>
|
57
|
+
# Sawmill::LevelGroup to use to parse log levels.
|
58
|
+
# If not specified, Sawmill::STANDARD_LEVELS is used by default.
|
59
|
+
# <tt>:emit_incomplete_records_at_eof</tt>
|
60
|
+
# If set to true, causes any incomplete log records to be emitted
|
61
|
+
# in their incomplete state when EOF is reached on all streams.
|
62
|
+
|
63
|
+
def initialize(io_array_, processor_, opts_={})
|
64
|
+
@emit_incomplete_records_at_eof = opts_.delete(:emit_incomplete_records_at_eof)
|
65
|
+
@heap = Util::Heap.new{ |a_, b_| a_[1].timestamp <=> b_[1].timestamp }
|
66
|
+
@queue = Util::Queue.new
|
67
|
+
io_array_.each{ |io_| _enqueue(Parser.new(io_, nil, opts_)) }
|
68
|
+
@processor = nil
|
69
|
+
if processor_.respond_to?(:record) && processor_.respond_to?(:extra_entry)
|
70
|
+
@processor = RecordBuilder.new(processor_)
|
71
|
+
elsif processor_.respond_to?(:begin_record) && processor_.respond_to?(:end_record)
|
72
|
+
@processor = processor_
|
73
|
+
end
|
74
|
+
@classifier = @processor ? EntryClassifier.new(@processor) : nil
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
# Parse one log entry from the streams and emit it to the processor.
|
79
|
+
# Also returns the log entry.
|
80
|
+
# Returns nil if EOF has been reached on all streams.
|
81
|
+
|
82
|
+
def parse_one_entry
|
83
|
+
entry_ = @queue.dequeue
|
84
|
+
unless entry_
|
85
|
+
data_ = @heap.remove
|
86
|
+
if data_
|
87
|
+
_enqueue(data_[0])
|
88
|
+
entry_ = data_[1]
|
89
|
+
else
|
90
|
+
if @emit_incomplete_records_at_eof && @processor.respond_to?(:emit_incomplete_records)
|
91
|
+
@processor.emit_incomplete_records
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
@classifier.entry(entry_) if entry_
|
96
|
+
entry_
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# Parse until EOF is reached on all streams, and emit the log
|
101
|
+
# entries to the processor.
|
102
|
+
|
103
|
+
def parse_all
|
104
|
+
while parse_one_entry; end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def _enqueue(parser_) # :nodoc:
|
111
|
+
loop do
|
112
|
+
entry_ = parser_.parse_one_entry
|
113
|
+
return unless entry_
|
114
|
+
if entry_.type == :unknown_data
|
115
|
+
@queue.enqueue(entry_)
|
116
|
+
else
|
117
|
+
@heap << [parser_, entry_]
|
118
|
+
return
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
end
|
data/lib/sawmill/parser.rb
CHANGED
@@ -62,21 +62,20 @@ module Sawmill
|
|
62
62
|
# <tt>:levels</tt>
|
63
63
|
# Sawmill::LevelGroup to use to parse log levels.
|
64
64
|
# If not specified, Sawmill::STANDARD_LEVELS is used by default.
|
65
|
-
# <tt>:
|
65
|
+
# <tt>:emit_incomplete_records_at_eof</tt>
|
66
66
|
# If set to true, causes any incomplete log records to be emitted
|
67
67
|
# in their incomplete state when EOF is reached.
|
68
68
|
|
69
69
|
def initialize(io_, processor_, opts_={})
|
70
70
|
@io = io_
|
71
|
-
@record_processor = nil
|
72
71
|
@processor = nil
|
73
72
|
if processor_.respond_to?(:record) && processor_.respond_to?(:extra_entry)
|
74
73
|
@processor = RecordBuilder.new(processor_)
|
75
74
|
elsif processor_.respond_to?(:begin_record) && processor_.respond_to?(:end_record)
|
76
75
|
@processor = processor_
|
77
76
|
end
|
78
|
-
@levels = opts_[:levels] ||
|
79
|
-
@
|
77
|
+
@levels = opts_[:levels] || STANDARD_LEVELS
|
78
|
+
@emit_incomplete_records_at_eof = opts_[:emit_incomplete_records_at_eof]
|
80
79
|
@current_record_id = nil
|
81
80
|
@parser_directives = {}
|
82
81
|
end
|
@@ -155,11 +154,11 @@ module Sawmill
|
|
155
154
|
if str_ =~ DIRECTIVE_REGEXP
|
156
155
|
@parser_directives[$1] = $2
|
157
156
|
end
|
158
|
-
entry_ = Entry::UnknownData.new(str_)
|
157
|
+
entry_ = Entry::UnknownData.new(str_.chomp)
|
159
158
|
@processor.unknown_data(entry_) if @processor.respond_to?(:unknown_data)
|
160
159
|
end
|
161
160
|
else
|
162
|
-
if @
|
161
|
+
if @emit_incomplete_records_at_eof && @processor.respond_to?(:emit_incomplete_records)
|
163
162
|
@processor.emit_incomplete_records
|
164
163
|
end
|
165
164
|
end
|
@@ -171,7 +170,7 @@ module Sawmill
|
|
171
170
|
# entries to the processor.
|
172
171
|
|
173
172
|
def parse_all
|
174
|
-
while
|
173
|
+
while parse_one_entry; end
|
175
174
|
end
|
176
175
|
|
177
176
|
|
data/lib/sawmill/record.rb
CHANGED
@@ -89,6 +89,16 @@ module Sawmill
|
|
89
89
|
end
|
90
90
|
|
91
91
|
|
92
|
+
def eql?(obj_) # :nodoc:
|
93
|
+
return false unless obj_.kind_of?(Record)
|
94
|
+
return @entries == obj_.instance_variable_get(:@entries)
|
95
|
+
end
|
96
|
+
|
97
|
+
def ==(obj_) # :nodoc:
|
98
|
+
eql?(obj_)
|
99
|
+
end
|
100
|
+
|
101
|
+
|
92
102
|
# Append a log entry to this record.
|
93
103
|
#
|
94
104
|
# Entries must be added in order. Raises Errors::IllegalRecordError if
|
@@ -132,9 +142,9 @@ module Sawmill
|
|
132
142
|
when :append
|
133
143
|
val_ = @attributes[entry_.key]
|
134
144
|
case val_
|
135
|
-
when Array
|
145
|
+
when ::Array
|
136
146
|
val_ << entry_.value
|
137
|
-
when String
|
147
|
+
when ::String
|
138
148
|
@attributes[entry_.key] = [val_, entry_.value]
|
139
149
|
when nil
|
140
150
|
@attributes[entry_.key] = [entry_.value]
|
@@ -61,9 +61,9 @@ module Sawmill
|
|
61
61
|
@attributes.each do |key_, value_|
|
62
62
|
record_value_ = record_.attribute(key_.to_s)
|
63
63
|
case record_value_
|
64
|
-
when Array
|
64
|
+
when ::Array
|
65
65
|
return false unless record_value_.find{ |rval_| value_ === rval_ }
|
66
|
-
when String
|
66
|
+
when ::String
|
67
67
|
return false unless value_ === record_value_
|
68
68
|
when nil
|
69
69
|
return false unless value_.nil?
|
@@ -73,6 +73,13 @@ module Sawmill
|
|
73
73
|
end
|
74
74
|
|
75
75
|
|
76
|
+
# Return an array of the contents of the record queue, in order.
|
77
|
+
|
78
|
+
def dequeue_all
|
79
|
+
@queue.dequeue_all
|
80
|
+
end
|
81
|
+
|
82
|
+
|
76
83
|
# Return the number of records in the record queue.
|
77
84
|
|
78
85
|
def size
|
@@ -88,6 +95,13 @@ module Sawmill
|
|
88
95
|
end
|
89
96
|
|
90
97
|
|
98
|
+
# Return an array of the contents of the extra entry queue, in order.
|
99
|
+
|
100
|
+
def dequeue_all_extra_entries
|
101
|
+
@extra_entries_queue.dequeue_all
|
102
|
+
end
|
103
|
+
|
104
|
+
|
91
105
|
# Return the number of entries in the extra entry queue.
|
92
106
|
|
93
107
|
def extra_entries_size
|
@@ -109,12 +109,12 @@ module Sawmill
|
|
109
109
|
|
110
110
|
def _interpret_processor(param_) # :nodoc:
|
111
111
|
case param_
|
112
|
-
when Class
|
112
|
+
when ::Class
|
113
113
|
param_.new
|
114
114
|
when Base
|
115
115
|
param_
|
116
116
|
else
|
117
|
-
raise ArgumentError, "Unknown processor object of type #{param_.class.name}"
|
117
|
+
raise ::ArgumentError, "Unknown processor object of type #{param_.class.name}"
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
data/lib/sawmill/rotater/base.rb
CHANGED
@@ -82,8 +82,8 @@ module Sawmill
|
|
82
82
|
|
83
83
|
def initialize(options_)
|
84
84
|
@turnover_frequency = options_[:turnover_frequency] || :none
|
85
|
-
dirname_ = options_[:dirname] || Dir.getwd
|
86
|
-
@prefix = File.join(dirname_, options_[:prefix] || 'sawmill')
|
85
|
+
dirname_ = options_[:dirname] || ::Dir.getwd
|
86
|
+
@prefix = ::File.join(dirname_, options_[:prefix] || 'sawmill')
|
87
87
|
@suffix = options_[:suffix] || '.log'
|
88
88
|
@local_timezone = options_[:local_timezone]
|
89
89
|
@date_pattern =
|
@@ -101,7 +101,7 @@ module Sawmill
|
|
101
101
|
|
102
102
|
def preferred_handle
|
103
103
|
if @date_pattern
|
104
|
-
time_ = Time.now
|
104
|
+
time_ = ::Time.now
|
105
105
|
time_.utc unless @local_timezone
|
106
106
|
time_.strftime(@date_pattern)
|
107
107
|
else
|
@@ -118,7 +118,7 @@ module Sawmill
|
|
118
118
|
else
|
119
119
|
path_ = @prefix+@suffix
|
120
120
|
end
|
121
|
-
file_ = File.open(path_, File::CREAT | File::WRONLY | File::APPEND)
|
121
|
+
file_ = ::File.open(path_, ::File::CREAT | ::File::WRONLY | ::File::APPEND)
|
122
122
|
file_.sync = true
|
123
123
|
file_
|
124
124
|
end
|
@@ -91,11 +91,11 @@ module Sawmill
|
|
91
91
|
end
|
92
92
|
@history_size = options_[:history_size].to_i
|
93
93
|
@history_size = 1 if @history_size < 1 && (@max_logfile_size || @shift_period)
|
94
|
-
dirname_ = options_[:dirname] || Dir.getwd
|
95
|
-
@normal_path = File.join(dirname_, options_[:filename] || 'sawmill.log')
|
94
|
+
dirname_ = options_[:dirname] || ::Dir.getwd
|
95
|
+
@normal_path = ::File.join(dirname_, options_[:filename] || 'sawmill.log')
|
96
96
|
@preferred_handle = 0
|
97
97
|
@open_handles = {}
|
98
|
-
@last_shift = Time.now
|
98
|
+
@last_shift = ::Time.now
|
99
99
|
end
|
100
100
|
|
101
101
|
|
@@ -114,7 +114,7 @@ module Sawmill
|
|
114
114
|
else
|
115
115
|
path_ = "#{@normal_path}.#{@preferred_handle-handle_-1}"
|
116
116
|
end
|
117
|
-
file_ = File.open(path_, File::CREAT | File::WRONLY | File::APPEND)
|
117
|
+
file_ = ::File.open(path_, ::File::CREAT | ::File::WRONLY | ::File::APPEND)
|
118
118
|
file_.sync = true
|
119
119
|
@open_handles[handle_] = true
|
120
120
|
file_
|
@@ -126,7 +126,7 @@ module Sawmill
|
|
126
126
|
def close_handle(handle_, io_)
|
127
127
|
io_.close
|
128
128
|
if @preferred_handle - handle_ > @history_size
|
129
|
-
File.delete("#{@normal_path}.#{@preferred_handle-handle_-1}") rescue nil
|
129
|
+
::File.delete("#{@normal_path}.#{@preferred_handle-handle_-1}") rescue nil
|
130
130
|
end
|
131
131
|
@open_handles.delete(handle_)
|
132
132
|
nil
|
@@ -138,22 +138,22 @@ module Sawmill
|
|
138
138
|
def before_write
|
139
139
|
return unless @max_logfile_size || @shift_period
|
140
140
|
turnover_ = false
|
141
|
-
if @max_logfile_size && File.file?(@normal_path) && File.size(@normal_path) > @max_logfile_size
|
141
|
+
if @max_logfile_size && ::File.file?(@normal_path) && ::File.size(@normal_path) > @max_logfile_size
|
142
142
|
turnover_ = true
|
143
143
|
end
|
144
|
-
if @shift_period && (Time.now - @last_shift) > @shift_period
|
144
|
+
if @shift_period && (::Time.now - @last_shift) > @shift_period
|
145
145
|
turnover_ = true
|
146
146
|
end
|
147
147
|
if turnover_
|
148
148
|
max_ = @preferred_handle - @open_handles.keys.min + 1
|
149
149
|
max_ = @history_size if max_ < @history_size
|
150
|
-
File.delete("#{@normal_path}.#{max_-1}") rescue nil
|
150
|
+
::File.delete("#{@normal_path}.#{max_-1}") rescue nil
|
151
151
|
(max_-1).downto(1) do |index_|
|
152
|
-
File.rename("#{@normal_path}.#{index_-1}", "#{@normal_path}.#{index_}") rescue nil
|
152
|
+
::File.rename("#{@normal_path}.#{index_-1}", "#{@normal_path}.#{index_}") rescue nil
|
153
153
|
end
|
154
|
-
File.rename("#{@normal_path}", "#{@normal_path}.0") rescue nil
|
154
|
+
::File.rename("#{@normal_path}", "#{@normal_path}.0") rescue nil
|
155
155
|
@preferred_handle += 1
|
156
|
-
@last_shift = Time.now
|
156
|
+
@last_shift = ::Time.now
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
data/lib/sawmill/rotater.rb
CHANGED
@@ -73,13 +73,13 @@ module Sawmill
|
|
73
73
|
|
74
74
|
def initialize(io_manager_, opts_={})
|
75
75
|
@omit_directives = opts_.delete(:omit_directives)
|
76
|
-
if io_manager_.kind_of?(Class)
|
76
|
+
if io_manager_.kind_of?(::Class)
|
77
77
|
@io_manager = io_manager_.new(opts_)
|
78
78
|
else
|
79
79
|
@io_manager = io_manager_
|
80
80
|
end
|
81
81
|
@handles ||= {}
|
82
|
-
@mutex ||= Monitor.new
|
82
|
+
@mutex ||= ::Monitor.new
|
83
83
|
end
|
84
84
|
|
85
85
|
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Sawmill heap utility
|
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 Util
|
40
|
+
|
41
|
+
|
42
|
+
# A simple heap class.
|
43
|
+
|
44
|
+
class Heap
|
45
|
+
|
46
|
+
|
47
|
+
# Create a new heap.
|
48
|
+
|
49
|
+
def initialize(data_=nil, &block_)
|
50
|
+
@_heap = data_ || []
|
51
|
+
@_comparator = block_ || ::Proc.new{ |a_,b_| a_ <=> b_ }
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def merge(enum_)
|
56
|
+
enum_.each{ |value_| add(value_) }
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def add(value_)
|
62
|
+
@_heap << value_
|
63
|
+
_sift_up(@_heap.length-1)
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def <<(value_)
|
69
|
+
add(value_)
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def remove
|
74
|
+
ret_ = @_heap[0]
|
75
|
+
if @_heap.length > 1
|
76
|
+
@_heap[0] = @_heap.pop
|
77
|
+
_sift_down(0)
|
78
|
+
else
|
79
|
+
@_heap.clear
|
80
|
+
end
|
81
|
+
ret_
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def peek
|
86
|
+
@_heap[0]
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def size
|
91
|
+
@_heap.size
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def empty?
|
96
|
+
@_heap.empty?
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def clear
|
101
|
+
@_heap.clear
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def each!
|
106
|
+
while !empty?
|
107
|
+
yield(remove)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def _sift_up(start_) # :nodoc:
|
115
|
+
while start_ > 0
|
116
|
+
parent_ = (start_ + 1) / 2 - 1
|
117
|
+
if @_comparator.call(@_heap[start_], @_heap[parent_]) < 0
|
118
|
+
@_heap[start_], @_heap[parent_] = @_heap[parent_], @_heap[start_]
|
119
|
+
start_ = parent_
|
120
|
+
else
|
121
|
+
return start_
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def _sift_down(start_) # :nodoc:
|
128
|
+
length_ = self.size
|
129
|
+
while length_ >= (child2_ = (start_ + 1) * 2)
|
130
|
+
child1_ = child2_-1
|
131
|
+
if length_ <= child2_
|
132
|
+
earliest_child_ = child1_
|
133
|
+
elsif @_comparator.call(@_heap[child1_], @_heap[child2_]) < 0
|
134
|
+
earliest_child_ = child1_
|
135
|
+
else
|
136
|
+
earliest_child_ = child2_
|
137
|
+
end
|
138
|
+
if @_comparator.call(@_heap[start_], @_heap[earliest_child_]) < 0
|
139
|
+
return start_
|
140
|
+
else
|
141
|
+
@_heap[start_], @_heap[earliest_child_] = @_heap[earliest_child_], @_heap[start_]
|
142
|
+
start_ = earliest_child_
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
data/lib/sawmill/util/queue.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -----------------------------------------------------------------------------
|
2
2
|
#
|
3
|
-
# Sawmill
|
3
|
+
# Sawmill queue utility
|
4
4
|
#
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
# Copyright 2009 Daniel Azuma
|
@@ -101,6 +101,7 @@ module Sawmill
|
|
101
101
|
if @push_ptr
|
102
102
|
if @pop_ptr
|
103
103
|
object_ = @buffer[@pop_ptr]
|
104
|
+
@buffer[@pop_ptr] = nil
|
104
105
|
@pop_ptr += 1
|
105
106
|
@pop_ptr = 0 if @pop_ptr == @buffer.size
|
106
107
|
@pop_ptr = nil if @pop_ptr == @push_ptr
|
@@ -114,6 +115,31 @@ module Sawmill
|
|
114
115
|
end
|
115
116
|
|
116
117
|
|
118
|
+
# Return an array of the contents of the queue, in order.
|
119
|
+
|
120
|
+
def dequeue_all
|
121
|
+
if @push_ptr
|
122
|
+
if @pop_ptr
|
123
|
+
if @pop_ptr < @push_ptr
|
124
|
+
ret_ = @buffer[@pop_ptr..@push_ptr-1]
|
125
|
+
else
|
126
|
+
ret_ = @buffer[@pop_ptr..-1] + @buffer[0..@push_ptr-1]
|
127
|
+
end
|
128
|
+
@buffer.fill(nil)
|
129
|
+
@push_ptr = 0
|
130
|
+
@pop_ptr = nil
|
131
|
+
ret_
|
132
|
+
else
|
133
|
+
[]
|
134
|
+
end
|
135
|
+
else
|
136
|
+
ret_ = @buffer
|
137
|
+
@buffer = []
|
138
|
+
ret_
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
117
143
|
# Return the size of the queue, which is 0 if the queue is empty.
|
118
144
|
|
119
145
|
def size
|
data/lib/sawmill/version.rb
CHANGED
data/lib/sawmill.rb
CHANGED
@@ -49,6 +49,7 @@ dir_ = ::File.expand_path('sawmill', ::File.dirname(__FILE__))
|
|
49
49
|
includes_ = [
|
50
50
|
'version',
|
51
51
|
'util/queue',
|
52
|
+
'util/heap',
|
52
53
|
'errors',
|
53
54
|
'level',
|
54
55
|
'entry',
|
@@ -68,6 +69,7 @@ includes_ = [
|
|
68
69
|
'record_processor/decompose',
|
69
70
|
'record_processor/format',
|
70
71
|
'parser',
|
72
|
+
'multi_parser',
|
71
73
|
'logger',
|
72
74
|
'rotater',
|
73
75
|
'rotater/base',
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Sawmill: tests multi-parser
|
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
|
+
require 'test/unit'
|
37
|
+
require 'stringio'
|
38
|
+
require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/sawmill.rb")
|
39
|
+
|
40
|
+
|
41
|
+
module Sawmill
|
42
|
+
module Tests # :nodoc:
|
43
|
+
|
44
|
+
class TestMultiParser < ::Test::Unit::TestCase # :nodoc:
|
45
|
+
|
46
|
+
|
47
|
+
def setup
|
48
|
+
@levels = ::Sawmill::STANDARD_LEVELS
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def _get_io_array(entry_groups_)
|
53
|
+
strings_ = []
|
54
|
+
entry_groups_.each do |entries_|
|
55
|
+
stringio_ = ::StringIO.new
|
56
|
+
formatter_ = ::Sawmill::EntryClassifier.new(::Sawmill::Formatter.new(stringio_, :fractional_second_digits => 6))
|
57
|
+
entries_.each do |entry_|
|
58
|
+
formatter_.entry(entry_)
|
59
|
+
end
|
60
|
+
strings_ << stringio_.string
|
61
|
+
end
|
62
|
+
strings_.map{ |str_| ::StringIO.new(str_) }
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# Test interleaved entries including unknown data entries.
|
67
|
+
# Makes sure they come out in the right order.
|
68
|
+
|
69
|
+
def test_interleaved_entries
|
70
|
+
base_time_ = Time.now.utc
|
71
|
+
entries_ = []
|
72
|
+
2.times do |i_|
|
73
|
+
entries_ << ::Sawmill::Entry::UnknownData.new("Unknown #{i_}")
|
74
|
+
end
|
75
|
+
4.times do |i_|
|
76
|
+
entries_ << ::Sawmill::Entry::Message.new(@levels.get(:INFO), base_time_+i_, 'rails', nil, "Hello #{i_}")
|
77
|
+
end
|
78
|
+
io_array_ = _get_io_array([[entries_[0], entries_[2], entries_[5]], [entries_[3], entries_[4], entries_[1]]])
|
79
|
+
queue_ = ::Sawmill::EntryProcessor::SimpleQueue.new
|
80
|
+
::Sawmill::MultiParser.new(io_array_, queue_).parse_all
|
81
|
+
assert_equal([entries_[0], entries_[2], entries_[3], entries_[4], entries_[1], entries_[5]], queue_.dequeue_all)
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
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
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.2.
|
23
|
+
version: 0.2.2
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: versionomy
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.1.
|
33
|
+
version: 0.1.2
|
34
34
|
version:
|
35
35
|
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
36
|
email: dazuma@gmail.com
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- lib/sawmill/level.rb
|
55
55
|
- lib/sawmill/log_record_middleware.rb
|
56
56
|
- lib/sawmill/logger.rb
|
57
|
+
- lib/sawmill/multi_parser.rb
|
57
58
|
- lib/sawmill/parser.rb
|
58
59
|
- lib/sawmill/record.rb
|
59
60
|
- lib/sawmill/record_processor/conditionals.rb
|
@@ -67,6 +68,7 @@ files:
|
|
67
68
|
- lib/sawmill/rotater/date_based_log_file.rb
|
68
69
|
- lib/sawmill/rotater/shifting_log_file.rb
|
69
70
|
- lib/sawmill/rotater.rb
|
71
|
+
- lib/sawmill/util/heap.rb
|
70
72
|
- lib/sawmill/util/queue.rb
|
71
73
|
- lib/sawmill/version.rb
|
72
74
|
- lib/sawmill.rb
|
@@ -74,13 +76,14 @@ files:
|
|
74
76
|
- tests/tc_formatter_parser.rb
|
75
77
|
- tests/tc_levels.rb
|
76
78
|
- tests/tc_logger.rb
|
79
|
+
- tests/tc_multi_parser.rb
|
77
80
|
- tests/tc_record_processors.rb
|
78
81
|
- tests/tc_records.rb
|
79
82
|
- History.rdoc
|
80
83
|
- README.rdoc
|
81
84
|
- Rakefile
|
82
85
|
has_rdoc: true
|
83
|
-
homepage: http://
|
86
|
+
homepage: http://virtuoso.rubyforge.org/sawmill
|
84
87
|
licenses: []
|
85
88
|
|
86
89
|
post_install_message:
|
@@ -112,5 +115,6 @@ test_files:
|
|
112
115
|
- tests/tc_formatter_parser.rb
|
113
116
|
- tests/tc_levels.rb
|
114
117
|
- tests/tc_logger.rb
|
118
|
+
- tests/tc_multi_parser.rb
|
115
119
|
- tests/tc_record_processors.rb
|
116
120
|
- tests/tc_records.rb
|