riemann-client 0.2.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d87901a4f9a48ce3fcae0940d204c36cdabd949d4495b99f2445735fb2deddd8
4
+ data.tar.gz: d64e574731d1a1dce475fb2227eaf2fdd4f3bf581bd20bae33fb92a22321adb2
5
+ SHA512:
6
+ metadata.gz: b75e2bd1256a168dc185ceaf53c80f045e2011fa1fa2e2717147e48c35d65b767df60182884a154575e09598b4305cda0e9cc16c0f5a2d3e0ab3218fc6d4380f
7
+ data.tar.gz: 1b5d7a51402e65c7994b91bd903f2dae9881390ee890058a881311c3bb57bfb12139065c1a0d466c76f2438677789ad8f3347351e26d1005f704f673f8c06025
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches:
7
+ - main
8
+ pull_request:
9
+ branches:
10
+ - main
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ ruby-version:
18
+ - 2.7
19
+ - 3.0
20
+ - 3.1
21
+ steps:
22
+ - uses: actions/checkout@v2
23
+ - name: Setup Ruby
24
+ uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby-version }}
27
+ bundler-cache: true
28
+ - name: Install riemann
29
+ run: |
30
+ wget --quiet https://github.com/riemann/riemann/releases/download/0.3.8/riemann_0.3.8_all.deb
31
+ sudo dpkg -i riemann_0.3.8_all.deb
32
+
33
+ sudo systemctl stop riemann
34
+
35
+ sudo openssl genrsa -out /etc/riemann/riemann_server.key 4096
36
+ sudo openssl pkcs8 -topk8 -nocrypt -in /etc/riemann/riemann_server.key -out /etc/riemann/riemann_server.pkcs8
37
+ sudo openssl req -x509 -new -nodes -key /etc/riemann/riemann_server.key -days 7 -out /etc/riemann/riemann_server.crt -subj '/CN=localhost'
38
+ sudo chmod +r /etc/riemann/riemann_server.pkcs8
39
+ sudo cp -v spec/riemann.config /etc/riemann/
40
+
41
+ sudo systemctl start riemann
42
+
43
+ while ! nc -z localhost 5555; do sleep 1; done
44
+ - name: Run the test suite
45
+ run: bundle exec bacon spec/*.rb
data/.gitignore CHANGED
@@ -4,3 +4,7 @@ pkg/
4
4
  .DS_Store
5
5
  .*.swp
6
6
  *.log
7
+ .bundle/
8
+ bin/
9
+ vendor/
10
+ Gemfile.lock
data/CHANGELOG.md ADDED
@@ -0,0 +1,76 @@
1
+ # Changelog
2
+
3
+ ## [1.0.0](https://github.com/riemann/riemann-ruby-client/tree/1.0.0) (2022-06-16)
4
+
5
+ [Full Changelog](https://github.com/riemann/riemann-ruby-client/compare/0.2.6...1.0.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Add support for micro-seconds resolution [\#34](https://github.com/riemann/riemann-ruby-client/pull/34) ([smortex](https://github.com/smortex))
10
+ - Add support for TLS [\#33](https://github.com/riemann/riemann-ruby-client/pull/33) ([smortex](https://github.com/smortex))
11
+ - Add support for IPv6 addresses [\#30](https://github.com/riemann/riemann-ruby-client/pull/30) ([dch](https://github.com/dch))
12
+
13
+ **Merged pull requests:**
14
+
15
+ - Fix race conditions in CI [\#35](https://github.com/riemann/riemann-ruby-client/pull/35) ([smortex](https://github.com/smortex))
16
+ - Modernize and setup CI [\#32](https://github.com/riemann/riemann-ruby-client/pull/32) ([smortex](https://github.com/smortex))
17
+ - Bump beefcake dependency [\#29](https://github.com/riemann/riemann-ruby-client/pull/29) ([dch](https://github.com/dch))
18
+
19
+ ## [0.2.6](https://github.com/riemann/riemann-ruby-client/tree/0.2.6) (2015-11-18)
20
+
21
+ [Full Changelog](https://github.com/riemann/riemann-ruby-client/compare/0.2.5...0.2.6)
22
+
23
+ **Merged pull requests:**
24
+
25
+ - Client should yield self [\#22](https://github.com/riemann/riemann-ruby-client/pull/22) ([agile](https://github.com/agile))
26
+ - Allow TCP sockets to work on Windows [\#21](https://github.com/riemann/riemann-ruby-client/pull/21) ([sgran](https://github.com/sgran))
27
+ - README hash syntax fix [\#20](https://github.com/riemann/riemann-ruby-client/pull/20) ([squarism](https://github.com/squarism))
28
+
29
+ ## [0.2.5](https://github.com/riemann/riemann-ruby-client/tree/0.2.5) (2015-02-05)
30
+
31
+ [Full Changelog](https://github.com/riemann/riemann-ruby-client/compare/0.2.4...0.2.5)
32
+
33
+ ## [0.2.4](https://github.com/riemann/riemann-ruby-client/tree/0.2.4) (2015-02-03)
34
+
35
+ [Full Changelog](https://github.com/riemann/riemann-ruby-client/compare/0.2.2...0.2.4)
36
+
37
+ **Merged pull requests:**
38
+
39
+ - Tightening beefcake requirement [\#19](https://github.com/riemann/riemann-ruby-client/pull/19) ([aphyr](https://github.com/aphyr))
40
+ - Fix for \#17, plus test and connection refactor [\#18](https://github.com/riemann/riemann-ruby-client/pull/18) ([RKelln](https://github.com/RKelln))
41
+ - Ensure that we close the connection if we got an error back [\#16](https://github.com/riemann/riemann-ruby-client/pull/16) ([eric](https://github.com/eric))
42
+ - String\#clear doesn't exist in 1.8 [\#15](https://github.com/riemann/riemann-ruby-client/pull/15) ([eric](https://github.com/eric))
43
+ - Tcp client with timeouts [\#14](https://github.com/riemann/riemann-ruby-client/pull/14) ([eric](https://github.com/eric))
44
+
45
+ ## [0.2.2](https://github.com/riemann/riemann-ruby-client/tree/0.2.2) (2013-05-28)
46
+
47
+ [Full Changelog](https://github.com/riemann/riemann-ruby-client/compare/0.2.0...0.2.2)
48
+
49
+ **Merged pull requests:**
50
+
51
+ - Update README with timeout information [\#11](https://github.com/riemann/riemann-ruby-client/pull/11) ([gsandie](https://github.com/gsandie))
52
+ - Add tcp socket timeouts [\#10](https://github.com/riemann/riemann-ruby-client/pull/10) ([gsandie](https://github.com/gsandie))
53
+ - Socket can not be opened in method connected? [\#9](https://github.com/riemann/riemann-ruby-client/pull/9) ([vadv](https://github.com/vadv))
54
+
55
+ ## [0.2.0](https://github.com/riemann/riemann-ruby-client/tree/0.2.0) (2013-04-02)
56
+
57
+ [Full Changelog](https://github.com/riemann/riemann-ruby-client/compare/version-0.0.7...0.2.0)
58
+
59
+ **Merged pull requests:**
60
+
61
+ - Get and set attributes using hash-style accessors [\#8](https://github.com/riemann/riemann-ruby-client/pull/8) ([jegt](https://github.com/jegt))
62
+ - Add extra attributes added to the Event constructor to the event as Attribute instances [\#7](https://github.com/riemann/riemann-ruby-client/pull/7) ([jegt](https://github.com/jegt))
63
+ - Change attribute name to attribute key [\#6](https://github.com/riemann/riemann-ruby-client/pull/6) ([b](https://github.com/b))
64
+ - Arbitrary attributes on events [\#5](https://github.com/riemann/riemann-ruby-client/pull/5) ([b](https://github.com/b))
65
+
66
+ ## [version-0.0.7](https://github.com/riemann/riemann-ruby-client/tree/version-0.0.7) (2012-04-16)
67
+
68
+ [Full Changelog](https://github.com/riemann/riemann-ruby-client/compare/fe25a3b01681612defc39250006748069e06a172...version-0.0.7)
69
+
70
+ **Merged pull requests:**
71
+
72
+ - Add support for ruby 1.8 [\#1](https://github.com/riemann/riemann-ruby-client/pull/1) ([eric](https://github.com/eric))
73
+
74
+
75
+
76
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem 'github_changelog_generator'
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'riemann'
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require 'github_changelog_generator/task'
6
+
7
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
8
+ config.user = 'riemann'
9
+ config.project = 'riemann-ruby-client'
10
+ config.future_release = Riemann::VERSION
11
+ config.add_issues_wo_labels = false
12
+ end
@@ -0,0 +1,91 @@
1
+ require 'openssl'
2
+ require_relative 'tcp_socket'
3
+
4
+ module Riemann
5
+ class Client
6
+ # Socket: A specialized socket that has been configure
7
+ class SSLSocket < TcpSocket
8
+
9
+ def initialize(options = {})
10
+ super(options)
11
+ @key_file = options[:key_file]
12
+ @cert_file = options[:cert_file]
13
+ @ca_file = options[:ca_file]
14
+ @ssl_verify = options[:ssl_verify]
15
+ end
16
+
17
+ def ssl_context
18
+ @ssl_context ||= OpenSSL::SSL::SSLContext.new.tap do |ctx|
19
+ ctx.key = OpenSSL::PKey::RSA.new(open(@key_file) {|f| f.read})
20
+ ctx.cert = OpenSSL::X509::Certificate.new(open(@cert_file) {|f| f.read})
21
+ ctx.ca_file = @ca_file if @ca_file
22
+ ctx.ssl_version = :TLSv1_2
23
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER if @ssl_verify
24
+ end
25
+ end
26
+
27
+ # Internal: Connect to the give address within the timeout.
28
+ #
29
+ # Make an attempt to connect to a single address within the given timeout.
30
+ #
31
+ # Return the ::Socket when it is connected, or raise an Error if no
32
+ # connection was possible.
33
+ def connect_nonblock( addr, timeout )
34
+ sock = super(addr, timeout)
35
+ ssl_socket = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
36
+ ssl_socket.sync = true
37
+
38
+ begin
39
+ ssl_socket.connect_nonblock
40
+ rescue IO::WaitReadable
41
+ if IO.select([ssl_socket], nil, nil, timeout)
42
+ retry
43
+ else
44
+ raise Timeout, "Could not read from #{host}:#{port} in #{timeout} seconds"
45
+ end
46
+ rescue IO::WaitWritable
47
+ if IO.select(nil, [ssl_socket], nil, timeout)
48
+ retry
49
+ else
50
+ raise Timeout, "Could not write to #{host}:#{port} in #{timeout} seconds"
51
+ end
52
+ end
53
+ ssl_socket
54
+ end
55
+
56
+ # Internal: Read up to a maxlen of data from the socket and store it in outbuf
57
+ #
58
+ # maxlen - the maximum number of bytes to read from the socket
59
+ # outbuf - the buffer in which to store the bytes.
60
+ #
61
+ # Returns the bytes read
62
+ def readpartial(maxlen, outbuf = nil)
63
+ return super(maxlen, outbuf)
64
+ rescue OpenSSL::SSL::SSLErrorWaitReadable
65
+ if wait_readable(read_timeout)
66
+ retry
67
+ else
68
+ raise Timeout, "Could not read from #{host}:#{port} in #{read_timeout} seconds"
69
+ end
70
+ end
71
+
72
+ # Internal: Write the given data to the socket
73
+ #
74
+ # buf - the data to write to the socket.
75
+ #
76
+ # Raises an error if it is unable to write the data to the socket within the
77
+ # write_timeout.
78
+ #
79
+ # returns nothing
80
+ def write(buf)
81
+ super(buf)
82
+ rescue OpenSSL::SSL::SSLErrorWaitWritable
83
+ if wait_writable(write_timeout)
84
+ retry
85
+ else
86
+ raise Timeout, "Could not write to #{host}:#{port} in #{write_timeout} seconds"
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,5 +1,6 @@
1
1
  require 'monitor'
2
2
  require 'riemann/client/tcp_socket'
3
+ require 'riemann/client/ssl_socket'
3
4
 
4
5
  module Riemann
5
6
  class Client
@@ -14,7 +15,13 @@ module Riemann
14
15
 
15
16
  # Public: Return a socket factory
16
17
  def self.socket_factory
17
- @socket_factory || proc { |options| TcpSocket.connect(options) }
18
+ @socket_factory || proc { |options|
19
+ if options[:ssl]
20
+ SSLSocket.connect(options)
21
+ else
22
+ TcpSocket.connect(options)
23
+ end
24
+ }
18
25
  end
19
26
 
20
27
  def initialize(options = {})
@@ -107,12 +107,13 @@ module Riemann
107
107
  # Using the options from the initializer, a new ::Socket is created that
108
108
  # is:
109
109
  #
110
- # TCP, IPv4 only, autoclosing on exit, nagle's algorithm is disabled and has
110
+ # TCP, autoclosing on exit, nagle's algorithm is disabled and has
111
111
  # TCP Keepalive options set if keepalive is supported.
112
112
  #
113
- # Returns a new ::Socket instance
114
- def blank_socket
115
- sock = ::Socket.new(::Socket::AF_INET, ::Socket::SOCK_STREAM, 0)
113
+ # Returns a new ::Socket instance for
114
+
115
+ def socket_factory(type)
116
+ sock = ::Socket.new(type, ::Socket::SOCK_STREAM, 0)
116
117
 
117
118
  # close file descriptors if we exec
118
119
  if Fcntl.constants.include?(:F_SETFD) && Fcntl.constants.include?(:FD_CLOEXEC)
@@ -167,13 +168,14 @@ module Riemann
167
168
  # Calculate our timeout deadline
168
169
  deadline = Time.now.to_f + connect_timeout
169
170
 
170
- # Lookup destination address, we only want IPv4 , TCP
171
- addrs = ::Socket.getaddrinfo(host, port, ::Socket::AF_INET, ::Socket::SOCK_STREAM )
171
+ # Lookup destination address, we only want TCP.
172
+ addrs = ::Socket.getaddrinfo(host, port, nil, ::Socket::SOCK_STREAM )
172
173
  errors = []
173
174
  conn_error = lambda { raise errors.first }
174
175
  sock = nil
175
176
 
176
- addrs.find( conn_error ) do |addr|
177
+ # Sort it so we get AF_INET, IPv4
178
+ addrs.sort.find( conn_error ) do |addr|
177
179
  sock = connect_or_error( addr, deadline, errors )
178
180
  end
179
181
  return sock
@@ -210,7 +212,7 @@ module Riemann
210
212
  # connection was possible.
211
213
  def connect_nonblock( addr, timeout )
212
214
  sockaddr = ::Socket.pack_sockaddr_in(addr[1], addr[3])
213
- sock = blank_socket()
215
+ sock = self.socket_factory( addr[4] )
214
216
  sock.connect_nonblock( sockaddr )
215
217
  return sock
216
218
  rescue Errno::EINPROGRESS
data/lib/riemann/event.rb CHANGED
@@ -11,6 +11,7 @@ module Riemann
11
11
  repeated :tags, :string, 7
12
12
  optional :ttl, :float, 8
13
13
  repeated :attributes, Attribute, 9
14
+ optional :time_micros, :int64, 10
14
15
 
15
16
  optional :metric_sint64, :sint64, 13
16
17
  optional :metric_d, :double, 14
@@ -27,6 +28,10 @@ module Riemann
27
28
  set << field
28
29
  end
29
30
 
31
+ def self.now
32
+ (Time.now.to_f * 1_000_000).to_i
33
+ end
34
+
30
35
  # Average a set of states together. Chooses the mean metric, the mode
31
36
  # state, mode service, and the mean time. If init is provided, its values
32
37
  # override (where present) the computed ones.
@@ -51,12 +56,12 @@ module Riemann
51
56
  init.service ||= mode states.map(&:service)
52
57
 
53
58
  # Time
54
- init.time = begin
55
- times = states.map(&:time).compact
59
+ init.time_micros = begin
60
+ times = states.map(&:time_micros).compact
56
61
  (times.inject(:+) / times.size).to_i
57
62
  rescue
58
63
  end
59
- init.time ||= Time.now.to_i
64
+ init.time_micros ||= now
60
65
 
61
66
  init
62
67
  end
@@ -85,12 +90,12 @@ module Riemann
85
90
  init.service ||= mode states.map(&:service)
86
91
 
87
92
  # Time
88
- init.time = begin
89
- times = states.map(&:time).compact
93
+ init.time_micros = begin
94
+ times = states.map(&:time_micros).compact
90
95
  (times.inject(:+) / times.size).to_i
91
96
  rescue
92
97
  end
93
- init.time ||= Time.now.to_i
98
+ init.time_micros ||= now
94
99
 
95
100
  init
96
101
  end
@@ -119,12 +124,12 @@ module Riemann
119
124
  end
120
125
 
121
126
  # Time
122
- init.time = begin
123
- times = states.map(&:time).compact
127
+ init.time_micros = begin
128
+ times = states.map(&:time_micros).compact
124
129
  (times.inject(:+) / times.size).to_i
125
130
  rescue
126
131
  end
127
- init.time ||= Time.now.to_i
132
+ init.time_micros ||= now
128
133
 
129
134
  init
130
135
  end
@@ -186,7 +191,7 @@ module Riemann
186
191
  super()
187
192
  end
188
193
 
189
- @time ||= Time.now.to_i
194
+ @time_micros ||= self.class.now unless @time
190
195
  end
191
196
 
192
197
  def metric
@@ -1,3 +1,3 @@
1
1
  module Riemann
2
- VERSION = '0.2.6'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -18,14 +18,13 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ['lib']
21
- spec.has_rdoc = true
22
21
 
23
- spec.required_ruby_version = '>= 1.8.7'
22
+ spec.required_ruby_version = '>= 2.7.0'
24
23
 
25
24
  spec.add_development_dependency 'bundler', '>= 1.3'
26
25
  spec.add_development_dependency 'bacon'
26
+ spec.add_development_dependency 'timecop'
27
27
 
28
- spec.add_dependency 'beefcake', ['>= 0.3.5','<= 1.0.0 ']
29
- spec.add_dependency 'trollop', '>= 1.16.2'
28
+ spec.add_dependency 'beefcake', ['>= 1.0.0 ']
30
29
  spec.add_dependency 'mtrc', '>= 0.0.4'
31
30
  end
data/spec/client.rb CHANGED
@@ -1,29 +1,47 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # How to run the bacon tests:
4
- # 1. Start Riemann on default location 127.0.0.1:5555
4
+ # 1. Start Riemann using the config from riemann.config
5
5
  # 2. $ bundle exec bacon spec/client.rb
6
6
 
7
7
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'riemann'))
8
8
  require 'riemann/client'
9
9
  require 'bacon'
10
10
  require 'set'
11
+ require 'timecop'
11
12
 
12
13
  Bacon.summary_on_exit
13
14
 
14
15
  include Riemann
15
16
 
16
17
  INACTIVITY_TIME = 5
17
- RIEMANN_IP = ENV["RIEMANN_IP"] || "127.0.0.1"
18
- RIEMANN_PORT = ENV["RIEMANN_PORT"] || 5555
18
+
19
+ def wait_for(&block)
20
+ tries = 0
21
+ while tries < 30
22
+ tries += 1
23
+ begin
24
+ res = block.call
25
+ return res if res
26
+ rescue NoMethodError
27
+ # If a query returns no result (#query retruns nil or #[] returns []),
28
+ # calling #first on it will raise a NoMethodError. We can ignore it for
29
+ # these tests.
30
+ end
31
+ sleep(0.1)
32
+ end
33
+
34
+ raise "wait_for condition never realized"
35
+ end
19
36
 
20
37
  def roundtrip_metric(m)
21
38
  @client_with_transport << {
22
39
  :service => 'metric-test',
23
40
  :metric => m
24
41
  }
25
- @client["service = \"metric-test\" and metric = #{m}"].
26
- first.metric.should.equal m
42
+
43
+ wait_for {@client["service = \"metric-test\" and metric = #{m}"].first }.
44
+ metric.should.equal m
27
45
  end
28
46
 
29
47
  def truthy
@@ -38,7 +56,7 @@ shared "a riemann client" do
38
56
 
39
57
  should 'yield itself to given block' do
40
58
  client = nil
41
- Client.new(:host => RIEMANN_IP, :port => RIEMANN_PORT) do |c|
59
+ Client.new(:host => "localhost", :port => 5555) do |c|
42
60
  client = c
43
61
  end
44
62
  client.should.be.kind_of?(Client)
@@ -48,7 +66,7 @@ shared "a riemann client" do
48
66
  should 'close sockets if given a block that raises' do
49
67
  client = nil
50
68
  begin
51
- Client.new(:host => RIEMANN_IP, :port => RIEMANN_PORT) do |c|
69
+ Client.new(:host => "localhost", :port => 5555) do |c|
52
70
  client = c
53
71
  raise "The Boom"
54
72
  end
@@ -90,7 +108,7 @@ shared "a riemann client" do
90
108
  )
91
109
  event[:sneak] = 'attack'
92
110
  @client_with_transport << event
93
- event2 = @client['service = "custom"'].first
111
+ event2 = wait_for { @client['service = "custom"'].first }
94
112
  event2.service.should.equal 'custom'
95
113
  event2.state.should.equal 'ok'
96
114
  event2[:cats].should.equal 'meow'
@@ -99,27 +117,53 @@ shared "a riemann client" do
99
117
  end
100
118
 
101
119
  should 'send a state with a time' do
102
- t = Time.now.to_i - 10
103
- @client_with_transport << {
104
- :state => 'ok',
105
- :service => 'test',
106
- :time => t
107
- }
108
- @client.query('service = "test"').events.first.time.should.equal t
120
+ Timecop.freeze do
121
+ t = (Time.now - 10).to_i
122
+ @client_with_transport << {
123
+ :state => 'ok',
124
+ :service => 'test',
125
+ :time => t
126
+ }
127
+ wait_for { @client.query('service = "test"').events.first.time == t }
128
+ e = @client.query('service = "test"').events.first
129
+ e.time.should.equal t
130
+ e.time_micros.should.equal t * 1_000_000
131
+ end
132
+ end
133
+
134
+ should 'send a state with a time_micros' do
135
+ Timecop.freeze do
136
+ t = ((Time.now - 10).to_f * 1_000_000).to_i
137
+ @client_with_transport << {
138
+ :state => 'ok',
139
+ :service => 'test',
140
+ :time_micros => t
141
+ }
142
+ wait_for { @client.query('service = "test"').events.first.time_micros == t }
143
+ e = @client.query('service = "test"').events.first
144
+ e.time.should.equal (Time.now - 10).to_i
145
+ e.time_micros.should.equal t
146
+ end
109
147
  end
110
148
 
111
- should 'send a state without time' do
149
+ should 'send a state without time nor time_micros' do
150
+ time_before = (Time.now.to_f * 1_000_000).to_i
112
151
  @client_with_transport << {
113
152
  :state => 'ok',
114
153
  :service => 'timeless test'
115
154
  }
116
- @client.query('service = "timeless test"').events.first.time.should.equal Time.now.to_i
155
+ wait_for { @client.query('service = "timeless test"').events.first.time_micros >= time_before }
156
+ e = @client.query('service = "timeless test"').events.first
157
+ time_after = (Time.now.to_f * 1_000_000).to_i
158
+
159
+ [time_before, e.time_micros, time_after].sort.should.equal([time_before, e.time_micros, time_after])
117
160
  end
118
161
 
119
162
  should "query states" do
120
163
  @client_with_transport << { :state => 'critical', :service => '1' }
121
164
  @client_with_transport << { :state => 'warning', :service => '2' }
122
165
  @client_with_transport << { :state => 'critical', :service => '3' }
166
+ wait_for { @client.query('service = "3"').events.first }
123
167
  @client.query.events.
124
168
  map(&:service).to_set.should.superset ['1', '2', '3'].to_set
125
169
  @client.query('state = "critical" and (service = "1" or service = "2" or service = "3")').events.
@@ -129,7 +173,7 @@ shared "a riemann client" do
129
173
  it '[]' do
130
174
  # @client['state = "critical"'].should == []
131
175
  @client_with_transport << {:state => 'critical'}
132
- @client['state = "critical"'].first.state.should.equal 'critical'
176
+ wait_for { @client['state = "critical"'].first }.state.should.equal 'critical'
133
177
  end
134
178
 
135
179
  should 'query quickly' do
@@ -174,10 +218,62 @@ shared "a riemann client" do
174
218
 
175
219
  end
176
220
 
221
+ describe "Riemann::Client (TLS transport)" do
222
+ before do
223
+ @client = Client.new(:host => "localhost", :port => 5554, :ssl => true, :key_file => '/etc/riemann/riemann_server.pkcs8', :cert_file => '/etc/riemann/riemann_server.crt', :ca_file => '/etc/riemann/riemann_server.crt', :ssl_verify => true)
224
+ @client_with_transport = @client.tcp
225
+ @expected_rate = 100
226
+ end
227
+ behaves_like "a riemann client"
228
+
229
+ should 'send a state' do
230
+ res = @client_with_transport << {
231
+ :state => 'ok',
232
+ :service => 'test',
233
+ :description => 'desc',
234
+ :metric_f => 1.0
235
+ }
236
+
237
+ res.ok.should.be truthy
238
+ wait_for { @client['service = "test"'].first }.state.should.equal 'ok'
239
+ end
240
+
241
+ should 'survive inactivity' do
242
+ @client_with_transport.<<({
243
+ :state => 'warning',
244
+ :service => 'survive TCP inactivity',
245
+ })
246
+ wait_for { @client['service = "survive TCP inactivity"'].first.state == 'warning' }
247
+
248
+ sleep INACTIVITY_TIME
249
+
250
+ @client_with_transport.<<({
251
+ :state => 'ok',
252
+ :service => 'survive TCP inactivity',
253
+ }).ok.should.be truthy
254
+ wait_for { @client['service = "survive TCP inactivity"'].first.state == 'ok' }
255
+ end
256
+
257
+ should 'survive local close' do
258
+ @client_with_transport.<<({
259
+ :state => 'warning',
260
+ :service => 'survive TCP local close',
261
+ }).ok.should.be truthy
262
+ wait_for { @client['service = "survive TCP local close"'].first .state == 'warning' }
263
+
264
+ @client.close
265
+
266
+ @client_with_transport.<<({
267
+ :state => 'ok',
268
+ :service => 'survive TCP local close',
269
+ }).ok.should.be truthy
270
+ wait_for { @client['service = "survive TCP local close"'].first.state == 'ok' }
271
+ end
272
+ end
177
273
 
178
274
  describe "Riemann::Client (TCP transport)" do
179
275
  before do
180
- @client = Client.new(:host => RIEMANN_IP, :port => RIEMANN_PORT)
276
+ @client = Client.new(:host => "localhost", :port => 5555)
181
277
  @client_with_transport = @client.tcp
182
278
  @expected_rate = 100
183
279
  end
@@ -192,7 +288,7 @@ describe "Riemann::Client (TCP transport)" do
192
288
  }
193
289
 
194
290
  res.ok.should.be truthy
195
- @client['service = "test"'].first.state.should.equal 'ok'
291
+ wait_for { @client['service = "test"'].first }.state.should.equal 'ok'
196
292
  end
197
293
 
198
294
  should 'survive inactivity' do
@@ -200,7 +296,7 @@ describe "Riemann::Client (TCP transport)" do
200
296
  :state => 'warning',
201
297
  :service => 'survive TCP inactivity',
202
298
  })
203
- @client['service = "survive TCP inactivity"'].first.state.should.equal 'warning'
299
+ wait_for { @client['service = "survive TCP inactivity"'].first.state == 'warning' }
204
300
 
205
301
  sleep INACTIVITY_TIME
206
302
 
@@ -208,7 +304,7 @@ describe "Riemann::Client (TCP transport)" do
208
304
  :state => 'ok',
209
305
  :service => 'survive TCP inactivity',
210
306
  }).ok.should.be truthy
211
- @client['service = "survive TCP inactivity"'].first.state.should.equal 'ok'
307
+ wait_for { @client['service = "survive TCP inactivity"'].first.state == 'ok' }
212
308
  end
213
309
 
214
310
  should 'survive local close' do
@@ -216,7 +312,7 @@ describe "Riemann::Client (TCP transport)" do
216
312
  :state => 'warning',
217
313
  :service => 'survive TCP local close',
218
314
  }).ok.should.be truthy
219
- @client['service = "survive TCP local close"'].first.state.should.equal 'warning'
315
+ wait_for { @client['service = "survive TCP local close"'].first.state == 'warning' }
220
316
 
221
317
  @client.close
222
318
 
@@ -224,13 +320,13 @@ describe "Riemann::Client (TCP transport)" do
224
320
  :state => 'ok',
225
321
  :service => 'survive TCP local close',
226
322
  }).ok.should.be truthy
227
- @client['service = "survive TCP local close"'].first.state.should.equal 'ok'
323
+ wait_for { @client['service = "survive TCP local close"'].first.state == 'ok' }
228
324
  end
229
325
  end
230
326
 
231
327
  describe "Riemann::Client (UDP transport)" do
232
328
  before do
233
- @client = Client.new(:host => RIEMANN_IP, :port => RIEMANN_PORT)
329
+ @client = Client.new(:host => "localhost", :port => 5555)
234
330
  @client_with_transport = @client.udp
235
331
  @expected_rate = 1000
236
332
  end
@@ -245,39 +341,39 @@ describe "Riemann::Client (UDP transport)" do
245
341
  }
246
342
 
247
343
  res.should.be.nil
248
- @client['service = "test"'].first.state.should.equal 'ok'
344
+ wait_for { @client['service = "test"'].first }.state.should.equal 'ok'
249
345
  end
250
346
 
251
347
  should 'survive inactivity' do
252
348
  @client_with_transport.<<({
253
349
  :state => 'warning',
254
350
  :service => 'survive UDP inactivity',
255
- })
256
- @client['service = "survive UDP inactivity"'].first.state.should.equal 'warning'
351
+ }).should.be.nil
352
+ wait_for { @client['service = "survive UDP inactivity"'].first.state == 'warning' }
257
353
 
258
354
  sleep INACTIVITY_TIME
259
355
 
260
356
  @client_with_transport.<<({
261
357
  :state => 'ok',
262
358
  :service => 'survive UDP inactivity',
263
- })
264
- @client['service = "survive UDP inactivity"'].first.state.should.equal 'ok'
359
+ }).should.be.nil
360
+ wait_for { @client['service = "survive UDP inactivity"'].first.state == 'ok' }
265
361
  end
266
362
 
267
363
  should 'survive local close' do
268
364
  @client_with_transport.<<({
269
365
  :state => 'warning',
270
366
  :service => 'survive UDP local close',
271
- })
272
- @client['service = "survive UDP local close"'].first.state.should.equal 'warning'
367
+ }).should.be.nil
368
+ wait_for { @client['service = "survive UDP local close"'].first.state == 'warning' }
273
369
 
274
370
  @client.close
275
371
 
276
372
  @client_with_transport.<<({
277
373
  :state => 'ok',
278
374
  :service => 'survive UDP local close',
279
- })
280
- @client['service = "survive UDP local close"'].first.state.should.equal 'ok'
375
+ }).should.be.nil
376
+ wait_for { @client['service = "survive UDP local close"'].first.state == 'ok' }
281
377
  end
282
378
 
283
379
  should "raise Riemann::Client::Unsupported exception on query" do
@@ -0,0 +1,30 @@
1
+ ; -*- mode: clojure; -*-
2
+ ; vim: filetype=clojure
3
+
4
+ (logging/init {:file "/var/log/riemann/riemann.log"})
5
+
6
+ ; Listen on the local interface over TCP (5555), UDP (5555), websockets
7
+ ; (5556) and TLS (5554)
8
+ (let [host "127.0.0.1"]
9
+ (tcp-server {:host host})
10
+ (udp-server {:host host})
11
+ (ws-server {:host host})
12
+ (tcp-server {:host host :port 5554 :tls? true :key "/etc/riemann/riemann_server.pkcs8" :cert "/etc/riemann/riemann_server.crt" :ca-cert "/etc/riemann/riemann_server.crt"}))
13
+
14
+ ; Expire old events from the index every 5 seconds.
15
+ (periodically-expire 5)
16
+
17
+ (let [index (index)]
18
+ ; Inbound events will be passed to these streams:
19
+ (streams
20
+ (default :ttl 60
21
+ ; Index all events immediately.
22
+ ;index
23
+
24
+ ; Index all events after a delay.
25
+ (batch 1000 1/10
26
+ (sflatten index))
27
+
28
+ ; Log expired events.
29
+ (expired
30
+ (fn [event] (info "expired" event))))))
metadata CHANGED
@@ -1,100 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riemann-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Kyle Kingsbury
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-11-18 00:00:00.000000000 Z
11
+ date: 2022-06-16 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.3'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.3'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: bacon
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
- name: beefcake
42
+ name: timecop
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: 0.3.5
54
- - - <=
45
+ - - ">="
55
46
  - !ruby/object:Gem::Version
56
- version: 1.0.0
57
- type: :runtime
47
+ version: '0'
48
+ type: :development
58
49
  prerelease: false
59
50
  version_requirements: !ruby/object:Gem::Requirement
60
- none: false
61
51
  requirements:
62
- - - ! '>='
52
+ - - ">="
63
53
  - !ruby/object:Gem::Version
64
- version: 0.3.5
65
- - - <=
66
- - !ruby/object:Gem::Version
67
- version: 1.0.0
54
+ version: '0'
68
55
  - !ruby/object:Gem::Dependency
69
- name: trollop
56
+ name: beefcake
70
57
  requirement: !ruby/object:Gem::Requirement
71
- none: false
72
58
  requirements:
73
- - - ! '>='
59
+ - - ">="
74
60
  - !ruby/object:Gem::Version
75
- version: 1.16.2
61
+ version: 1.0.0
76
62
  type: :runtime
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
- none: false
80
65
  requirements:
81
- - - ! '>='
66
+ - - ">="
82
67
  - !ruby/object:Gem::Version
83
- version: 1.16.2
68
+ version: 1.0.0
84
69
  - !ruby/object:Gem::Dependency
85
70
  name: mtrc
86
71
  requirement: !ruby/object:Gem::Requirement
87
- none: false
88
72
  requirements:
89
- - - ! '>='
73
+ - - ">="
90
74
  - !ruby/object:Gem::Version
91
75
  version: 0.0.4
92
76
  type: :runtime
93
77
  prerelease: false
94
78
  version_requirements: !ruby/object:Gem::Requirement
95
- none: false
96
79
  requirements:
97
- - - ! '>='
80
+ - - ">="
98
81
  - !ruby/object:Gem::Version
99
82
  version: 0.0.4
100
83
  description: Client for the distributed event system Riemann.
@@ -103,15 +86,18 @@ executables: []
103
86
  extensions: []
104
87
  extra_rdoc_files: []
105
88
  files:
106
- - .gitignore
89
+ - ".github/workflows/ci.yml"
90
+ - ".gitignore"
91
+ - CHANGELOG.md
107
92
  - Gemfile
108
93
  - LICENSE
109
94
  - README.markdown
110
- - Rakefile.rb
95
+ - Rakefile
111
96
  - lib/riemann.rb
112
97
  - lib/riemann/attribute.rb
113
98
  - lib/riemann/auto_state.rb
114
99
  - lib/riemann/client.rb
100
+ - lib/riemann/client/ssl_socket.rb
115
101
  - lib/riemann/client/tcp.rb
116
102
  - lib/riemann/client/tcp_socket.rb
117
103
  - lib/riemann/client/udp.rb
@@ -123,30 +109,30 @@ files:
123
109
  - lib/riemann/version.rb
124
110
  - riemann-client.gemspec
125
111
  - spec/client.rb
112
+ - spec/riemann.config
126
113
  homepage: https://github.com/aphyr/riemann-ruby-client
127
114
  licenses:
128
115
  - MIT
116
+ metadata: {}
129
117
  post_install_message:
130
118
  rdoc_options: []
131
119
  require_paths:
132
120
  - lib
133
121
  required_ruby_version: !ruby/object:Gem::Requirement
134
- none: false
135
122
  requirements:
136
- - - ! '>='
123
+ - - ">="
137
124
  - !ruby/object:Gem::Version
138
- version: 1.8.7
125
+ version: 2.7.0
139
126
  required_rubygems_version: !ruby/object:Gem::Requirement
140
- none: false
141
127
  requirements:
142
- - - ! '>='
128
+ - - ">="
143
129
  - !ruby/object:Gem::Version
144
130
  version: '0'
145
131
  requirements: []
146
- rubyforge_project:
147
- rubygems_version: 1.8.25
132
+ rubygems_version: 3.2.5
148
133
  signing_key:
149
- specification_version: 3
134
+ specification_version: 4
150
135
  summary: Client for the distributed event system Riemann.
151
136
  test_files:
152
137
  - spec/client.rb
138
+ - spec/riemann.config
data/Rakefile.rb DELETED
@@ -1,46 +0,0 @@
1
- $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
-
3
- require 'rubygems'
4
- require 'rubygems/package_task'
5
- require 'rdoc/task'
6
- require 'riemann/version'
7
- require 'find'
8
-
9
- # Don't include resource forks in tarballs on Mac OS X.
10
- ENV['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
11
- ENV['COPYFILE_DISABLE'] = 'true'
12
-
13
- # Gemspec
14
- gemspec = Gem::Specification.new do |s|
15
- s.rubyforge_project = 'riemann-client'
16
-
17
- s.name = 'riemann-client'
18
- s.version = Riemann::VERSION
19
- s.author = 'Kyle Kingsbury'
20
- s.email = 'aphyr@aphyr.com'
21
- s.homepage = 'https://github.com/aphyr/riemann-ruby-client'
22
- s.platform = Gem::Platform::RUBY
23
- s.summary = 'Client for the distributed event system Riemann.'
24
-
25
- s.add_dependency 'beefcake', '>= 0.3.5'
26
- s.add_dependency 'trollop', '>= 1.16.2'
27
- s.add_dependency 'mtrc', '>= 0.0.4'
28
-
29
- s.files = FileList['{lib}/**/*', 'LICENSE', 'README.markdown'].to_a
30
- s.executables = []
31
- s.require_path = 'lib'
32
- s.has_rdoc = true
33
-
34
- s.required_ruby_version = '>= 1.8.7'
35
- end
36
-
37
- Gem::PackageTask.new gemspec do |p|
38
- end
39
-
40
- RDoc::Task.new do |rd|
41
- rd.main = 'Riemann'
42
- rd.title = 'Riemann'
43
- rd.rdoc_dir = 'doc'
44
-
45
- rd.rdoc_files.include('lib/**/*.rb')
46
- end