efigence-influxdb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rubocop.yml +41 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +11 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +362 -0
  8. data/Rakefile +22 -0
  9. data/efigence-influxdb.gemspec +28 -0
  10. data/lib/influxdb.rb +21 -0
  11. data/lib/influxdb/client.rb +77 -0
  12. data/lib/influxdb/client/http.rb +98 -0
  13. data/lib/influxdb/config.rb +60 -0
  14. data/lib/influxdb/errors.rb +40 -0
  15. data/lib/influxdb/logging.rb +22 -0
  16. data/lib/influxdb/max_queue.rb +18 -0
  17. data/lib/influxdb/point_value.rb +31 -0
  18. data/lib/influxdb/query/cluster.rb +17 -0
  19. data/lib/influxdb/query/continuous_query.rb +36 -0
  20. data/lib/influxdb/query/core.rb +109 -0
  21. data/lib/influxdb/query/database.rb +21 -0
  22. data/lib/influxdb/query/series.rb +13 -0
  23. data/lib/influxdb/query/shard.rb +14 -0
  24. data/lib/influxdb/query/shard_space.rb +60 -0
  25. data/lib/influxdb/query/user.rb +38 -0
  26. data/lib/influxdb/version.rb +3 -0
  27. data/lib/influxdb/writer/async.rb +115 -0
  28. data/lib/influxdb/writer/udp.rb +21 -0
  29. data/spec/influxdb/cases/async_client_spec.rb +33 -0
  30. data/spec/influxdb/cases/query_cluster_spec.rb +65 -0
  31. data/spec/influxdb/cases/query_database_spec.rb +58 -0
  32. data/spec/influxdb/cases/query_series_spec.rb +50 -0
  33. data/spec/influxdb/cases/query_shard_spec.rb +43 -0
  34. data/spec/influxdb/cases/query_user_spec.rb +127 -0
  35. data/spec/influxdb/cases/querying_spec.rb +159 -0
  36. data/spec/influxdb/cases/retry_requests_spec.rb +97 -0
  37. data/spec/influxdb/cases/udp_client_spec.rb +21 -0
  38. data/spec/influxdb/cases/write_points_spec.rb +141 -0
  39. data/spec/influxdb/client_spec.rb +58 -0
  40. data/spec/influxdb/config_spec.rb +118 -0
  41. data/spec/influxdb/logging_spec.rb +48 -0
  42. data/spec/influxdb/max_queue_spec.rb +29 -0
  43. data/spec/influxdb/point_value_spec.rb +66 -0
  44. data/spec/influxdb/worker_spec.rb +23 -0
  45. data/spec/spec_helper.rb +8 -0
  46. metadata +192 -0
@@ -0,0 +1,97 @@
1
+ require "spec_helper"
2
+ require "json"
3
+
4
+ describe InfluxDB::Client do
5
+ let(:client) do
6
+ described_class.new(
7
+ "database",
8
+ {
9
+ host: "influxdb.test",
10
+ port: 9999,
11
+ username: "username",
12
+ password: "password",
13
+ time_precision: "s"
14
+ }.merge(args)
15
+ )
16
+ end
17
+
18
+ let(:args) { {} }
19
+
20
+ let(:database) { client.config.database }
21
+
22
+ describe "retrying requests" do
23
+
24
+ let(:series) { "cpu" }
25
+ let(:data) do
26
+ { tags: { region: 'us', host: 'server_1' },
27
+ values: { temp: 88, value: 54 } }
28
+ end
29
+ let(:body) do
30
+ InfluxDB::PointValue.new(data.merge(series: series)).dump
31
+ end
32
+
33
+ subject { client.write_point(series, data) }
34
+
35
+ before do
36
+ allow(client).to receive(:log)
37
+ stub_request(:post, "http://influxdb.test:9999/write").with(
38
+ :query => {:u => "username", :p => "password", :precision => 's', :db => database},
39
+ :headers => {"Content-Type" => "application/octet-stream"},
40
+ :body => body
41
+ ).to_raise(Timeout::Error)
42
+ end
43
+
44
+ it "raises when stopped" do
45
+ client.stop!
46
+ expect(client).not_to receive(:sleep)
47
+ expect { subject }.to raise_error(Timeout::Error)
48
+ end
49
+
50
+ context "when retry is 0" do
51
+ let(:args) { { retry: 0 } }
52
+ it "raise error directly" do
53
+ expect(client).not_to receive(:sleep)
54
+ expect { subject }.to raise_error(Timeout::Error)
55
+ end
56
+ end
57
+
58
+ context "when retry is 'n'" do
59
+ let(:args) { { retry: 3 } }
60
+
61
+ it "raise error after 'n' attemps" do
62
+ expect(client).to receive(:sleep).exactly(3).times
63
+ expect { subject }.to raise_error(Timeout::Error)
64
+ end
65
+ end
66
+
67
+ context "when retry is -1" do
68
+ let(:args) { { retry: -1 } }
69
+ before do
70
+ stub_request(:post, "http://influxdb.test:9999/write").with(
71
+ :query => {:u => "username", :p => "password", :precision => 's', :db => database},
72
+ :headers => {"Content-Type" => "application/octet-stream"},
73
+ :body => body
74
+ ).to_raise(Timeout::Error).then
75
+ .to_raise(Timeout::Error).then
76
+ .to_raise(Timeout::Error).then
77
+ .to_raise(Timeout::Error).then
78
+ .to_return(:status => 200)
79
+ end
80
+
81
+ it "keep trying until get the connection" do
82
+ expect(client).to receive(:sleep).exactly(4).times
83
+ expect { subject }.to_not raise_error
84
+ end
85
+ end
86
+
87
+ it "raise an exception if the server didn't return 200" do
88
+ stub_request(:post, "http://influxdb.test:9999/write").with(
89
+ :query => {:u => "username", :p => "password", :precision => 's', :db => database},
90
+ :headers => {"Content-Type" => "application/octet-stream"},
91
+ :body => body
92
+ ).to_return(:status => 401)
93
+
94
+ expect { client.write_point(series, data) }.to raise_error
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe InfluxDB::Client do
4
+ let(:client) { described_class.new(udp: { host: "localhost", port: 44_444 }) }
5
+
6
+ specify { expect(client.writer).to be_a(InfluxDB::Writer::UDP) }
7
+
8
+ describe "#write" do
9
+ let(:message) { "responses,region=eu value=5" }
10
+
11
+ it "sends a UPD packet" do
12
+ s = UDPSocket.new
13
+ s.bind("localhost", 44_444)
14
+
15
+ client.write_point("responses", values: {value: 5}, tags: {region: 'eu'})
16
+
17
+ rec_message = s.recvfrom(30).first
18
+ expect(rec_message).to eq message
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,141 @@
1
+ require "spec_helper"
2
+ require "json"
3
+
4
+ describe InfluxDB::Client do
5
+ let(:subject) do
6
+ described_class.new(
7
+ "database",
8
+ {
9
+ host: "influxdb.test",
10
+ port: 9999,
11
+ username: "username",
12
+ password: "password",
13
+ time_precision: "s"
14
+ }.merge(args)
15
+ )
16
+ end
17
+
18
+ let(:args) { {} }
19
+
20
+ let(:database) { subject.config.database }
21
+
22
+ describe "#write_point" do
23
+ let(:series) { "cpu" }
24
+ let(:data) do
25
+ { tags: { region: 'us', host: 'server_1' },
26
+ values: { temp: 88, value: 54 } }
27
+ end
28
+ let(:body) do
29
+ InfluxDB::PointValue.new(data.merge(series: series)).dump
30
+ end
31
+
32
+ before do
33
+ stub_request(:post, "http://influxdb.test:9999/write").with(
34
+ :query => {:u => "username", :p => "password", :precision => 's', :db => database},
35
+ :headers => {"Content-Type" => "application/octet-stream"},
36
+ :body => body
37
+ )
38
+ end
39
+
40
+ it "should POST to add single point" do
41
+ expect(subject.write_point(series, data)).to be_a(Net::HTTPOK)
42
+ end
43
+ end
44
+
45
+ describe "#write_points" do
46
+
47
+ context "with multiple series" do
48
+ let(:data) do
49
+ [{
50
+ series: 'cpu',
51
+ tags: { region: 'us', host: 'server_1' },
52
+ values: { temp: 88, value: 54 }
53
+ },
54
+ {
55
+ series: 'gpu',
56
+ tags: { region: 'uk', host: 'server_5'},
57
+ values: { value: 0.5435345}
58
+ }]
59
+ end
60
+ let(:body) do
61
+ data.map do |point|
62
+ InfluxDB::PointValue.new(point).dump
63
+ end.join("\n")
64
+ end
65
+
66
+ before do
67
+ stub_request(:post, "http://influxdb.test:9999/write").with(
68
+ :query => {:u => "username", :p => "password", :precision => 's', :db => database},
69
+ :headers => {"Content-Type" => "application/octet-stream"},
70
+ :body => body
71
+ )
72
+ end
73
+
74
+ it "should POST multiple points" do
75
+ expect(subject.write_points(data)).to be_a(Net::HTTPOK)
76
+ end
77
+ end
78
+
79
+ context "with no tags" do
80
+ let(:data) do
81
+ [{
82
+ series: 'cpu',
83
+ values: { temp: 88, value: 54 }
84
+ },
85
+ {
86
+ series: 'gpu',
87
+ values: { value: 0.5435345 }
88
+ }]
89
+ end
90
+ let(:body) do
91
+ data.map do |point|
92
+ InfluxDB::PointValue.new(point).dump
93
+ end.join("\n")
94
+ end
95
+
96
+ before do
97
+ stub_request(:post, "http://influxdb.test:9999/write").with(
98
+ :query => {:u => "username", :p => "password", :precision => 's', :db => database},
99
+ :headers => {"Content-Type" => "application/octet-stream"},
100
+ :body => body
101
+ )
102
+ end
103
+
104
+ it "should POST multiple points" do
105
+ expect(subject.write_points(data)).to be_a(Net::HTTPOK)
106
+ end
107
+ end
108
+
109
+ context "with time precision set to milisceconds" do
110
+ let(:data) do
111
+ [{
112
+ series: 'cpu',
113
+ values: { temp: 88, value: 54 },
114
+ timestamp: (Time.now.to_f * 1000).to_i
115
+ },
116
+ {
117
+ series: 'gpu',
118
+ values: { value: 0.5435345 },
119
+ timestamp: (Time.now.to_f * 1000).to_i
120
+ }]
121
+ end
122
+
123
+ let(:body) do
124
+ data.map do |point|
125
+ InfluxDB::PointValue.new(point).dump
126
+ end.join("\n")
127
+ end
128
+
129
+ before do
130
+ stub_request(:post, "http://influxdb.test:9999/write").with(
131
+ :query => {:u => "username", :p => "password", :precision => 'm', :db => database},
132
+ :headers => {"Content-Type" => "application/octet-stream"},
133
+ :body => body
134
+ )
135
+ end
136
+ it "should POST multiple points" do
137
+ expect(subject.write_points(data, 'm')).to be_a(Net::HTTPOK)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,58 @@
1
+ require "spec_helper"
2
+ require "json"
3
+
4
+ describe InfluxDB::Client do
5
+ let(:subject) do
6
+ described_class.new(
7
+ "database",
8
+ {
9
+ host: "influxdb.test",
10
+ port: 9999,
11
+ username: "username",
12
+ password: "password",
13
+ time_precision: "s"
14
+ }.merge(args)
15
+ )
16
+ end
17
+
18
+ let(:args) { {} }
19
+
20
+ specify { is_expected.not_to be_stopped }
21
+
22
+ context "with basic auth" do
23
+ let(:args) { { auth_method: 'basic_auth' } }
24
+
25
+ let(:stub_url) { "http://username:password@influxdb.test:9999/" }
26
+ let(:url) { subject.send(:full_url, '/') }
27
+
28
+ it "GET" do
29
+ stub_request(:get, stub_url).to_return(body: '[]')
30
+ expect(subject.get(url, parse: true)).to eq []
31
+ end
32
+
33
+ it "POST" do
34
+ stub_request(:post, stub_url)
35
+ expect(subject.post(url, {})).to be_a(Net::HTTPOK)
36
+ end
37
+ end
38
+
39
+ describe "#full_url" do
40
+ it "returns String" do
41
+ expect(subject.send(:full_url, "/unknown")).to be_a String
42
+ end
43
+
44
+ it "escapes params" do
45
+ url = subject.send(:full_url, "/unknown", value: ' !@#$%^&*()/\\_+-=?|`~')
46
+ expect(url).to include("value=+%21%40%23%24%25%5E%26%2A%28%29%2F%5C_%2B-%3D%3F%7C%60%7E")
47
+ end
48
+ end
49
+
50
+ describe "GET #ping" do
51
+ it "returns OK" do
52
+ stub_request(:get, "http://influxdb.test:9999/ping")
53
+ .to_return(status: 204)
54
+
55
+ expect(subject.ping).to be_a(Net::HTTPNoContent)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe InfluxDB::Config do
4
+ let(:conf) do
5
+ InfluxDB::Client.new(*args).config
6
+ end
7
+
8
+ let(:args) { {} }
9
+
10
+ context "with no parameters specified" do
11
+ specify { expect(conf.database).to be_nil }
12
+ specify { expect(conf.hosts).to eq ["localhost"] }
13
+ specify { expect(conf.port).to eq 8086 }
14
+ specify { expect(conf.username).to eq "root" }
15
+ specify { expect(conf.password).to eq "root" }
16
+ specify { expect(conf.use_ssl).to be_falsey }
17
+ specify { expect(conf.time_precision).to eq "s" }
18
+ specify { expect(conf.auth_method).to eq "params" }
19
+ specify { expect(conf.denormalize).to be_truthy }
20
+ specify { expect(conf).not_to be_udp }
21
+ specify { expect(conf).not_to be_async }
22
+ end
23
+
24
+ context "with no database specified" do
25
+ let(:args) do
26
+ [{
27
+ host: "host",
28
+ port: "port",
29
+ username: "username",
30
+ password: "password",
31
+ time_precision: "m"
32
+ }]
33
+ end
34
+
35
+ specify { expect(conf.database).to be_nil }
36
+ specify { expect(conf.hosts).to eq ["host"] }
37
+ specify { expect(conf.port).to eq "port" }
38
+ specify { expect(conf.username).to eq "username" }
39
+ specify { expect(conf.password).to eq "password" }
40
+ specify { expect(conf.time_precision).to eq "m" }
41
+ end
42
+
43
+ context "with both a database and options specified" do
44
+ let(:args) do
45
+ [
46
+ "database",
47
+ host: "host",
48
+ port: "port",
49
+ username: "username",
50
+ password: "password",
51
+ time_precision: "m"
52
+ ]
53
+ end
54
+
55
+ specify { expect(conf.database).to eq "database" }
56
+ specify { expect(conf.hosts).to eq ["host"] }
57
+ specify { expect(conf.port).to eq "port" }
58
+ specify { expect(conf.username).to eq "username" }
59
+ specify { expect(conf.password).to eq "password" }
60
+ specify { expect(conf.time_precision).to eq "m" }
61
+ end
62
+
63
+ context "with ssl option specified" do
64
+ let(:args) { [{ use_ssl: true }] }
65
+
66
+ specify { expect(conf.database).to be_nil }
67
+ specify { expect(conf.hosts).to eq ["localhost"] }
68
+ specify { expect(conf.port).to eq 8086 }
69
+ specify { expect(conf.username).to eq "root" }
70
+ specify { expect(conf.password).to eq "root" }
71
+ specify { expect(conf.use_ssl).to be_truthy }
72
+ end
73
+
74
+ context "with multiple hosts specified" do
75
+ let(:args) { [{ hosts: ["1.1.1.1", "2.2.2.2"] }] }
76
+
77
+ specify { expect(conf.database).to be_nil }
78
+ specify { expect(conf.port).to eq 8086 }
79
+ specify { expect(conf.username).to eq "root" }
80
+ specify { expect(conf.password).to eq "root" }
81
+ specify { expect(conf.hosts).to eq ["1.1.1.1", "2.2.2.2"] }
82
+ end
83
+
84
+ context "with auth_method basic auth specified" do
85
+ let(:args) { [{ auth_method: 'basic_auth' }] }
86
+
87
+ specify { expect(conf.database).to be_nil }
88
+ specify { expect(conf.hosts).to eq ["localhost"] }
89
+ specify { expect(conf.port).to eq 8086 }
90
+ specify { expect(conf.username).to eq "root" }
91
+ specify { expect(conf.password).to eq "root" }
92
+ specify { expect(conf.auth_method).to eq "basic_auth" }
93
+ end
94
+
95
+ context "with udp specified with params" do
96
+ let(:args) { [{ udp: { host: 'localhost', port: 4444 } }] }
97
+
98
+ specify { expect(conf).to be_udp }
99
+ end
100
+
101
+ context "with udp specified as true" do
102
+ let(:args) { [{ udp: true }] }
103
+
104
+ specify { expect(conf).to be_udp }
105
+ end
106
+
107
+ context "with async specified with params" do
108
+ let(:args) { [{ async: { max_queue: 20_000 } }] }
109
+
110
+ specify { expect(conf).to be_async }
111
+ end
112
+
113
+ context "with async specified as true" do
114
+ let(:args) { [{ async: true }] }
115
+
116
+ specify { expect(conf).to be_async }
117
+ end
118
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ require 'logger'
3
+
4
+ describe InfluxDB::Logging do
5
+ class LoggerTest # :nodoc:
6
+ include InfluxDB::Logging
7
+
8
+ def write_to_log(level, message)
9
+ log(level, message)
10
+ end
11
+ end
12
+
13
+ before { @old_logger = InfluxDB::Logging.logger }
14
+ after { InfluxDB::Logging.logger = @old_logger }
15
+
16
+ it "has a default logger" do
17
+ expect(InfluxDB::Logging.logger).to be_a(Logger)
18
+ end
19
+
20
+ it "allows setting of a logger" do
21
+ new_logger = Logger.new(STDOUT)
22
+ InfluxDB::Logging.logger = new_logger
23
+ expect(InfluxDB::Logging.logger).to eq(new_logger)
24
+ end
25
+
26
+ it "allows disabling of a logger" do
27
+ InfluxDB::Logging.logger = false
28
+ expect(InfluxDB::Logging.logger).to eql false
29
+ end
30
+
31
+ context "when logging is disabled" do
32
+ subject { LoggerTest.new }
33
+ it "does not log" do
34
+ InfluxDB::Logging.logger = false
35
+ expect(InfluxDB::Logging.logger).not_to receive(:debug)
36
+ subject.write_to_log(:debug, 'test')
37
+ end
38
+ end
39
+
40
+ context "when included in classes" do
41
+ subject { LoggerTest.new }
42
+
43
+ it "logs" do
44
+ expect(InfluxDB::Logging.logger).to receive(:debug).with(an_instance_of(String)).once
45
+ subject.write_to_log(:debug, 'test')
46
+ end
47
+ end
48
+ end