riemann-client 0.2.6 → 1.0.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 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