logstash-input-file 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile +3 -1
- data/README.md +4 -4
- data/lib/logstash/inputs/file.rb +72 -19
- data/logstash-input-file.gemspec +4 -4
- data/spec/inputs/file_spec.rb +49 -0
- metadata +38 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39708420cb297cae2205c5e2ef4e595f2b1652f0
|
4
|
+
data.tar.gz: 405f93ecc407455518f14fb9d16544e9357733b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2460287157dd990831b5f91717f9004c9eb2af6469d73a15596ab029eb0579941c5a7d10a392e8e857cd02d2c84fe22e5b830d1d44ec7fba8789ba69e86bb32
|
7
|
+
data.tar.gz: 2fea4c08d6adcd180f920bf33083292d1d06a6bb9b209d67a5f150d4c6f800667ed230484df139f7b0bc0542fe2689b068e6b3f129981bbefcc8dfc312b22438
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 1.0.2
|
2
|
+
- Using filewatch >= 0.6.7, tail.quit closes files. Only one set of file
|
3
|
+
handles are used if run is called more than once.
|
4
|
+
|
1
5
|
## 1.0.1
|
2
6
|
- Force dependency on filewatch >= 0.6.5 that fixes a sincedb bug
|
3
7
|
- Better documentation and error handling regarding the "sincedb_path" parameter
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Logstash Plugin
|
2
2
|
|
3
|
-
This is a plugin for [Logstash](https://github.com/
|
3
|
+
This is a plugin for [Logstash](https://github.com/elastic/logstash).
|
4
4
|
|
5
5
|
It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
|
6
6
|
|
7
7
|
## Documentation
|
8
8
|
|
9
|
-
Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.
|
9
|
+
Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elastic.co/guide/en/logstash/current/).
|
10
10
|
|
11
11
|
- For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
|
12
|
-
- For more asciidoc formatting tips, see the excellent reference here https://github.com/
|
12
|
+
- For more asciidoc formatting tips, see the excellent reference here https://github.com/elastic/docs#asciidoc-guide
|
13
13
|
|
14
14
|
## Need Help?
|
15
15
|
|
@@ -83,4 +83,4 @@ Programming is not a required skill. Whatever you've seen about open source and
|
|
83
83
|
|
84
84
|
It is more important to the community that you are able to contribute.
|
85
85
|
|
86
|
-
For more information about contributing, see the [CONTRIBUTING](https://github.com/
|
86
|
+
For more information about contributing, see the [CONTRIBUTING](https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md) file.
|
data/lib/logstash/inputs/file.rb
CHANGED
@@ -5,14 +5,62 @@ require "logstash/namespace"
|
|
5
5
|
require "pathname"
|
6
6
|
require "socket" # for Socket.gethostname
|
7
7
|
|
8
|
-
# Stream events from files
|
8
|
+
# Stream events from files, normally by tailing them in a manner
|
9
|
+
# similar to `tail -0F` but optionally reading them from the
|
10
|
+
# beginning.
|
9
11
|
#
|
10
12
|
# By default, each event is assumed to be one line. If you would like
|
11
13
|
# to join multiple log lines into one event, you'll want to use the
|
12
|
-
# multiline codec.
|
14
|
+
# multiline codec or filter.
|
13
15
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
+
# The plugin aims to track changing files and emit new content as it's
|
17
|
+
# appended to each file. It's not well-suited for reading a file from
|
18
|
+
# beginning to end and storing all of it in a single event (not even
|
19
|
+
# with the multiline codec or filter).
|
20
|
+
#
|
21
|
+
# ==== Tracking of current position in watched files
|
22
|
+
#
|
23
|
+
# The plugin keeps track of the current position in each file by
|
24
|
+
# recording it in a separate file named sincedb. This makes it
|
25
|
+
# possible to stop and restart Logstash and have it pick up where it
|
26
|
+
# left off without missing the lines that were added to the file while
|
27
|
+
# Logstash was stopped.
|
28
|
+
#
|
29
|
+
# By default, the sincedb file is placed in the home directory of the
|
30
|
+
# user running Logstash with a filename based on the filename patterns
|
31
|
+
# being watched (i.e. the `path` option). Thus, changing the filename
|
32
|
+
# patterns will result in a new sincedb file being used and any
|
33
|
+
# existing current position state will be lost. If you change your
|
34
|
+
# patterns with any frequency it might make sense to explicitly choose
|
35
|
+
# a sincedb path with the `sincedb_path` option.
|
36
|
+
#
|
37
|
+
# Sincedb files are text files with four columns:
|
38
|
+
#
|
39
|
+
# . The inode number (or equivalent).
|
40
|
+
# . The major device number of the file system (or equivalent).
|
41
|
+
# . The minor device number of the file system (or equivalent).
|
42
|
+
# . The current byte offset within the file.
|
43
|
+
#
|
44
|
+
# On non-Windows systems you can obtain the inode number of a file
|
45
|
+
# with e.g. `ls -li`.
|
46
|
+
#
|
47
|
+
# ==== File rotation
|
48
|
+
#
|
49
|
+
# File rotation is detected and handled by this input, regardless of
|
50
|
+
# whether the file is rotated via a rename or a copy operation. To
|
51
|
+
# support programs that write to the rotated file for some time after
|
52
|
+
# the rotation has taken place, include both the original filename and
|
53
|
+
# the rotated filename (e.g. /var/log/syslog and /var/log/syslog.1) in
|
54
|
+
# the filename patterns to watch (the `path` option). Note that the
|
55
|
+
# rotated filename will be treated as a new file so if
|
56
|
+
# `start_position` is set to 'beginning' the rotated file will be
|
57
|
+
# reprocessed.
|
58
|
+
#
|
59
|
+
# With the default value of `start_position` ('end') any messages
|
60
|
+
# written to the end of the file between the last read operation prior
|
61
|
+
# to the rotation and its reopening under the new name (an interval
|
62
|
+
# determined by the `stat_interval` and `discover_interval` options)
|
63
|
+
# will not get picked up.
|
16
64
|
class LogStash::Inputs::File < LogStash::Inputs::Base
|
17
65
|
config_name "file"
|
18
66
|
|
@@ -21,15 +69,15 @@ class LogStash::Inputs::File < LogStash::Inputs::Base
|
|
21
69
|
default :codec, "plain"
|
22
70
|
|
23
71
|
# The path(s) to the file(s) to use as an input.
|
24
|
-
# You can use
|
72
|
+
# You can use filename patterns here, such as `/var/log/*.log`.
|
25
73
|
# Paths must be absolute and cannot be relative.
|
26
74
|
#
|
27
75
|
# You may also configure multiple paths. See an example
|
28
76
|
# on the <<array,Logstash configuration page>>.
|
29
77
|
config :path, :validate => :array, :required => true
|
30
78
|
|
31
|
-
# Exclusions (matched against the filename, not full path).
|
32
|
-
# are valid here, too. For example, if you have
|
79
|
+
# Exclusions (matched against the filename, not full path). Filename
|
80
|
+
# patterns are valid here, too. For example, if you have
|
33
81
|
# [source,ruby]
|
34
82
|
# path => "/var/log/*"
|
35
83
|
#
|
@@ -43,7 +91,8 @@ class LogStash::Inputs::File < LogStash::Inputs::Base
|
|
43
91
|
# but increase the time to detect new log lines.
|
44
92
|
config :stat_interval, :validate => :number, :default => 1
|
45
93
|
|
46
|
-
# How often (in seconds) we expand
|
94
|
+
# How often (in seconds) we expand the filename patterns in the
|
95
|
+
# `path` option to discover new files to watch.
|
47
96
|
config :discover_interval, :validate => :number, :default => 15
|
48
97
|
|
49
98
|
# Path of the sincedb database file (keeps track of the current
|
@@ -59,11 +108,13 @@ class LogStash::Inputs::File < LogStash::Inputs::Base
|
|
59
108
|
# Choose where Logstash starts initially reading files: at the beginning or
|
60
109
|
# at the end. The default behavior treats files like live streams and thus
|
61
110
|
# starts at the end. If you have old data you want to import, set this
|
62
|
-
# to 'beginning'
|
111
|
+
# to 'beginning'.
|
63
112
|
#
|
64
|
-
# This option only modifies "first contact" situations where a file
|
65
|
-
# and not seen before.
|
66
|
-
#
|
113
|
+
# This option only modifies "first contact" situations where a file
|
114
|
+
# is new and not seen before, i.e. files that don't have a current
|
115
|
+
# position recorded in a sincedb file read by Logstash. If a file
|
116
|
+
# has already been seen before, this option has no effect and the
|
117
|
+
# position recorded in the sincedb file will be used.
|
67
118
|
config :start_position, :validate => [ "beginning", "end"], :default => "end"
|
68
119
|
|
69
120
|
# set the new line delimiter, defaults to "\n"
|
@@ -132,12 +183,15 @@ class LogStash::Inputs::File < LogStash::Inputs::Base
|
|
132
183
|
end
|
133
184
|
end # def register
|
134
185
|
|
135
|
-
|
136
|
-
|
186
|
+
def begin_tailing
|
187
|
+
teardown # if the pipeline restarts this input.
|
137
188
|
@tail = FileWatch::Tail.new(@tail_config)
|
138
189
|
@tail.logger = @logger
|
139
190
|
@path.each { |path| @tail.tail(path) }
|
191
|
+
end
|
140
192
|
|
193
|
+
def run(queue)
|
194
|
+
begin_tailing
|
141
195
|
@tail.subscribe do |path, line|
|
142
196
|
@logger.debug? && @logger.debug("Received line", :path => path, :text => line)
|
143
197
|
@codec.decode(line) do |event|
|
@@ -153,10 +207,9 @@ class LogStash::Inputs::File < LogStash::Inputs::Base
|
|
153
207
|
|
154
208
|
public
|
155
209
|
def teardown
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
210
|
+
# in filewatch >= 0.6.7, quit will close and forget all files
|
211
|
+
# but it will write their last read positions to since_db
|
212
|
+
# beforehand
|
213
|
+
@tail.quit if @tail
|
161
214
|
end # def teardown
|
162
215
|
end # class LogStash::Inputs::File
|
data/logstash-input-file.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-input-file'
|
4
|
-
s.version = '1.0.
|
4
|
+
s.version = '1.0.2'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "Stream events from files."
|
7
7
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
@@ -20,14 +20,14 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
|
21
21
|
|
22
22
|
# Gem dependencies
|
23
|
-
s.add_runtime_dependency "logstash-core", '>= 1.4.0', '< 2.0.0'
|
23
|
+
s.add_runtime_dependency "logstash-core", '>= 1.4.0', '< 2.0.0.alpha0'
|
24
24
|
|
25
25
|
s.add_runtime_dependency 'logstash-codec-plain'
|
26
26
|
s.add_runtime_dependency 'addressable'
|
27
|
-
s.add_runtime_dependency 'filewatch', ['>= 0.6.
|
27
|
+
s.add_runtime_dependency 'filewatch', ['>= 0.6.7', '~> 0.6']
|
28
28
|
|
29
29
|
s.add_development_dependency 'stud', ['~> 0.0.19']
|
30
|
-
s.add_development_dependency 'logstash-devutils'
|
30
|
+
s.add_development_dependency 'logstash-devutils', '= 0.0.15'
|
31
31
|
s.add_development_dependency 'logstash-codec-json'
|
32
32
|
end
|
33
33
|
|
data/spec/inputs/file_spec.rb
CHANGED
@@ -6,6 +6,14 @@ require "stud/temporary"
|
|
6
6
|
require "logstash/inputs/file"
|
7
7
|
|
8
8
|
describe "inputs/file" do
|
9
|
+
before(:all) do
|
10
|
+
@abort_on_exception = Thread.abort_on_exception
|
11
|
+
Thread.abort_on_exception = true
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:all) do
|
15
|
+
Thread.abort_on_exception = @abort_on_exception
|
16
|
+
end
|
9
17
|
|
10
18
|
delimiter = (LogStash::Environment.windows? ? "\r\n" : "\n")
|
11
19
|
|
@@ -180,4 +188,45 @@ describe "inputs/file" do
|
|
180
188
|
expect { subject.register }.to raise_error(ArgumentError)
|
181
189
|
end
|
182
190
|
end
|
191
|
+
|
192
|
+
context "when #run is called multiple times", :unix => true do
|
193
|
+
let(:tmpdir_path) { Stud::Temporary.directory }
|
194
|
+
let(:sincedb_path) { Stud::Temporary.pathname }
|
195
|
+
let(:file_path) { "#{tmpdir_path}/a.log" }
|
196
|
+
let(:buffer) { [] }
|
197
|
+
let(:lsof) { [] }
|
198
|
+
let(:stop_proc) do
|
199
|
+
lambda do |input, arr|
|
200
|
+
Thread.new(input, arr) do |i, a|
|
201
|
+
sleep 0.5
|
202
|
+
a << `lsof -p #{Process.pid} | grep "a.log"`
|
203
|
+
i.teardown
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
subject { LogStash::Inputs::File.new("path" => tmpdir_path + "/*.log", "start_position" => "beginning", "sincedb_path" => sincedb_path) }
|
209
|
+
|
210
|
+
after :each do
|
211
|
+
FileUtils.rm_rf(tmpdir_path)
|
212
|
+
FileUtils.rm_rf(sincedb_path)
|
213
|
+
end
|
214
|
+
before do
|
215
|
+
File.open(file_path, "w") do |fd|
|
216
|
+
fd.puts('foo')
|
217
|
+
fd.puts('bar')
|
218
|
+
end
|
219
|
+
end
|
220
|
+
it "should only have one set of files open" do
|
221
|
+
subject.register
|
222
|
+
lsof_before = `lsof -p #{Process.pid} | grep #{file_path}`
|
223
|
+
expect(lsof_before).to eq("")
|
224
|
+
stop_proc.call(subject, lsof)
|
225
|
+
subject.run(buffer)
|
226
|
+
expect(lsof.first).not_to eq("")
|
227
|
+
stop_proc.call(subject, lsof)
|
228
|
+
subject.run(buffer)
|
229
|
+
expect(lsof.last).to eq(lsof.first)
|
230
|
+
end
|
231
|
+
end
|
183
232
|
end
|
metadata
CHANGED
@@ -1,25 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-file
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: logstash-core
|
15
|
-
version_requirements: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.4.0
|
20
|
-
- - <
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 2.0.0
|
23
14
|
requirement: !ruby/object:Gem::Requirement
|
24
15
|
requirements:
|
25
16
|
- - '>='
|
@@ -27,99 +18,108 @@ dependencies:
|
|
27
18
|
version: 1.4.0
|
28
19
|
- - <
|
29
20
|
- !ruby/object:Gem::Version
|
30
|
-
version: 2.0.0
|
21
|
+
version: 2.0.0.alpha0
|
22
|
+
name: logstash-core
|
31
23
|
prerelease: false
|
32
24
|
type: :runtime
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: logstash-codec-plain
|
35
25
|
version_requirements: !ruby/object:Gem::Requirement
|
36
26
|
requirements:
|
37
27
|
- - '>='
|
38
28
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
29
|
+
version: 1.4.0
|
30
|
+
- - <
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0.alpha0
|
33
|
+
- !ruby/object:Gem::Dependency
|
40
34
|
requirement: !ruby/object:Gem::Requirement
|
41
35
|
requirements:
|
42
36
|
- - '>='
|
43
37
|
- !ruby/object:Gem::Version
|
44
38
|
version: '0'
|
39
|
+
name: logstash-codec-plain
|
45
40
|
prerelease: false
|
46
41
|
type: :runtime
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: addressable
|
49
42
|
version_requirements: !ruby/object:Gem::Requirement
|
50
43
|
requirements:
|
51
44
|
- - '>='
|
52
45
|
- !ruby/object:Gem::Version
|
53
46
|
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
54
48
|
requirement: !ruby/object:Gem::Requirement
|
55
49
|
requirements:
|
56
50
|
- - '>='
|
57
51
|
- !ruby/object:Gem::Version
|
58
52
|
version: '0'
|
53
|
+
name: addressable
|
59
54
|
prerelease: false
|
60
55
|
type: :runtime
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: filewatch
|
63
56
|
version_requirements: !ruby/object:Gem::Requirement
|
64
57
|
requirements:
|
65
58
|
- - '>='
|
66
59
|
- !ruby/object:Gem::Version
|
67
|
-
version: 0
|
68
|
-
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: '0.6'
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
71
62
|
requirement: !ruby/object:Gem::Requirement
|
72
63
|
requirements:
|
73
64
|
- - '>='
|
74
65
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.6.
|
66
|
+
version: 0.6.7
|
76
67
|
- - ~>
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0.6'
|
70
|
+
name: filewatch
|
79
71
|
prerelease: false
|
80
72
|
type: :runtime
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
|
-
name: stud
|
83
73
|
version_requirements: !ruby/object:Gem::Requirement
|
84
74
|
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.6.7
|
85
78
|
- - ~>
|
86
79
|
- !ruby/object:Gem::Version
|
87
|
-
version: 0.
|
80
|
+
version: '0.6'
|
81
|
+
- !ruby/object:Gem::Dependency
|
88
82
|
requirement: !ruby/object:Gem::Requirement
|
89
83
|
requirements:
|
90
84
|
- - ~>
|
91
85
|
- !ruby/object:Gem::Version
|
92
86
|
version: 0.0.19
|
87
|
+
name: stud
|
93
88
|
prerelease: false
|
94
89
|
type: :development
|
95
|
-
- !ruby/object:Gem::Dependency
|
96
|
-
name: logstash-devutils
|
97
90
|
version_requirements: !ruby/object:Gem::Requirement
|
98
91
|
requirements:
|
99
|
-
- -
|
92
|
+
- - ~>
|
100
93
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
94
|
+
version: 0.0.19
|
95
|
+
- !ruby/object:Gem::Dependency
|
102
96
|
requirement: !ruby/object:Gem::Requirement
|
103
97
|
requirements:
|
104
|
-
- - '
|
98
|
+
- - '='
|
105
99
|
- !ruby/object:Gem::Version
|
106
|
-
version:
|
100
|
+
version: 0.0.15
|
101
|
+
name: logstash-devutils
|
107
102
|
prerelease: false
|
108
103
|
type: :development
|
109
|
-
- !ruby/object:Gem::Dependency
|
110
|
-
name: logstash-codec-json
|
111
104
|
version_requirements: !ruby/object:Gem::Requirement
|
112
105
|
requirements:
|
113
|
-
- - '
|
106
|
+
- - '='
|
114
107
|
- !ruby/object:Gem::Version
|
115
|
-
version:
|
108
|
+
version: 0.0.15
|
109
|
+
- !ruby/object:Gem::Dependency
|
116
110
|
requirement: !ruby/object:Gem::Requirement
|
117
111
|
requirements:
|
118
112
|
- - '>='
|
119
113
|
- !ruby/object:Gem::Version
|
120
114
|
version: '0'
|
115
|
+
name: logstash-codec-json
|
121
116
|
prerelease: false
|
122
117
|
type: :development
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
123
|
description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
|
124
124
|
email: info@elastic.co
|
125
125
|
executables: []
|
@@ -159,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
159
|
version: '0'
|
160
160
|
requirements: []
|
161
161
|
rubyforge_project:
|
162
|
-
rubygems_version: 2.
|
162
|
+
rubygems_version: 2.4.5
|
163
163
|
signing_key:
|
164
164
|
specification_version: 4
|
165
165
|
summary: Stream events from files.
|