logstash-input-file 4.1.17 → 4.2.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/lib/filewatch/discoverer.rb +9 -8
- data/lib/filewatch/observing_base.rb +1 -12
- data/lib/filewatch/processor.rb +55 -0
- data/lib/filewatch/read_mode/handlers/base.rb +12 -11
- data/lib/filewatch/read_mode/handlers/read_file.rb +26 -8
- data/lib/filewatch/read_mode/handlers/read_zip_file.rb +8 -6
- data/lib/filewatch/read_mode/processor.rb +22 -36
- data/lib/filewatch/settings.rb +1 -2
- data/lib/filewatch/sincedb_collection.rb +39 -40
- data/lib/filewatch/sincedb_record_serializer.rb +5 -11
- data/lib/filewatch/stat/generic.rb +8 -13
- data/lib/filewatch/stat/windows_path.rb +7 -9
- data/lib/filewatch/tail_mode/handlers/base.rb +32 -23
- data/lib/filewatch/tail_mode/handlers/delete.rb +2 -4
- data/lib/filewatch/tail_mode/handlers/shrink.rb +2 -3
- data/lib/filewatch/tail_mode/handlers/unignore.rb +4 -4
- data/lib/filewatch/tail_mode/processor.rb +47 -54
- data/lib/filewatch/watch.rb +12 -14
- data/lib/filewatch/watched_file.rb +25 -14
- data/lib/filewatch/watched_files_collection.rb +11 -74
- data/lib/jars/filewatch-1.0.1.jar +0 -0
- data/lib/logstash/inputs/delete_completed_file_handler.rb +5 -0
- data/lib/logstash/inputs/file.rb +28 -13
- data/lib/logstash/inputs/file_listener.rb +3 -14
- data/logstash-input-file.gemspec +2 -1
- data/spec/filewatch/reading_spec.rb +60 -9
- data/spec/filewatch/settings_spec.rb +3 -0
- data/spec/filewatch/sincedb_record_serializer_spec.rb +6 -2
- data/spec/filewatch/spec_helper.rb +12 -14
- data/spec/filewatch/tailing_spec.rb +14 -12
- data/spec/filewatch/watched_file_spec.rb +30 -0
- data/spec/filewatch/watched_files_collection_spec.rb +62 -8
- data/spec/helpers/spec_helper.rb +1 -0
- data/spec/inputs/file_read_spec.rb +119 -0
- metadata +17 -2
@@ -47,55 +47,53 @@ module FileWatch
|
|
47
47
|
@time_sdb_opened = Time.now.to_f
|
48
48
|
begin
|
49
49
|
path.open do |file|
|
50
|
-
logger.
|
50
|
+
logger.debug("open: reading from #{path}")
|
51
51
|
@serializer.deserialize(file) do |key, value|
|
52
|
-
logger.trace("open: importing
|
52
|
+
logger.trace? && logger.trace("open: importing #{key.inspect} => #{value.inspect}")
|
53
53
|
set_key_value(key, value)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
logger.trace("open: count of keys read: #{@sincedb.keys.size}")
|
57
57
|
rescue => e
|
58
58
|
#No existing sincedb to load
|
59
|
-
logger.
|
59
|
+
logger.debug("open: error opening #{path}", :exception => e.class, :message => e.message)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
63
|
def associate(watched_file)
|
64
|
-
logger.trace("associate: finding",
|
64
|
+
logger.trace? && logger.trace("associate: finding", :path => watched_file.path, :inode => watched_file.sincedb_key.inode)
|
65
65
|
sincedb_value = find(watched_file)
|
66
66
|
if sincedb_value.nil?
|
67
67
|
# sincedb has no record of this inode
|
68
68
|
# and due to the window handling of many files
|
69
69
|
# this file may not be opened in this session.
|
70
70
|
# a new value will be added when the file is opened
|
71
|
-
logger.trace("associate: unmatched")
|
71
|
+
logger.trace("associate: unmatched", :filename => watched_file.filename)
|
72
72
|
return true
|
73
73
|
end
|
74
|
-
logger.trace("associate: found sincedb record",
|
75
|
-
|
76
|
-
|
74
|
+
logger.trace? && logger.trace("associate: found sincedb record", :filename => watched_file.filename,
|
75
|
+
:sincedb_key => watched_file.sincedb_key, :sincedb_value => sincedb_value)
|
76
|
+
if sincedb_value.watched_file.nil? # not associated
|
77
77
|
if sincedb_value.path_in_sincedb.nil?
|
78
78
|
handle_association(sincedb_value, watched_file)
|
79
|
-
logger.trace("associate: inode matched but no path in sincedb")
|
79
|
+
logger.trace? && logger.trace("associate: inode matched but no path in sincedb", :filename => watched_file.filename)
|
80
80
|
return true
|
81
81
|
end
|
82
82
|
if sincedb_value.path_in_sincedb == watched_file.path
|
83
|
-
# the path on disk is the same as discovered path
|
84
|
-
# and the inode is the same.
|
83
|
+
# the path on disk is the same as discovered path and the inode is the same.
|
85
84
|
handle_association(sincedb_value, watched_file)
|
86
|
-
logger.trace("associate: inode and path matched")
|
85
|
+
logger.trace? && logger.trace("associate: inode and path matched", :filename => watched_file.filename)
|
87
86
|
return true
|
88
87
|
end
|
89
|
-
# the path on disk is different from discovered unassociated path
|
90
|
-
# but they have the same key (inode)
|
88
|
+
# the path on disk is different from discovered unassociated path but they have the same key (inode)
|
91
89
|
# treat as a new file, a new value will be added when the file is opened
|
92
90
|
sincedb_value.clear_watched_file
|
93
91
|
delete(watched_file.sincedb_key)
|
94
|
-
logger.trace("associate: matched but allocated to another")
|
92
|
+
logger.trace? && logger.trace("associate: matched but allocated to another", :filename => watched_file.filename)
|
95
93
|
return true
|
96
94
|
end
|
97
95
|
if sincedb_value.watched_file.equal?(watched_file) # pointer equals
|
98
|
-
logger.trace("associate: already associated")
|
96
|
+
logger.trace? && logger.trace("associate: already associated", :filename => watched_file.filename)
|
99
97
|
return true
|
100
98
|
end
|
101
99
|
# sincedb_value.watched_file is not this discovered watched_file but they have the same key (inode)
|
@@ -106,7 +104,8 @@ module FileWatch
|
|
106
104
|
# after the original is deleted
|
107
105
|
# are not yet in the delete phase, let this play out
|
108
106
|
existing_watched_file = sincedb_value.watched_file
|
109
|
-
logger.trace("
|
107
|
+
logger.trace? && logger.trace("associate: found sincedb_value has a watched_file - this is a rename",
|
108
|
+
:this_watched_file => watched_file.details, :existing_watched_file => existing_watched_file.details)
|
110
109
|
watched_file.rotation_in_progress
|
111
110
|
true
|
112
111
|
end
|
@@ -149,8 +148,8 @@ module FileWatch
|
|
149
148
|
end
|
150
149
|
|
151
150
|
def watched_file_deleted(watched_file)
|
152
|
-
|
153
|
-
|
151
|
+
value = @sincedb[watched_file.sincedb_key]
|
152
|
+
value.unset_watched_file if value
|
154
153
|
end
|
155
154
|
|
156
155
|
def store_last_read(key, pos)
|
@@ -178,63 +177,63 @@ module FileWatch
|
|
178
177
|
get(key).watched_file.nil?
|
179
178
|
end
|
180
179
|
|
181
|
-
private
|
182
|
-
|
183
180
|
def flush_at_interval
|
184
|
-
now = Time.now
|
185
|
-
delta = now - @sincedb_last_write
|
181
|
+
now = Time.now
|
182
|
+
delta = now.to_i - @sincedb_last_write
|
186
183
|
if delta >= @settings.sincedb_write_interval
|
187
184
|
logger.debug("writing sincedb (delta since last write = #{delta})")
|
188
185
|
sincedb_write(now)
|
189
186
|
end
|
190
187
|
end
|
191
188
|
|
189
|
+
private
|
190
|
+
|
192
191
|
def handle_association(sincedb_value, watched_file)
|
193
192
|
watched_file.update_bytes_read(sincedb_value.position)
|
194
193
|
sincedb_value.set_watched_file(watched_file)
|
195
194
|
watched_file.initial_completed
|
196
195
|
if watched_file.all_read?
|
197
196
|
watched_file.ignore
|
198
|
-
logger.trace("handle_association fully read, ignoring
|
197
|
+
logger.trace? && logger.trace("handle_association fully read, ignoring", :watched_file => watched_file.details, :sincedb_value => sincedb_value)
|
199
198
|
end
|
200
199
|
end
|
201
200
|
|
202
201
|
def set_key_value(key, value)
|
203
202
|
if @time_sdb_opened < value.last_changed_at_expires(@settings.sincedb_expiry_duration)
|
204
|
-
logger.trace("open: setting #{key.inspect} to #{value.inspect}")
|
205
203
|
set(key, value)
|
206
204
|
else
|
207
|
-
logger.
|
205
|
+
logger.debug("set_key_value: record has expired, skipping: #{key.inspect} => #{value.inspect}")
|
208
206
|
end
|
209
207
|
end
|
210
208
|
|
211
|
-
def sincedb_write(time = Time.now
|
212
|
-
logger.trace("sincedb_write:
|
209
|
+
def sincedb_write(time = Time.now)
|
210
|
+
logger.trace? && logger.trace("sincedb_write: #{path} (time = #{time})")
|
213
211
|
begin
|
214
|
-
@write_method.call
|
215
|
-
|
212
|
+
expired_keys = @write_method.call(time)
|
213
|
+
expired_keys.each do |key|
|
216
214
|
@sincedb[key].unset_watched_file
|
217
215
|
delete(key)
|
218
|
-
logger.trace("sincedb_write: cleaned",
|
216
|
+
logger.trace? && logger.trace("sincedb_write: cleaned", :key => key)
|
219
217
|
end
|
220
|
-
@sincedb_last_write = time
|
218
|
+
@sincedb_last_write = time.to_i
|
221
219
|
@write_requested = false
|
222
|
-
rescue Errno::EACCES
|
223
|
-
# no file handles free perhaps
|
224
|
-
#
|
225
|
-
logger.trace("sincedb_write: error: #{path}: #{$!}")
|
220
|
+
rescue Errno::EACCES => e
|
221
|
+
# no file handles free perhaps - maybe it will work next time
|
222
|
+
logger.debug("sincedb_write: #{path} error:", :exception => e.class, :message => e.message)
|
226
223
|
end
|
227
224
|
end
|
228
225
|
|
229
|
-
|
226
|
+
# @return expired keys
|
227
|
+
def atomic_write(time)
|
230
228
|
FileHelper.write_atomically(@full_path) do |io|
|
231
|
-
@serializer.serialize(@sincedb, io)
|
229
|
+
@serializer.serialize(@sincedb, io, time.to_f)
|
232
230
|
end
|
233
231
|
end
|
234
232
|
|
235
|
-
|
233
|
+
# @return expired keys
|
234
|
+
def non_atomic_write(time)
|
236
235
|
IO.open(IO.sysopen(@full_path, "w+")) do |io|
|
237
|
-
@serializer.serialize(@sincedb, io)
|
236
|
+
@serializer.serialize(@sincedb, io, time.to_f)
|
238
237
|
end
|
239
238
|
end
|
240
239
|
end
|
@@ -3,30 +3,25 @@
|
|
3
3
|
module FileWatch
|
4
4
|
class SincedbRecordSerializer
|
5
5
|
|
6
|
-
attr_reader :expired_keys
|
7
|
-
|
8
6
|
def self.days_to_seconds(days)
|
9
7
|
(24 * 3600) * days.to_f
|
10
8
|
end
|
11
9
|
|
12
10
|
def initialize(sincedb_value_expiry)
|
13
11
|
@sincedb_value_expiry = sincedb_value_expiry
|
14
|
-
@expired_keys = []
|
15
|
-
end
|
16
|
-
|
17
|
-
def update_sincedb_value_expiry_from_days(days)
|
18
|
-
@sincedb_value_expiry = SincedbRecordSerializer.days_to_seconds(days)
|
19
12
|
end
|
20
13
|
|
14
|
+
# @return Array expired keys (ones that were not written to the file)
|
21
15
|
def serialize(db, io, as_of = Time.now.to_f)
|
22
|
-
|
16
|
+
expired_keys = []
|
23
17
|
db.each do |key, value|
|
24
18
|
if as_of > value.last_changed_at_expires(@sincedb_value_expiry)
|
25
|
-
|
19
|
+
expired_keys << key
|
26
20
|
next
|
27
21
|
end
|
28
22
|
io.write(serialize_record(key, value))
|
29
23
|
end
|
24
|
+
expired_keys
|
30
25
|
end
|
31
26
|
|
32
27
|
def deserialize(io)
|
@@ -36,8 +31,7 @@ module FileWatch
|
|
36
31
|
end
|
37
32
|
|
38
33
|
def serialize_record(k, v)
|
39
|
-
# effectively InodeStruct#to_s SincedbValue#to_s
|
40
|
-
"#{k} #{v}\n"
|
34
|
+
"#{k} #{v}\n" # effectively InodeStruct#to_s SincedbValue#to_s
|
41
35
|
end
|
42
36
|
|
43
37
|
def deserialize_record(record)
|
@@ -3,24 +3,19 @@
|
|
3
3
|
module FileWatch module Stat
|
4
4
|
class Generic
|
5
5
|
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :inode, :modified_at, :size, :inode_struct
|
7
7
|
|
8
8
|
def initialize(source)
|
9
|
-
@source = source
|
10
|
-
@identifier = nil
|
9
|
+
@source = source # Pathname
|
11
10
|
restat
|
12
11
|
end
|
13
12
|
|
14
|
-
def add_identifier(identifier) self; end
|
15
|
-
|
16
13
|
def restat
|
17
|
-
|
18
|
-
@inode =
|
19
|
-
@modified_at =
|
20
|
-
@size =
|
21
|
-
@
|
22
|
-
@dev_minor = @inner_stat.dev_minor
|
23
|
-
@inode_struct = InodeStruct.new(@inode, @dev_major, @dev_minor)
|
14
|
+
stat = @source.stat
|
15
|
+
@inode = stat.ino.to_s
|
16
|
+
@modified_at = stat.mtime.to_f
|
17
|
+
@size = stat.size
|
18
|
+
@inode_struct = InodeStruct.new(@inode, stat.dev_major, stat.dev_minor)
|
24
19
|
end
|
25
20
|
|
26
21
|
def windows?
|
@@ -28,7 +23,7 @@ module FileWatch module Stat
|
|
28
23
|
end
|
29
24
|
|
30
25
|
def inspect
|
31
|
-
"
|
26
|
+
"<#{self.class.name} size=#{@size}, modified_at=#{@modified_at}, inode='#{@inode}', inode_struct=#{@inode_struct}>"
|
32
27
|
end
|
33
28
|
end
|
34
29
|
end end
|
@@ -3,22 +3,20 @@
|
|
3
3
|
module FileWatch module Stat
|
4
4
|
class WindowsPath
|
5
5
|
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :inode, :modified_at, :size, :inode_struct
|
7
7
|
|
8
8
|
def initialize(source)
|
9
|
-
@source = source
|
9
|
+
@source = source # Pathname
|
10
10
|
@inode = Winhelper.identifier_from_path(@source.to_path)
|
11
|
-
@dev_major = 0
|
12
|
-
@dev_minor = 0
|
13
11
|
# in windows the dev hi and low are in the identifier
|
14
|
-
@inode_struct = InodeStruct.new(@inode,
|
12
|
+
@inode_struct = InodeStruct.new(@inode, 0, 0)
|
15
13
|
restat
|
16
14
|
end
|
17
15
|
|
18
16
|
def restat
|
19
|
-
|
20
|
-
@modified_at =
|
21
|
-
@size =
|
17
|
+
stat = @source.stat
|
18
|
+
@modified_at = stat.mtime.to_f
|
19
|
+
@size = stat.size
|
22
20
|
end
|
23
21
|
|
24
22
|
def windows?
|
@@ -26,7 +24,7 @@ module FileWatch module Stat
|
|
26
24
|
end
|
27
25
|
|
28
26
|
def inspect
|
29
|
-
"
|
27
|
+
"<#{self.class.name} size=#{@size}, modified_at=#{@modified_at}, inode=#{@inode}, inode_struct=#{@inode_struct}>"
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end end
|
@@ -18,7 +18,7 @@ module FileWatch module TailMode module Handlers
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def handle(watched_file)
|
21
|
-
logger.trace("handling:
|
21
|
+
logger.trace? && logger.trace("handling:", :path => watched_file.path)
|
22
22
|
unless watched_file.has_listener?
|
23
23
|
watched_file.set_listener(@observer)
|
24
24
|
end
|
@@ -37,7 +37,7 @@ module FileWatch module TailMode module Handlers
|
|
37
37
|
|
38
38
|
def controlled_read(watched_file, loop_control)
|
39
39
|
changed = false
|
40
|
-
logger.trace(
|
40
|
+
logger.trace? && logger.trace(__method__.to_s, :iterations => loop_control.count, :amount => loop_control.size, :filename => watched_file.filename)
|
41
41
|
# from a real config (has 102 file inputs)
|
42
42
|
# -- This cfg creates a file input for every log file to create a dedicated file pointer and read all file simultaneously
|
43
43
|
# -- If we put all log files in one file input glob we will have indexing delay, because Logstash waits until the first file becomes EOF
|
@@ -48,7 +48,7 @@ module FileWatch module TailMode module Handlers
|
|
48
48
|
loop_control.count.times do
|
49
49
|
break if quit?
|
50
50
|
begin
|
51
|
-
logger.debug("
|
51
|
+
logger.debug? && logger.debug("#{__method__} get chunk")
|
52
52
|
result = watched_file.read_extract_lines(loop_control.size) # expect BufferExtractResult
|
53
53
|
logger.trace(result.warning, result.additional) unless result.warning.empty?
|
54
54
|
changed = true
|
@@ -57,40 +57,42 @@ module FileWatch module TailMode module Handlers
|
|
57
57
|
# sincedb position is now independent from the watched_file bytes_read
|
58
58
|
sincedb_collection.increment(watched_file.sincedb_key, line.bytesize + @settings.delimiter_byte_size)
|
59
59
|
end
|
60
|
-
rescue EOFError
|
60
|
+
rescue EOFError => e
|
61
61
|
# it only makes sense to signal EOF in "read" mode not "tail"
|
62
|
+
logger.debug(__method__.to_s, exception_details(watched_file.path, e, false))
|
62
63
|
loop_control.flag_read_error
|
63
64
|
break
|
64
|
-
rescue Errno::EWOULDBLOCK, Errno::EINTR
|
65
|
+
rescue Errno::EWOULDBLOCK, Errno::EINTR => e
|
66
|
+
logger.debug(__method__.to_s, exception_details(watched_file.path, e, false))
|
65
67
|
watched_file.listener.error
|
66
68
|
loop_control.flag_read_error
|
67
69
|
break
|
68
70
|
rescue => e
|
69
|
-
logger.error("
|
71
|
+
logger.error("#{__method__} general error reading", exception_details(watched_file.path, e))
|
70
72
|
watched_file.listener.error
|
71
73
|
loop_control.flag_read_error
|
72
74
|
break
|
73
75
|
end
|
74
76
|
end
|
75
|
-
logger.debug("
|
77
|
+
logger.debug("#{__method__} stopped loop due quit") if quit?
|
76
78
|
sincedb_collection.request_disk_flush if changed
|
77
79
|
end
|
78
80
|
|
79
81
|
def open_file(watched_file)
|
80
82
|
return true if watched_file.file_open?
|
81
|
-
logger.trace("
|
83
|
+
logger.trace? && logger.trace("open_file", :filename => watched_file.filename)
|
82
84
|
begin
|
83
85
|
watched_file.open
|
84
|
-
rescue
|
86
|
+
rescue => e
|
85
87
|
# don't emit this message too often. if a file that we can't
|
86
88
|
# read is changing a lot, we'll try to open it more often, and spam the logs.
|
87
89
|
now = Time.now.to_i
|
88
|
-
logger.trace("open_file OPEN_WARN_INTERVAL is '#{OPEN_WARN_INTERVAL}'")
|
90
|
+
logger.trace? && logger.trace("open_file OPEN_WARN_INTERVAL is '#{OPEN_WARN_INTERVAL}'")
|
89
91
|
if watched_file.last_open_warning_at.nil? || now - watched_file.last_open_warning_at > OPEN_WARN_INTERVAL
|
90
|
-
logger.warn("failed to open
|
92
|
+
logger.warn("failed to open file", exception_details(watched_file.path, e))
|
91
93
|
watched_file.last_open_warning_at = now
|
92
94
|
else
|
93
|
-
logger.
|
95
|
+
logger.debug("open_file suppressed warning `failed to open file`", exception_details(watched_file.path, e, false))
|
94
96
|
end
|
95
97
|
watched_file.watch # set it back to watch so we can try it again
|
96
98
|
else
|
@@ -108,26 +110,22 @@ module FileWatch module TailMode module Handlers
|
|
108
110
|
update_existing_sincedb_collection_value(watched_file, sincedb_value)
|
109
111
|
watched_file.initial_completed
|
110
112
|
else
|
111
|
-
|
112
|
-
|
113
|
-
"sincedb key" => watched_file.sincedb_key,
|
114
|
-
"sincedb value" => sincedb_value
|
115
|
-
)
|
113
|
+
logger.trace? && logger.trace("add_or_update_sincedb_collection: found sincedb record",
|
114
|
+
:sincedb_key => watched_file.sincedb_key, :sincedb_value => sincedb_value)
|
116
115
|
# detected a rotation, Discoverer can't handle this because this watched file is not a new discovery.
|
117
116
|
# we must handle it here, by transferring state and have the sincedb value track this watched file
|
118
117
|
# rotate_as_file and rotate_from will switch the sincedb key to the inode that the path is now pointing to
|
119
118
|
# and pickup the sincedb_value from before.
|
120
|
-
|
121
|
-
logger.trace(msg)
|
119
|
+
logger.debug("add_or_update_sincedb_collection: the found sincedb_value has a watched_file - this is a rename, switching inode to this watched file")
|
122
120
|
existing_watched_file = sincedb_value.watched_file
|
123
121
|
if existing_watched_file.nil?
|
124
122
|
sincedb_value.set_watched_file(watched_file)
|
125
|
-
logger.trace("add_or_update_sincedb_collection: switching as new file")
|
123
|
+
logger.trace? && logger.trace("add_or_update_sincedb_collection: switching as new file")
|
126
124
|
watched_file.rotate_as_file
|
127
125
|
watched_file.update_bytes_read(sincedb_value.position)
|
128
126
|
else
|
129
127
|
sincedb_value.set_watched_file(watched_file)
|
130
|
-
logger.trace("add_or_update_sincedb_collection: switching from
|
128
|
+
logger.trace? && logger.trace("add_or_update_sincedb_collection: switching from:", :watched_file => watched_file.details)
|
131
129
|
watched_file.rotate_from(existing_watched_file)
|
132
130
|
end
|
133
131
|
end
|
@@ -135,13 +133,15 @@ module FileWatch module TailMode module Handlers
|
|
135
133
|
end
|
136
134
|
|
137
135
|
def update_existing_sincedb_collection_value(watched_file, sincedb_value)
|
138
|
-
logger.trace("update_existing_sincedb_collection_value
|
136
|
+
logger.trace? && logger.trace("update_existing_sincedb_collection_value", :position => sincedb_value.position,
|
137
|
+
:filename => watched_file.filename, :last_stat_size => watched_file.last_stat_size)
|
139
138
|
update_existing_specifically(watched_file, sincedb_value)
|
140
139
|
end
|
141
140
|
|
142
141
|
def add_new_value_sincedb_collection(watched_file)
|
143
142
|
sincedb_value = get_new_value_specifically(watched_file)
|
144
|
-
logger.trace("add_new_value_sincedb_collection",
|
143
|
+
logger.trace? && logger.trace("add_new_value_sincedb_collection", :position => sincedb_value.position,
|
144
|
+
:watched_file => watched_file.details)
|
145
145
|
sincedb_collection.set(watched_file.sincedb_key, sincedb_value)
|
146
146
|
sincedb_value
|
147
147
|
end
|
@@ -153,5 +153,14 @@ module FileWatch module TailMode module Handlers
|
|
153
153
|
watched_file.update_bytes_read(position)
|
154
154
|
value
|
155
155
|
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def exception_details(path, e, trace = true)
|
160
|
+
details = { :path => path, :exception => e.class, :message => e.message }
|
161
|
+
details[:backtrace] = e.backtrace if trace && logger.debug?
|
162
|
+
details
|
163
|
+
end
|
164
|
+
|
156
165
|
end
|
157
166
|
end end end
|
@@ -7,11 +7,9 @@ module FileWatch module TailMode module Handlers
|
|
7
7
|
# TODO consider trying to find the renamed file - it will have the same inode.
|
8
8
|
# Needs a rotate scheme rename hint from user e.g. "<name>-YYYY-MM-DD-N.<ext>" or "<name>.<ext>.N"
|
9
9
|
# send the found content to the same listener (stream identity)
|
10
|
-
logger.trace(
|
11
|
-
"watched_file details" => watched_file.details,
|
12
|
-
"path" => watched_file.path)
|
10
|
+
logger.trace? && logger.trace(__method__.to_s, :path => watched_file.path, :watched_file => watched_file.details)
|
13
11
|
if watched_file.bytes_unread > 0
|
14
|
-
logger.warn(DATA_LOSS_WARNING,
|
12
|
+
logger.warn(DATA_LOSS_WARNING, :path => watched_file.path, :unread_bytes => watched_file.bytes_unread)
|
15
13
|
end
|
16
14
|
watched_file.listener.deleted
|
17
15
|
# no need to worry about data in the buffer
|