syslogstash 0.4.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|