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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/lib/filewatch/discoverer.rb +9 -8
  4. data/lib/filewatch/observing_base.rb +1 -12
  5. data/lib/filewatch/processor.rb +55 -0
  6. data/lib/filewatch/read_mode/handlers/base.rb +12 -11
  7. data/lib/filewatch/read_mode/handlers/read_file.rb +26 -8
  8. data/lib/filewatch/read_mode/handlers/read_zip_file.rb +8 -6
  9. data/lib/filewatch/read_mode/processor.rb +22 -36
  10. data/lib/filewatch/settings.rb +1 -2
  11. data/lib/filewatch/sincedb_collection.rb +39 -40
  12. data/lib/filewatch/sincedb_record_serializer.rb +5 -11
  13. data/lib/filewatch/stat/generic.rb +8 -13
  14. data/lib/filewatch/stat/windows_path.rb +7 -9
  15. data/lib/filewatch/tail_mode/handlers/base.rb +32 -23
  16. data/lib/filewatch/tail_mode/handlers/delete.rb +2 -4
  17. data/lib/filewatch/tail_mode/handlers/shrink.rb +2 -3
  18. data/lib/filewatch/tail_mode/handlers/unignore.rb +4 -4
  19. data/lib/filewatch/tail_mode/processor.rb +47 -54
  20. data/lib/filewatch/watch.rb +12 -14
  21. data/lib/filewatch/watched_file.rb +25 -14
  22. data/lib/filewatch/watched_files_collection.rb +11 -74
  23. data/lib/jars/filewatch-1.0.1.jar +0 -0
  24. data/lib/logstash/inputs/delete_completed_file_handler.rb +5 -0
  25. data/lib/logstash/inputs/file.rb +28 -13
  26. data/lib/logstash/inputs/file_listener.rb +3 -14
  27. data/logstash-input-file.gemspec +2 -1
  28. data/spec/filewatch/reading_spec.rb +60 -9
  29. data/spec/filewatch/settings_spec.rb +3 -0
  30. data/spec/filewatch/sincedb_record_serializer_spec.rb +6 -2
  31. data/spec/filewatch/spec_helper.rb +12 -14
  32. data/spec/filewatch/tailing_spec.rb +14 -12
  33. data/spec/filewatch/watched_file_spec.rb +30 -0
  34. data/spec/filewatch/watched_files_collection_spec.rb +62 -8
  35. data/spec/helpers/spec_helper.rb +1 -0
  36. data/spec/inputs/file_read_spec.rb +119 -0
  37. 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.trace("open: reading from #{path}")
50
+ logger.debug("open: reading from #{path}")
51
51
  @serializer.deserialize(file) do |key, value|
52
- logger.trace("open: importing ... '#{key}' => '#{value}'")
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.trace("open: error: #{path}: #{e.inspect}")
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", "inode" => watched_file.sincedb_key.inode, "path" => watched_file.path)
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", "filename" => watched_file.filename, "sincedb key" => watched_file.sincedb_key,"sincedb_value" => sincedb_value)
75
- if sincedb_value.watched_file.nil?
76
- # not associated
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("----------------- >> associate: the found sincedb_value has a watched_file - this is a rename", "this watched_file details" => watched_file.details, "other watched_file details" => existing_watched_file.details)
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
- return unless member?(watched_file.sincedb_key)
153
- get(watched_file.sincedb_key).unset_watched_file
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.to_i
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.....", "watched file" => watched_file.details, "sincedb value" => sincedb_value)
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.trace("open: record has expired, skipping: #{key.inspect} #{value.inspect}")
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.to_i)
212
- logger.trace("sincedb_write: to: #{path}")
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
- @serializer.expired_keys.each do |key|
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", "key" => "'#{key}'")
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
- # maybe it will work next time
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
- def atomic_write
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
- def non_atomic_write
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
- @expired_keys.clear
16
+ expired_keys = []
23
17
  db.each do |key, value|
24
18
  if as_of > value.last_changed_at_expires(@sincedb_value_expiry)
25
- @expired_keys << key
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 :identifier, :inode, :modified_at, :size, :inode_struct
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
- @inner_stat = @source.stat
18
- @inode = @inner_stat.ino.to_s
19
- @modified_at = @inner_stat.mtime.to_f
20
- @size = @inner_stat.size
21
- @dev_major = @inner_stat.dev_major
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
- "<Generic size='#{@size}', modified_at='#{@modified_at}', inode='#{@inode}', inode_struct='#{@inode_struct}'>"
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 :identifier, :inode, :modified_at, :size, :inode_struct
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, @dev_major, @dev_minor)
12
+ @inode_struct = InodeStruct.new(@inode, 0, 0)
15
13
  restat
16
14
  end
17
15
 
18
16
  def restat
19
- @inner_stat = @source.stat
20
- @modified_at = @inner_stat.mtime.to_f
21
- @size = @inner_stat.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
- "<WindowsPath size='#{@size}', modified_at='#{@modified_at}', inode='#{@inode}', inode_struct='#{@inode_struct}'>"
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: #{watched_file.filename}")
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("reading...", "iterations" => loop_control.count, "amount" => loop_control.size, "filename" => watched_file.filename)
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("read_to_eof: get chunk")
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("read_to_eof: general error reading #{watched_file.path}", "error" => e.inspect, "backtrace" => e.backtrace.take(4))
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("read_to_eof: exit due to quit") if quit?
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("opening #{watched_file.filename}")
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 #{watched_file.path}: #{$!.inspect}, #{$!.backtrace.take(3)}")
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.trace("suppressed warning for `failed to open` #{watched_file.path}: #{$!.inspect}")
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
- msg = "add_or_update_sincedb_collection: found sincedb record"
112
- logger.trace(msg,
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
- msg = "add_or_update_sincedb_collection: the found sincedb_value has a watched_file - this is a rename, switching inode to this watched file"
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...", "watched_file details" => watched_file.details)
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: #{watched_file.filename}, last value #{sincedb_value.position}, cur size #{watched_file.last_stat_size}")
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", "position" => sincedb_value.position, "watched_file details" => watched_file.details)
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("info",
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, "unread_bytes" => watched_file.bytes_unread, "path" => watched_file.path)
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