syslogstash 0.4.1 → 1.0.0
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/README.md +28 -6
- data/lib/syslogstash.rb +5 -5
- data/lib/syslogstash/logstash_writer.rb +1 -1
- data/lib/syslogstash/prometheus_exporter.rb +7 -2
- data/lib/syslogstash/syslog_reader.rb +55 -7
- data/lib/syslogstash/worker.rb +2 -2
- data/syslogstash.gemspec +0 -1
- metadata +2 -17
- data/lib/.gitkeep +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88eb57340c1514fab16aca8395e8dc0821309e95
|
4
|
+
data.tar.gz: bfe7b8d15263768f868d42e8749261388b24496a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cee42ae44c931c73e868e6254987fc1900f5e541bbeb4b44dd5c07b8c6feecf2f572223b543648a7a30ba33c6c8e08b54e3e7c162ada82efcdf262bf58007ec8
|
7
|
+
data.tar.gz: 4fa56e690b3715e7179c863afa41e2fd85946b570ad0d1f2a2df6fba64883b25a0b2c102a5c5a9fd9503dd33e3f43b69c15ec08d140d5e0e839627de4e2619ac
|
data/README.md
CHANGED
@@ -31,20 +31,25 @@ The file which describes how `syslogstash` will operate is a fairly simple
|
|
31
31
|
YAML file. It consists of two sections, `sockets` and `servers`, which list
|
32
32
|
the UNIX sockets to listen for syslog messages on, and the URLs of logstash
|
33
33
|
servers to send the resulting log entries to. Optionally, you can specify
|
34
|
-
additional
|
34
|
+
additional fields to insert into every message received from each syslog
|
35
35
|
socket.
|
36
36
|
|
37
37
|
It looks like this:
|
38
38
|
|
39
39
|
sockets:
|
40
|
-
# These sockets have no additional
|
40
|
+
# These sockets have no additional fields
|
41
41
|
/tmp/sock1:
|
42
42
|
/tmp/sock2:
|
43
43
|
|
44
|
-
# This socket will have its messages
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
# This socket will have some fields added to its messages, and will
|
45
|
+
# send all messages to a couple of other sockets, too
|
46
|
+
/tmp/supersock:
|
47
|
+
add_fields:
|
48
|
+
foo: bar
|
49
|
+
baz: wombat
|
50
|
+
relay_to:
|
51
|
+
- /tmp/relaysock1
|
52
|
+
- /tmp/relaysock2
|
48
53
|
|
49
54
|
# Every log entry received will be sent to *exactly* one of these
|
50
55
|
# servers. This provides high availability for your log messages.
|
@@ -54,6 +59,23 @@ It looks like this:
|
|
54
59
|
- tcp://10.0.0.2:5151
|
55
60
|
|
56
61
|
|
62
|
+
### Socket configuration
|
63
|
+
|
64
|
+
Each socket has a configuration associated with it. Using this
|
65
|
+
configuration, you can add logstash fields to each entry, and configure
|
66
|
+
socket relaying.
|
67
|
+
|
68
|
+
The following keys are available under each socket's path:
|
69
|
+
|
70
|
+
* `add_fields` -- A hash of additional fields to add to every log entry that
|
71
|
+
is received on this socket, before it is passed on to logstash.
|
72
|
+
|
73
|
+
* `relay_to` -- A list of sockets to send all received messages to. This is
|
74
|
+
useful in a very limited range of circumstances, when (for instance) you
|
75
|
+
have another syslog socket consumer that wants to get in on the act, like
|
76
|
+
a legacy syslogd.
|
77
|
+
|
78
|
+
|
57
79
|
## Logstash server configuration
|
58
80
|
|
59
81
|
You'll need to setup a TCP input, with the `json_lines` codec, for
|
data/lib/syslogstash.rb
CHANGED
@@ -12,7 +12,7 @@ class Syslogstash
|
|
12
12
|
|
13
13
|
@writer = LogstashWriter.new(servers, backlog, @metrics)
|
14
14
|
|
15
|
-
@readers = sockets.map { |f,
|
15
|
+
@readers = sockets.map { |f, cfg| SyslogReader.new(f, cfg, @writer, @metrics) }
|
16
16
|
end
|
17
17
|
|
18
18
|
def run
|
@@ -25,19 +25,19 @@ class Syslogstash
|
|
25
25
|
dead_thread = tw.next_wait
|
26
26
|
|
27
27
|
if dead_thread == @writer.thread
|
28
|
-
$stderr.puts "Writer thread crashed."
|
28
|
+
$stderr.puts "[Syslogstash] Writer thread crashed."
|
29
29
|
elsif dead_thread == @metrics.thread
|
30
|
-
$stderr.puts "Metrics exporter thread crashed."
|
30
|
+
$stderr.puts "[Syslogstash] Metrics exporter thread crashed."
|
31
31
|
else
|
32
32
|
reader = @readers.find { |r| r.thread == dead_thread }
|
33
33
|
|
34
|
-
$stderr.puts "Reader thread for #{reader.file} crashed."
|
34
|
+
$stderr.puts "[Syslogstash] Reader thread for #{reader.file} crashed."
|
35
35
|
end
|
36
36
|
|
37
37
|
begin
|
38
38
|
dead_thread.join
|
39
39
|
rescue Exception => ex
|
40
|
-
$stderr.puts "Exception in thread was: #{ex.message} (#{ex.class})"
|
40
|
+
$stderr.puts "[Syslogstash] Exception in thread was: #{ex.message} (#{ex.class})"
|
41
41
|
$stderr.puts ex.backtrace.map { |l| " #{l}" }.join("\n")
|
42
42
|
end
|
43
43
|
|
@@ -62,7 +62,7 @@ class Syslogstash::LogstashWriter
|
|
62
62
|
# to put the entry back on the queue in the ensure block
|
63
63
|
entry = nil
|
64
64
|
rescue StandardError => ex
|
65
|
-
|
65
|
+
log { "Unhandled exception: #{ex.message} (#{ex.class})" }
|
66
66
|
$stderr.puts ex.backtrace.map { |l| " #{l}" }.join("\n")
|
67
67
|
ensure
|
68
68
|
@entries_mutex.synchronize { @entries.unshift if entry }
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'prometheus/client/rack/exporter'
|
2
2
|
require 'rack'
|
3
|
-
require 'rack/handler/
|
3
|
+
require 'rack/handler/webrick'
|
4
|
+
require 'logger'
|
4
5
|
|
5
6
|
class Syslogstash::PrometheusExporter
|
6
7
|
attr_reader :thread
|
@@ -40,7 +41,11 @@ class Syslogstash::PrometheusExporter
|
|
40
41
|
app.use Prometheus::Client::Rack::Exporter
|
41
42
|
app.run ->(env) { [404, {'Content-Type' => 'text/plain'}, ['Nope']] }
|
42
43
|
|
43
|
-
|
44
|
+
logger = Logger.new($stderr)
|
45
|
+
logger.level = Logger::INFO
|
46
|
+
logger.formatter = proc { |s, t, p, m| "[Syslogstash::PrometheusExporter::WEBrick] #{m}\n" }
|
47
|
+
|
48
|
+
Rack::Handler::WEBrick.run app, BindAddress: '::', Port: 9159, Logger: logger, AccessLog: []
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
@@ -7,10 +7,24 @@ class Syslogstash::SyslogReader
|
|
7
7
|
|
8
8
|
attr_reader :file
|
9
9
|
|
10
|
-
def initialize(file,
|
11
|
-
@file, @
|
10
|
+
def initialize(file, config, logstash, metrics)
|
11
|
+
@file, @logstash, @metrics = file, logstash, metrics
|
12
|
+
config ||= {}
|
12
13
|
|
13
|
-
|
14
|
+
@add_fields = config['add_fields'] || {}
|
15
|
+
@relay_to = config['relay_to'] || []
|
16
|
+
|
17
|
+
unless @add_fields.is_a? Hash
|
18
|
+
raise ArgumentError,
|
19
|
+
"add_fields parameter to socket #{file} must be a hash"
|
20
|
+
end
|
21
|
+
|
22
|
+
unless @relay_to.is_a? Array
|
23
|
+
raise ArgumentError,
|
24
|
+
"relay_to parameter to socket #{file} must be an array"
|
25
|
+
end
|
26
|
+
|
27
|
+
log { "initialized syslog socket #{file} with config #{config.inspect}" }
|
14
28
|
end
|
15
29
|
|
16
30
|
# Start reading from the socket file, parsing entries, and flinging
|
@@ -28,7 +42,7 @@ class Syslogstash::SyslogReader
|
|
28
42
|
File.unlink(@file) rescue nil
|
29
43
|
retry
|
30
44
|
rescue SystemCallError
|
31
|
-
|
45
|
+
log { "Error while trying to bind to #{@file}" }
|
32
46
|
raise
|
33
47
|
end
|
34
48
|
|
@@ -39,6 +53,7 @@ class Syslogstash::SyslogReader
|
|
39
53
|
debug { "Message received: #{msg.inspect}" }
|
40
54
|
@metrics.received(@file, Time.now)
|
41
55
|
process_message msg.first.chomp
|
56
|
+
relay_message msg.first
|
42
57
|
end
|
43
58
|
ensure
|
44
59
|
socket.close
|
@@ -87,7 +102,7 @@ class Syslogstash::SyslogReader
|
|
87
102
|
|
88
103
|
@logstash.send_entry(log_entry)
|
89
104
|
else
|
90
|
-
|
105
|
+
log { "Unparseable message: #{msg}" }
|
91
106
|
end
|
92
107
|
end
|
93
108
|
|
@@ -100,13 +115,46 @@ class Syslogstash::SyslogReader
|
|
100
115
|
h[:severity_name] = SEVERITIES[h[:severity]]
|
101
116
|
|
102
117
|
e.merge!(h.delete_if { |k,v| v.nil? })
|
103
|
-
|
104
|
-
e.merge!(@tags) if @tags.is_a? Hash
|
118
|
+
e.merge!(@add_fields)
|
105
119
|
|
106
120
|
debug { "Log entry is: #{e.inspect}" }
|
107
121
|
end
|
108
122
|
end
|
109
123
|
|
124
|
+
def relay_message(msg)
|
125
|
+
@currently_failed ||= {}
|
126
|
+
|
127
|
+
@relay_to.each do |f|
|
128
|
+
s = Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM, 0)
|
129
|
+
begin
|
130
|
+
s.connect(Socket.pack_sockaddr_un(f))
|
131
|
+
rescue Errno::ENOENT
|
132
|
+
# Socket doesn't exist; we don't care enough about this to bother
|
133
|
+
# reporting it. People will figure it out themselves soon enough.
|
134
|
+
rescue StandardError => ex
|
135
|
+
log { "Error while connecting to relay socket #{f}: #{ex.message} (#{ex.class})" }
|
136
|
+
next
|
137
|
+
end
|
138
|
+
|
139
|
+
begin
|
140
|
+
s.sendmsg_nonblock(msg)
|
141
|
+
if @currently_failed[f]
|
142
|
+
log { "Backlog on socket #{f} has cleared; messages are being delivered again" }
|
143
|
+
@currently_failed[f] = false
|
144
|
+
end
|
145
|
+
rescue Errno::ENOTCONN
|
146
|
+
# Socket isn't being listened to. Not our problem.
|
147
|
+
rescue IO::EAGAINWaitWritable
|
148
|
+
unless @currently_failed[f]
|
149
|
+
log { "Socket #{f} is backlogged; messages to this socket from socket #{@file} are being discarded undelivered" }
|
150
|
+
@currently_failed = true
|
151
|
+
end
|
152
|
+
rescue StandardError => ex
|
153
|
+
log { "Failed to relay message to socket #{f} from #{@file}: #{ex.message} (#{ex.class})" }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
110
158
|
FACILITIES = %w{
|
111
159
|
kern
|
112
160
|
user
|
data/lib/syslogstash/worker.rb
CHANGED
@@ -23,12 +23,12 @@ module Syslogstash::Worker
|
|
23
23
|
private
|
24
24
|
|
25
25
|
def log
|
26
|
-
$stderr.puts "#{
|
26
|
+
$stderr.puts "[#{self.class}] #{yield.to_s}"
|
27
27
|
end
|
28
28
|
|
29
29
|
def debug
|
30
30
|
if ENV['DEBUG_SYSLOGSTASH']
|
31
|
-
$stderr.puts "#{
|
31
|
+
$stderr.puts "[#{self.class}] #{yield.to_s}"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
data/syslogstash.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: syslogstash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Palmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prometheus-client
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: puma
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: rack
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -210,7 +196,6 @@ files:
|
|
210
196
|
- LICENCE
|
211
197
|
- README.md
|
212
198
|
- bin/syslogstash
|
213
|
-
- lib/.gitkeep
|
214
199
|
- lib/syslogstash.rb
|
215
200
|
- lib/syslogstash/logstash_writer.rb
|
216
201
|
- lib/syslogstash/prometheus_exporter.rb
|
data/lib/.gitkeep
DELETED
File without changes
|