syslogstash 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e2eed91a10f0ce2e5adede3c8639b37fc4becf3
4
- data.tar.gz: b673ee85fcb7bfb6504aadf1941f27f1293dc1af
3
+ metadata.gz: f013a89558632b9ac7402191a3a1bf7e9399d9af
4
+ data.tar.gz: 5e56866a48fa92bbc4d3decdd6662d130380f409
5
5
  SHA512:
6
- metadata.gz: d02d4b1013baebd1aaccc6b11e1fcaf5f1afb4735e8fa272aef9246ec58c39e13ee963911795696264d5e3deaa5f2d5f0d80c9189f1275ba5bebbc6d2cc04fa1
7
- data.tar.gz: b5f8d87359e5cf32a564db2d0966392deadb2038bbdc8bc55dc93921ab595b834947a114ba1390288ce7847c506af70b7ecd66ec47e396fc686bf1867d5de85c
6
+ metadata.gz: 8adb890310f7fbb3e3c0b388361d9f746b7676cc6ab85730728431df938d48b61f911ac86f50223c4b59d1bd4b6e87d0a71ad5e9d6fe26064864d20a0d3e5319
7
+ data.tar.gz: e67f439643eb30a7af9d7abae8e1abba1d64a0006330d887ebaf128e1377d95d7afd42b121d6149d4669eacb8515d714fb726c65418001e6a6d054b0570d7e89
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ Gemfile.lock
2
2
  /pkg
3
3
  /doc
4
4
  /.yardoc
5
+ /.bundle
data/lib/syslogstash.rb CHANGED
@@ -8,22 +8,26 @@ require 'thwait'
8
8
  #
9
9
  class Syslogstash
10
10
  def initialize(sockets, servers, backlog)
11
- @writer = LogstashWriter.new(servers, backlog)
11
+ @metrics = PrometheusExporter.new
12
12
 
13
- @readers = sockets.map { |f, tags| SyslogReader.new(f, tags, @writer) }
13
+ @writer = LogstashWriter.new(servers, backlog, @metrics)
14
+
15
+ @readers = sockets.map { |f, tags| SyslogReader.new(f, tags, @writer, @metrics) }
14
16
  end
15
17
 
16
18
  def run
19
+ @metrics.run
17
20
  @writer.run
18
21
  @readers.each { |w| w.run }
19
22
 
20
- tw = ThreadsWait.new(@writer.thread, *(@readers.map { |r| r.thread }))
23
+ tw = ThreadsWait.new(@metrics.thread, @writer.thread, *(@readers.map { |r| r.thread }))
21
24
 
22
25
  dead_thread = tw.next_wait
23
26
 
24
27
  if dead_thread == @writer.thread
25
28
  $stderr.puts "Writer thread crashed."
26
- exit 1
29
+ elsif dead_thread == @metrics.thread
30
+ $stderr.puts "Metrics exporter thread crashed."
27
31
  else
28
32
  reader = @readers.find { |r| r.thread == dead_thread }
29
33
 
@@ -33,7 +37,7 @@ class Syslogstash
33
37
  begin
34
38
  dead_thread.join
35
39
  rescue Exception => ex
36
- $stderr.puts "Exception in worker thread was: #{ex.message} (#{ex.class})"
40
+ $stderr.puts "Exception in thread was: #{ex.message} (#{ex.class})"
37
41
  $stderr.puts ex.backtrace.map { |l| " #{l}" }.join("\n")
38
42
  end
39
43
 
@@ -43,4 +47,4 @@ end
43
47
 
44
48
  require_relative 'syslogstash/syslog_reader'
45
49
  require_relative 'syslogstash/logstash_writer'
46
-
50
+ require_relative 'syslogstash/prometheus_exporter'
@@ -10,8 +10,8 @@ class Syslogstash::LogstashWriter
10
10
  # Give it a list of servers, and your writer will be ready to go.
11
11
  # No messages will actually be *delivered*, though, until you call #run.
12
12
  #
13
- def initialize(servers, backlog)
14
- @servers, @backlog = servers.map { |s| URI(s) }, backlog
13
+ def initialize(servers, backlog, metrics)
14
+ @servers, @backlog, @metrics = servers.map { |s| URI(s) }, backlog, metrics
15
15
 
16
16
  unless @servers.all? { |url| url.scheme == 'tcp' }
17
17
  raise ArgumentError,
@@ -28,7 +28,7 @@ class Syslogstash::LogstashWriter
28
28
  #
29
29
  def send_entry(e)
30
30
  @entries_mutex.synchronize do
31
- @entries << e
31
+ @entries << { content: e, arrival_timestamp: Time.now }
32
32
  @entries.shift while @entries.length > @backlog
33
33
  end
34
34
  @worker.run if @worker
@@ -53,9 +53,11 @@ class Syslogstash::LogstashWriter
53
53
  entry = @entries_mutex.synchronize { @entries.shift }
54
54
 
55
55
  current_server do |s|
56
- s.puts entry
56
+ s.puts entry[:content]
57
57
  end
58
58
 
59
+ @metrics.sent(@servers.last, entry[:arrival_timestamp])
60
+
59
61
  # If we got here, we sent successfully, so we don't want
60
62
  # to put the entry back on the queue in the ensure block
61
63
  entry = nil
@@ -75,7 +77,7 @@ class Syslogstash::LogstashWriter
75
77
  #
76
78
  # The yielding is very deliberate: it allows us to centralise all
77
79
  # error detection and handling within this one method, and retry
78
- # sending just be calling `yield` again when we've connected to
80
+ # sending just by calling `yield` again when we've connected to
79
81
  # another server.
80
82
  #
81
83
  def current_server
@@ -0,0 +1,58 @@
1
+ require 'prometheus/client/rack/exporter'
2
+ require 'rack'
3
+ require 'rack/handler/puma'
4
+
5
+ class Syslogstash::PrometheusExporter
6
+ attr_reader :thread
7
+
8
+ def initialize
9
+ @msg_in = prom.counter(:syslogstash_messages_received, "The number of syslog messages received from each log socket")
10
+ @msg_out = prom.counter(:syslogstash_messages_sent, "The number of logstash messages sent to each logstash server")
11
+ @lag = prom.gauge(:syslogstash_lag_ms, "How far behind we are in relaying messages")
12
+ @queue = prom.gauge(:syslogstash_queue_size, "How many messages are queued to be sent")
13
+ end
14
+
15
+ def received(socket, stamp)
16
+ @msg_in.increment(socket_path: socket)
17
+ @queue.set({}, (@queue.get({}) || 0) + 1)
18
+
19
+ if @most_recent_received.nil? || @most_recent_received < stamp
20
+ @most_recent_received = stamp
21
+
22
+ refresh_lag
23
+ end
24
+ end
25
+
26
+ def sent(server, stamp)
27
+ @msg_out.increment(logstash_server: server)
28
+ @queue.set({}, @queue.get({}) - 1)
29
+
30
+ if @most_recent_sent.nil? || @most_recent_sent < stamp
31
+ @most_recent_sent = stamp
32
+
33
+ refresh_lag
34
+ end
35
+ end
36
+
37
+ def run
38
+ @thread = Thread.new do
39
+ app = Rack::Builder.new
40
+ app.use Prometheus::Client::Rack::Exporter
41
+ app.run ->(env) { [404, {'Content-Type' => 'text/plain'}, ['Nope']] }
42
+
43
+ Rack::Handler::Puma.run app, Host: '[::]', Port: 9159
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def prom
50
+ Prometheus::Client.registry
51
+ end
52
+
53
+ def refresh_lag
54
+ if @most_recent_received && @most_recent_sent
55
+ @lag.set({}, ((@most_recent_received.to_f - @most_recent_sent.to_f) * 1000).to_i)
56
+ end
57
+ end
58
+ end
@@ -7,8 +7,8 @@ class Syslogstash::SyslogReader
7
7
 
8
8
  attr_reader :file
9
9
 
10
- def initialize(file, tags, logstash)
11
- @file, @tags, @logstash = file, tags, logstash
10
+ def initialize(file, tags, logstash, metrics)
11
+ @file, @tags, @logstash, @metrics = file, tags, logstash, metrics
12
12
 
13
13
  log { "initializing syslog socket #{file} with tags #{tags.inspect}" }
14
14
  end
@@ -37,6 +37,7 @@ class Syslogstash::SyslogReader
37
37
  loop do
38
38
  msg = socket.recvmsg
39
39
  debug { "Message received: #{msg.inspect}" }
40
+ @metrics.received(@file, Time.now)
40
41
  process_message msg.first.chomp
41
42
  end
42
43
  ensure
data/syslogstash.gemspec CHANGED
@@ -21,7 +21,11 @@ Gem::Specification.new do |s|
21
21
  s.files = `git ls-files -z`.split("\0").reject { |f| f =~ /^(G|spec|Rakefile)/ }
22
22
  s.executables = ["syslogstash"]
23
23
 
24
- s.required_ruby_version = ">= 2.0.0"
24
+ s.required_ruby_version = ">= 2.1.0"
25
+
26
+ s.add_runtime_dependency 'prometheus-client'
27
+ s.add_runtime_dependency 'puma'
28
+ s.add_runtime_dependency 'rack'
25
29
 
26
30
  s.add_development_dependency 'bundler'
27
31
  s.add_development_dependency 'github-release'
metadata CHANGED
@@ -1,15 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: syslogstash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.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-05-24 00:00:00.000000000 Z
11
+ date: 2016-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prometheus-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
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
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
13
55
  - !ruby/object:Gem::Dependency
14
56
  name: bundler
15
57
  requirement: !ruby/object:Gem::Requirement
@@ -171,6 +213,7 @@ files:
171
213
  - lib/.gitkeep
172
214
  - lib/syslogstash.rb
173
215
  - lib/syslogstash/logstash_writer.rb
216
+ - lib/syslogstash/prometheus_exporter.rb
174
217
  - lib/syslogstash/syslog_reader.rb
175
218
  - lib/syslogstash/worker.rb
176
219
  - syslogstash.gemspec
@@ -185,7 +228,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
228
  requirements:
186
229
  - - ">="
187
230
  - !ruby/object:Gem::Version
188
- version: 2.0.0
231
+ version: 2.1.0
189
232
  required_rubygems_version: !ruby/object:Gem::Requirement
190
233
  requirements:
191
234
  - - ">="