logstash-input-journald 0.0.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df132fdfd9561d73df5f49ac4c7408a15df597d3
4
+ data.tar.gz: 3c34d90fecb45efee4fa6eadad7e37233539be51
5
+ SHA512:
6
+ metadata.gz: 355034993d7381aa58acead667a6e5a3fa79cae74387c1acb118e9c02f3ec321409467a5b2655a9d7673c068b2b0280779a28ecb3e87d8924f85d6931355f413
7
+ data.tar.gz: 7350329c4f27f81c495fcd498f89fa5443110a10b50280f04c05463cd5ece4ebf85fbfb5fb6b5eae46991532489c45508ca83733aac24700d47d46405b5034fd
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ Gemfile.lock
3
+ .bundle
4
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+ gem "logstash", :github => "elasticsearch/logstash", :branch => "1.5"
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012-2014 Elasticsearch <http://www.elasticsearch.org>
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ logstash-input-journald
2
+ =======================
3
+
4
+ POC systemd journal Logstash input
5
+
6
+ Example config
7
+ --------------
8
+ ```
9
+ input {
10
+ journald {
11
+ lowercase => true
12
+ seekto => "head"
13
+ thisboot => true
14
+ type => "systemd"
15
+ tags => [ "coreos" ]
16
+ }
17
+ }
18
+
19
+ output {
20
+ stdout {codec => rubydebug}
21
+ }
22
+ ```
23
+
24
+ Install with
25
+ ------------
26
+ ```
27
+ git clone https://github.com/stuart-warren/logstash-input-journald.git
28
+ cd logstash-input-journald
29
+ gem build logstash-input-journald.gemspec
30
+ sudo /path/to/logstash/bin/plugin install /path/to/git/logstash-input-journald/logstash-input-journald-0.0.1.gem
31
+ ```
32
+ Sincedb
33
+ ----
34
+
35
+ This plugin creates a sincedb in your home, called .sincedb\_journal.
36
+ It automatically stores the cursor to the journal there, so when you restart logstash, only new messages are read.
37
+ When executing the plugin the second time (which means the sincedb exists), ``seekto``, and ``thisboot`` are ignored.
38
+ If you don't want the sincedb, configure it's path to /dev/null.
39
+ Tips
40
+ ----
41
+
42
+ Ensure the user you are running logstash as has read access to the journal files ``/var/log/journal/*/*``
43
+
44
+ Issues
45
+ ------
46
+
47
+ Killing the logstash process takes a long time...
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ @files=[]
2
+
3
+ task :default do
4
+ system("rake -T")
5
+ end
6
+
7
+ require "logstash/devutils/rake"
@@ -0,0 +1,163 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/threadable"
3
+ require "logstash/namespace"
4
+ require "socket"
5
+ require "systemd/journal"
6
+ require "fileutils" # For touch
7
+
8
+ # Pull events from a local systemd journal.
9
+ #
10
+ # See requirements https://github.com/ledbettj/systemd-journal
11
+ class LogStash::Inputs::Journald < LogStash::Inputs::Threadable
12
+
13
+ config_name "journald"
14
+
15
+ # Where in the journal to start capturing logs
16
+ # Options: head, tail
17
+ config :seekto, :validate => [ "head", "tail" ], :default => "tail"
18
+
19
+ # System journal flags
20
+ # 0 = all avalable
21
+ # 1 = local only
22
+ # 2 = runtime only
23
+ # 4 = system only
24
+ #
25
+ config :flags, :validate => [0, 1, 2, 4], :default => 0
26
+
27
+ # Path to read journal files from
28
+ #
29
+ config :path, :validate => :string, :default => "/var/log/journal"
30
+
31
+ # Filter on events. Not heavily tested.
32
+ #
33
+ config :filter, :validate => :hash, :required => false, :default => {}
34
+
35
+ # Filter logs since the system booted (only relevant with seekto => "head")
36
+ #
37
+ config :thisboot, :validate => :boolean, :default => true
38
+
39
+ # Lowercase annoying UPPERCASE fieldnames. (May clobber existing fields)
40
+ #
41
+ config :lowercase, :validate => :boolean, :default => false
42
+
43
+ # Where to write the sincedb database (keeps track of the current
44
+ # position of the journal). The default will write
45
+ # the sincedb file to matching `$HOME/.sincedb_journal`
46
+ #
47
+ config :sincedb_path, :validate => :string
48
+
49
+ # How often (in seconds) to write a since database with the current position of
50
+ # the journal.
51
+ #
52
+ config :sincedb_write_interval, :validate => :number, :default => 15
53
+
54
+ public
55
+ def register
56
+ opts = {
57
+ flags: @flags,
58
+ path: @path,
59
+ }
60
+ @hostname = Socket.gethostname
61
+ @journal = Systemd::Journal.new(opts)
62
+ @cursor = ""
63
+ @written_cursor = ""
64
+ @cursor_lock = Mutex.new
65
+ if @thisboot
66
+ @filter[:_boot_id] = Systemd::Id128.boot_id
67
+ end
68
+ if @sincedb_path.nil?
69
+ if ENV["SINCEDB_DIR"].nil? && ENV["HOME"].nil?
70
+ @logger.error("No SINCEDB_DIR or HOME environment variable set, I don't know where " \
71
+ "to keep track of the files I'm watching. Either set " \
72
+ "HOME or SINCEDB_DIR in your environment, or set sincedb_path in " \
73
+ "in your Logstash config for the file input with " \
74
+ "path '#{@path.inspect}'")
75
+ raise(LogStash::ConfigurationError, "Sincedb can not be created.")
76
+ end
77
+ sincedb_dir = ENV["SINCEDB_DIR"] || ENV["HOME"]
78
+ @sincedb_path = File.join(sincedb_dir, ".sincedb_journal")
79
+ @logger.info("No sincedb_path set, generating one for the journal",
80
+ :sincedb_path => @sincedb_path)
81
+ end
82
+ # (Create and) read sincedb
83
+ FileUtils.touch(@sincedb_path)
84
+ @cursor = IO.read(@sincedb_path)
85
+ # Write sincedb in thread
86
+ @sincedb_writer = Thread.new do
87
+ loop do
88
+ sleep @sincedb_write_interval
89
+ if @cursor != @written_cursor
90
+ file = File.open(@sincedb_path, 'w+')
91
+ file.puts @cursor
92
+ file.close
93
+ @cursor_lock.synchronize {
94
+ @written_cursor = @cursor
95
+ }
96
+ end
97
+ end
98
+ end
99
+ end # def register
100
+
101
+ def run(queue)
102
+ if @cursor.strip.length == 0
103
+ @journal.seek(@seekto.to_sym)
104
+
105
+ # We must make one movement in order for the journal C api or else
106
+ # the @journal.watch call will start from the beginning of the
107
+ # journal. see:
108
+ # https://github.com/ledbettj/systemd-journal/issues/55
109
+ if @seekto == 'tail'
110
+ @journal.move_previous
111
+ end
112
+
113
+ @journal.filter(@filter)
114
+ else
115
+ @journal.seek(@cursor)
116
+ @journal.move_next # Without this, the last event will be read again
117
+ end
118
+ @journal.watch do |entry|
119
+ timestamp = entry.realtime_timestamp
120
+ event = LogStash::Event.new(
121
+ entry.to_h_lower(@lowercase).merge(
122
+ "@timestamp" => timestamp,
123
+ "host" => entry._hostname || @hostname,
124
+ "cursor" => @journal.cursor
125
+ )
126
+ )
127
+ decorate(event)
128
+ queue << event
129
+ @cursor_lock.synchronize {
130
+ @cursor = @journal.cursor
131
+ }
132
+ end
133
+ end # def run
134
+
135
+ public
136
+ def teardown # FIXME: doesn't really seem to work...
137
+ return finished unless @journal # Ignore multiple calls
138
+
139
+ @logger.debug("journald shutting down.")
140
+ @journal = nil
141
+ Thread.kill(@sincedb_writer)
142
+ # Write current cursor
143
+ file = File.open(@sincedb_path, 'w+')
144
+ file.puts @cursor
145
+ file.close
146
+ @cursor = nil
147
+ finished
148
+ end # def teardown
149
+
150
+ end # class LogStash::Inputs::Journald
151
+
152
+ # Monkey patch Systemd::JournalEntry
153
+ module Systemd
154
+ class JournalEntry
155
+ def to_h_lower(is_lowercase)
156
+ if is_lowercase
157
+ @entry.each_with_object({}) { |(k, v), h| h[k.downcase] = v.dup.force_encoding('iso-8859-1').encode('utf-8') }
158
+ else
159
+ @entry.each_with_object({}) { |(k, v), h| h[k] = v.dup.force_encoding('iso-8859-1').encode('utf-8') }
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,32 @@
1
+ Gem::Specification.new do |s|
2
+
3
+ s.name = 'logstash-input-journald'
4
+ s.version = '0.0.4'
5
+ s.licenses = ['Apache License (2.0)']
6
+ s.summary = "Read events from local systemd journal"
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"
8
+ s.authors = ["stuart-warren"]
9
+ s.email = 'stuart.warren@ocado.com'
10
+ s.homepage = "http://www.elasticsearch.org/guide/en/logstash/current/index.html"
11
+ s.require_paths = ["lib"]
12
+
13
+ # Files
14
+ s.files = `git ls-files`.split($\)+::Dir.glob('vendor/*')
15
+
16
+ # Tests
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+
19
+ # Special flag to let us know this is actually a logstash plugin
20
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
21
+
22
+ # Gem dependencies
23
+ s.add_runtime_dependency 'logstash-core', '>= 1.4.0', '< 2.0.0'
24
+
25
+ s.add_runtime_dependency 'logstash-codec-plain'
26
+ s.add_runtime_dependency 'logstash-codec-line'
27
+ s.add_runtime_dependency 'logstash-codec-json'
28
+ s.add_runtime_dependency 'logstash-codec-json_lines'
29
+ s.add_runtime_dependency 'ffi'
30
+ s.add_runtime_dependency 'systemd-journal', '~> 1.2.2'
31
+ s.add_development_dependency 'logstash-devutils'
32
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "socket"
4
+ require "logstash/inputs/journald"
5
+
6
+ describe LogStash::Inputs::Journald do
7
+ context "Ummm" do
8
+ it "no tests here" do
9
+
10
+ end
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,172 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-input-journald
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - stuart-warren
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '>='
17
+ - !ruby/object:Gem::Version
18
+ version: 1.4.0
19
+ - - <
20
+ - !ruby/object:Gem::Version
21
+ version: 2.0.0
22
+ name: logstash-core
23
+ prerelease: false
24
+ type: :runtime
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.0
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ name: logstash-codec-plain
40
+ prerelease: false
41
+ type: :runtime
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ name: logstash-codec-line
54
+ prerelease: false
55
+ type: :runtime
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ name: logstash-codec-json
68
+ prerelease: false
69
+ type: :runtime
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ name: logstash-codec-json_lines
82
+ prerelease: false
83
+ type: :runtime
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ name: ffi
96
+ prerelease: false
97
+ type: :runtime
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ~>
107
+ - !ruby/object:Gem::Version
108
+ version: 1.2.2
109
+ name: systemd-journal
110
+ prerelease: false
111
+ type: :runtime
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ~>
115
+ - !ruby/object:Gem::Version
116
+ version: 1.2.2
117
+ - !ruby/object:Gem::Dependency
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ name: logstash-devutils
124
+ prerelease: false
125
+ type: :development
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ 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
132
+ email: stuart.warren@ocado.com
133
+ executables: []
134
+ extensions: []
135
+ extra_rdoc_files: []
136
+ files:
137
+ - .gitignore
138
+ - Gemfile
139
+ - LICENSE
140
+ - README.md
141
+ - Rakefile
142
+ - lib/logstash/inputs/journald.rb
143
+ - logstash-input-journald.gemspec
144
+ - spec/inputs/journald_spec.rb
145
+ homepage: http://www.elasticsearch.org/guide/en/logstash/current/index.html
146
+ licenses:
147
+ - Apache License (2.0)
148
+ metadata:
149
+ logstash_plugin: 'true'
150
+ logstash_group: input
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.4.8
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: Read events from local systemd journal
171
+ test_files:
172
+ - spec/inputs/journald_spec.rb