syslogstash 0.3.0 → 0.4.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: 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
  - - ">="