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 +7 -0
- data/.github/workflows/ci.yml +45 -0
- data/.gitignore +4 -0
- data/CHANGELOG.md +76 -0
- data/Gemfile +2 -0
- data/Rakefile +12 -0
- data/lib/riemann/client/ssl_socket.rb +91 -0
- data/lib/riemann/client/tcp.rb +8 -1
- data/lib/riemann/client/tcp_socket.rb +10 -8
- data/lib/riemann/event.rb +15 -10
- data/lib/riemann/version.rb +1 -1
- data/riemann-client.gemspec +3 -4
- data/spec/client.rb +130 -34
- data/spec/riemann.config +30 -0
- metadata +32 -46
- data/Rakefile.rb +0 -46
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
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
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
|
data/lib/riemann/client/tcp.rb
CHANGED
@@ -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|
|
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,
|
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
|
-
|
115
|
-
|
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
|
171
|
-
addrs = ::Socket.getaddrinfo(host, port,
|
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
|
-
|
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 =
|
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.
|
55
|
-
times = states.map(&:
|
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.
|
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.
|
89
|
-
times = states.map(&:
|
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.
|
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.
|
123
|
-
times = states.map(&:
|
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.
|
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
|
-
@
|
194
|
+
@time_micros ||= self.class.now unless @time
|
190
195
|
end
|
191
196
|
|
192
197
|
def metric
|
data/lib/riemann/version.rb
CHANGED
data/riemann-client.gemspec
CHANGED
@@ -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 = '>=
|
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', ['>=
|
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
|
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
|
-
|
18
|
-
|
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
|
-
|
26
|
-
|
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 =>
|
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 =>
|
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
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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.
|
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 =>
|
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
|
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
|
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
|
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
|
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 =>
|
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
|
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
|
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
|
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
|
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
|
data/spec/riemann.config
ADDED
@@ -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.
|
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:
|
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:
|
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:
|
57
|
-
type: :
|
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
|
65
|
-
- - <=
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: 1.0.0
|
54
|
+
version: '0'
|
68
55
|
- !ruby/object:Gem::Dependency
|
69
|
-
name:
|
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.
|
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.
|
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
|
-
- .
|
89
|
+
- ".github/workflows/ci.yml"
|
90
|
+
- ".gitignore"
|
91
|
+
- CHANGELOG.md
|
107
92
|
- Gemfile
|
108
93
|
- LICENSE
|
109
94
|
- README.markdown
|
110
|
-
- Rakefile
|
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:
|
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
|
-
|
147
|
-
rubygems_version: 1.8.25
|
132
|
+
rubygems_version: 3.2.5
|
148
133
|
signing_key:
|
149
|
-
specification_version:
|
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
|