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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 84f7fa134c15c370b86eb8bc685b4fb900c7c68d
4
- data.tar.gz: 31fbe3ad2d1e28f43a9ab3631b634c3c9fb78ee7
3
+ metadata.gz: 88eb57340c1514fab16aca8395e8dc0821309e95
4
+ data.tar.gz: bfe7b8d15263768f868d42e8749261388b24496a
5
5
  SHA512:
6
- metadata.gz: 9b8d20f5cc43ab7746247866358b6599a1bd92dcefee0b5681db88b820481159d6d15bd0d3167eec071824866f72d9383b1477d1cc420548cdc1e65440f48b81
7
- data.tar.gz: be68092ce035ebec4da5e5a643bbc07b8312cf085a5083f94ab8b6605a903d67b4ba4e06f60ee10fabdd4f71b700427fb021233b1771d95e479ca6628362e23d
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 tags to insert into every message received from each syslog
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 tags
40
+ # These sockets have no additional fields
41
41
  /tmp/sock1:
42
42
  /tmp/sock2:
43
43
 
44
- # This socket will have its messages tagged
45
- /tmp/taggedsock:
46
- foo: bar
47
- baz: wombat
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
@@ -12,7 +12,7 @@ class Syslogstash
12
12
 
13
13
  @writer = LogstashWriter.new(servers, backlog, @metrics)
14
14
 
15
- @readers = sockets.map { |f, tags| SyslogReader.new(f, tags, @writer, @metrics) }
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
- $stderr.puts "Unhandled exception: #{ex.message} (#{ex.class})"
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/puma'
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
- Rack::Handler::Puma.run app, Host: '[::]', Port: 9159
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, tags, logstash, metrics)
11
- @file, @tags, @logstash, @metrics = file, tags, logstash, metrics
10
+ def initialize(file, config, logstash, metrics)
11
+ @file, @logstash, @metrics = file, logstash, metrics
12
+ config ||= {}
12
13
 
13
- log { "initializing syslog socket #{file} with tags #{tags.inspect}" }
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
- $stderr.puts "Error while trying to bind to #{@file}"
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
- $stderr.puts "Unparseable message: #{msg}"
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
@@ -23,12 +23,12 @@ module Syslogstash::Worker
23
23
  private
24
24
 
25
25
  def log
26
- $stderr.puts "#{Time.now.strftime("%F %T.%L")} #{self.class} #{yield.to_s}"
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 "#{Time.now.strftime("%F %T.%L")} #{self.class} #{yield.to_s}"
31
+ $stderr.puts "[#{self.class}] #{yield.to_s}"
32
32
  end
33
33
  end
34
34
  end
@@ -24,7 +24,6 @@ Gem::Specification.new do |s|
24
24
  s.required_ruby_version = ">= 2.1.0"
25
25
 
26
26
  s.add_runtime_dependency 'prometheus-client'
27
- s.add_runtime_dependency 'puma'
28
27
  s.add_runtime_dependency 'rack'
29
28
 
30
29
  s.add_development_dependency 'bundler'
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.1
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-02 00:00:00.000000000 Z
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
File without changes