influxdb 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 09adde8da537fe6ffd14bae482aa630646f5da5c
4
- data.tar.gz: 856b57d58d9958bf159c1a1b8b324aae9289f4bb
5
- SHA512:
6
- metadata.gz: e5756f9e16da70784f771e807c806fdf4ac4cf4e1e46d55132058b3c6149f8b83cfc7ad6744e0fe4df36a56ca8917d52e7c5033a8f2c46014170d3285fa107d3
7
- data.tar.gz: 814e95e5e0c861a64613a2b65f9eac3229215adacee80e702587f8c010a857b5a7e66bd39448f8a782c458c40b11b375e6434cefa769e1ef656dc514fa5a5e49
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MTM1OTVmZjljMTBkM2NjMjM3YTg2MTA5Yjk0MDRlZTdhNzNiODU4OQ==
5
+ data.tar.gz: !binary |-
6
+ ZDJlMGNhZDFhODg2NzEyZmFhODk5MTk4YjIxMzZjMjU3MTIwMzY0OA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YjlhYmZmMTk0MTEwYzc4MjVmNjJiN2E4MjE0OWI5YjU2ZGFlMDc0YTY3ZDBm
10
+ YjJkNWM3OGRiODU5NzMxMTdmYmJiMmZjZTdlOTIyNzA3OWZiZWJmMjNjZDU2
11
+ ZDVjYzNmOWUxOWMyNDcyZjZhMjIzMDVmZjY4MTFjNDkwZjIxM2M=
12
+ data.tar.gz: !binary |-
13
+ Njc1OTllNjhmYmQwYjM3ZGU0NjliZmRhZjJiMGZiZGExZmYzMzc0NWY0Zjcx
14
+ Yjc3Y2MyZjRjZDQxOGE5YmE0YmRjZWY3NzBlMmQ0NzJkMWFlZTY4M2I5NGZk
15
+ MDkzY2Y1OGRkYjBjNjkxYjljNmUyODUxNWMyNDhkODcxZTdhNjM=
data/README.md CHANGED
@@ -76,6 +76,52 @@ loop do
76
76
  end
77
77
  ```
78
78
 
79
+ Write data with time precision:
80
+
81
+ Time precision can be set in 2 ways, either in the client initialization
82
+
83
+ ``` ruby
84
+ require 'influxdb'
85
+
86
+ username = 'foo'
87
+ password = 'bar'
88
+ database = 'site_development'
89
+ name = 'foobar'
90
+ time_precision = 's'
91
+
92
+ influxdb = InfluxDB::Client.new database, :username => username,
93
+ :password => password,
94
+ :time_precision => time_precision
95
+
96
+ data = {
97
+ :value => 0
98
+ :time => Time.now.to_i
99
+ }
100
+
101
+ influxdb.write_point(name, data)
102
+ ```
103
+ or in the write call
104
+
105
+ ``` ruby
106
+ require 'influxdb'
107
+
108
+ username = 'foo'
109
+ password = 'bar'
110
+ database = 'site_development'
111
+ name = 'foobar'
112
+ time_precision = 's'
113
+
114
+ influxdb = InfluxDB::Client.new database, :username => username, :password => password
115
+
116
+ data = {
117
+ :value => 0
118
+ :time => Time.now.to_i
119
+ }
120
+
121
+ influxdb.write_point(name, data, false, time_precision)
122
+ ```
123
+
124
+
79
125
  List cluster admins:
80
126
 
81
127
  ``` ruby
data/lib/influxdb.rb CHANGED
@@ -5,3 +5,4 @@ require "influxdb/logger"
5
5
  require "influxdb/max_queue"
6
6
  require "influxdb/worker"
7
7
  require "influxdb/client"
8
+ require "influxdb/point_value"
@@ -5,7 +5,7 @@ require 'json'
5
5
 
6
6
  module InfluxDB
7
7
  class Client
8
- attr_accessor :host, :port, :username, :password, :database
8
+ attr_accessor :host, :port, :username, :password, :database, :time_precision
9
9
  attr_accessor :queue, :worker
10
10
 
11
11
  include InfluxDB::Logger
@@ -26,7 +26,7 @@ module InfluxDB
26
26
  #
27
27
  # === Valid options in hash
28
28
  #
29
- # +:hostname+:: the hostname to connect to
29
+ # +:host+:: the hostname to connect to
30
30
  # +:port+:: the port to connect to
31
31
  # +:username+:: the username to use when executing commands
32
32
  # +:password+:: the password associated with the username
@@ -40,11 +40,14 @@ module InfluxDB
40
40
  @password = opts[:password] || "root"
41
41
  @http = Net::HTTP.new(@host, @port)
42
42
  @http.use_ssl = opts[:use_ssl]
43
+ @time_precision = opts[:time_precision] || "m"
43
44
  end
44
45
 
45
- def create_database(name)
46
+ ## allow options, e.g. influxdb.create_database('foo', replicationFactor: 3)
47
+ def create_database(name, options = {})
46
48
  url = full_url("db")
47
- data = JSON.generate({:name => name})
49
+ options[:name] = name
50
+ data = JSON.generate(options)
48
51
  post(url, data)
49
52
  end
50
53
 
@@ -100,27 +103,27 @@ module InfluxDB
100
103
  update_database_user(database, username, :admin => admin)
101
104
  end
102
105
 
103
- def write_point(name, data, async=false)
106
+ def write_point(name, data, async=false, time_precision=@time_precision)
104
107
  data = data.is_a?(Array) ? data : [data]
105
108
  columns = data.reduce(:merge).keys.sort {|a,b| a.to_s <=> b.to_s}
106
109
  payload = {:name => name, :points => [], :columns => columns}
107
110
 
108
- data.each do |p|
109
- point = []
110
- columns.each { |c| point << p[c] }
111
- payload[:points].push point
111
+ data.each do |point|
112
+ payload[:points] << columns.inject([]) do |array, column|
113
+ array << InfluxDB::PointValue.new(point[column]).dump
114
+ end
112
115
  end
113
116
 
114
117
  if async
115
118
  @worker = InfluxDB::Worker.new if @worker.nil?
116
119
  @worker.queue.push(payload)
117
120
  else
118
- _write([payload])
121
+ _write([payload], time_precision)
119
122
  end
120
123
  end
121
124
 
122
- def _write(payload)
123
- url = full_url("db/#{@database}/series")
125
+ def _write(payload, time_precision=nil)
126
+ url = full_url("db/#{@database}/series", "time_precision=#{time_precision}")
124
127
  data = JSON.generate(payload)
125
128
 
126
129
  headers = {"Content-Type" => "application/json"}
@@ -189,7 +192,12 @@ module InfluxDB
189
192
 
190
193
  def denormalize_series series
191
194
  columns = series['columns']
192
- series['points'].map { |point| Hash[columns.zip(point)]}
195
+ series['points'].map do |point|
196
+ decoded_point = point.map do |value|
197
+ InfluxDB::PointValue.new(value).load
198
+ end
199
+ Hash[columns.zip(decoded_point)]
200
+ end
193
201
  end
194
202
  end
195
203
  end
@@ -7,4 +7,7 @@ module InfluxDB
7
7
 
8
8
  class ConnectionError < Error
9
9
  end
10
+
11
+ class JSONParserError < Error
12
+ end
10
13
  end
@@ -0,0 +1,49 @@
1
+ require 'json'
2
+
3
+ module InfluxDB
4
+
5
+ class PointValue
6
+ attr_accessor :value
7
+
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+
12
+ def dump
13
+ if value.is_a?(Array) || value.is_a?(Hash)
14
+ JSON.generate(value)
15
+ else
16
+ value
17
+ end
18
+ end
19
+
20
+ def load
21
+ if json?
22
+ begin
23
+ JSON.parse(value)
24
+ rescue JSON::ParserError => e
25
+ raise InfluxDB::JSONParserError, e.message
26
+ end
27
+ else
28
+ value
29
+ end
30
+ end
31
+
32
+ def json?
33
+ value =~ /(
34
+ # define subtypes and build up the json syntax, BNF-grammar-style
35
+ # The {0} is a hack to simply define them as named groups here but not match on them yet
36
+ # I added some atomic grouping to prevent catastrophic backtracking on invalid inputs
37
+ (?<number> -?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?){0}
38
+ (?<boolean> true | false | null ){0}
39
+ (?<string> " (?>[^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " ){0}
40
+ (?<array> \[ (?> \g<json> (?: , \g<json> )* )? \s* \] ){0}
41
+ (?<pair> \s* \g<string> \s* : \g<json> ){0}
42
+ (?<object> \{ (?> \g<pair> (?: , \g<pair> )* )? \s* \} ){0}
43
+ (?<json> \s* (?> \g<number> | \g<boolean> | \g<string> | \g<array> | \g<object> ) \s* ){0}
44
+ )
45
+ \A \g<json> \Z
46
+ /uix
47
+ end
48
+ end
49
+ end
@@ -1,3 +1,3 @@
1
1
  module InfluxDB
2
- VERSION = "0.0.14"
2
+ VERSION = "0.0.15"
3
3
  end
@@ -4,7 +4,7 @@ require "json"
4
4
  describe InfluxDB::Client do
5
5
  before do
6
6
  @influxdb = InfluxDB::Client.new "database", :host => "influxdb.test",
7
- :port => 9999, :username => "username", :password => "password"
7
+ :port => 9999, :username => "username", :password => "password", :time_precision => "s"
8
8
  end
9
9
 
10
10
  describe "#new" do
@@ -19,6 +19,7 @@ describe InfluxDB::Client do
19
19
  @influxdb.username.should == "root"
20
20
  @influxdb.password.should == "root"
21
21
  @influxdb.instance_variable_get(:@http).use_ssl?.should == false
22
+ @influxdb.time_precision.should == "m"
22
23
  end
23
24
  end
24
25
 
@@ -27,7 +28,8 @@ describe InfluxDB::Client do
27
28
  @influxdb = InfluxDB::Client.new :hostname => "host",
28
29
  :port => "port",
29
30
  :username => "username",
30
- :password => "password"
31
+ :password => "password",
32
+ :time_precision => "s"
31
33
 
32
34
  @influxdb.should be_a InfluxDB::Client
33
35
  @influxdb.database.should be_nil
@@ -35,6 +37,7 @@ describe InfluxDB::Client do
35
37
  @influxdb.port.should == "port"
36
38
  @influxdb.username.should == "username"
37
39
  @influxdb.password.should == "password"
40
+ @influxdb.time_precision.should == "s"
38
41
  end
39
42
  end
40
43
 
@@ -48,6 +51,7 @@ describe InfluxDB::Client do
48
51
  @influxdb.port.should == 8086
49
52
  @influxdb.username.should == "root"
50
53
  @influxdb.password.should == "root"
54
+ @influxdb.time_precision.should == "m"
51
55
  end
52
56
  end
53
57
 
@@ -56,7 +60,8 @@ describe InfluxDB::Client do
56
60
  @influxdb = InfluxDB::Client.new "database", :hostname => "host",
57
61
  :port => "port",
58
62
  :username => "username",
59
- :password => "password"
63
+ :password => "password",
64
+ :time_precision => "s"
60
65
 
61
66
  @influxdb.should be_a(InfluxDB::Client)
62
67
  @influxdb.database.should == "database"
@@ -64,6 +69,7 @@ describe InfluxDB::Client do
64
69
  @influxdb.port.should == "port"
65
70
  @influxdb.username.should == "username"
66
71
  @influxdb.password.should == "password"
72
+ @influxdb.time_precision.should == "s"
67
73
  end
68
74
  end
69
75
 
@@ -220,7 +226,7 @@ describe InfluxDB::Client do
220
226
  }]
221
227
 
222
228
  stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
223
- :query => {:u => "username", :p => "password"},
229
+ :query => {:u => "username", :p => "password", :time_precision => "s"},
224
230
  :body => body
225
231
  )
226
232
 
@@ -237,7 +243,7 @@ describe InfluxDB::Client do
237
243
  }]
238
244
 
239
245
  stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
240
- :query => {:u => "username", :p => "password"},
246
+ :query => {:u => "username", :p => "password", :time_precision => "s"},
241
247
  :body => body
242
248
  ).to_return(:status => 401)
243
249
 
@@ -254,7 +260,7 @@ describe InfluxDB::Client do
254
260
  }]
255
261
 
256
262
  stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
257
- :query => {:u => "username", :p => "password"},
263
+ :query => {:u => "username", :p => "password", :time_precision => "s"},
258
264
  :body => body
259
265
  ).to_return(:status => 200)
260
266
 
@@ -271,7 +277,7 @@ describe InfluxDB::Client do
271
277
  }]
272
278
 
273
279
  stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
274
- :query => {:u => "username", :p => "password"},
280
+ :query => {:u => "username", :p => "password", :time_precision => "s"},
275
281
  :body => body
276
282
  )
277
283
 
@@ -279,6 +285,78 @@ describe InfluxDB::Client do
279
285
 
280
286
  @influxdb.write_point("seriez", data).should be_a(Net::HTTPOK)
281
287
  end
288
+
289
+ it "should dump a hash point value to json" do
290
+ prefs = [{'favorite_food' => 'lasagna'}]
291
+ body = [{
292
+ "name" => "users",
293
+ "points" => [[1, prefs.to_json]],
294
+ "columns" => ["id", "prefs"]
295
+ }]
296
+
297
+ stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
298
+ :query => {:u => "username", :p => "password", :time_precision => "s"},
299
+ :body => body
300
+ )
301
+
302
+ data = {:id => 1, :prefs => prefs}
303
+
304
+ @influxdb.write_point("users", data).should be_a(Net::HTTPOK)
305
+ end
306
+
307
+ it "should dump an array point value to json" do
308
+ line_items = [{'id' => 1, 'product_id' => 2, 'quantity' => 1, 'price' => "100.00"}]
309
+ body = [{
310
+ "name" => "seriez",
311
+ "points" => [[1, line_items.to_json]],
312
+ "columns" => ["id", "line_items"]
313
+ }]
314
+
315
+ stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
316
+ :query => {:u => "username", :p => "password", :time_precision => "s"},
317
+ :body => body
318
+ )
319
+
320
+ data = {:id => 1, :line_items => line_items}
321
+
322
+ @influxdb.write_point("seriez", data).should be_a(Net::HTTPOK)
323
+ end
324
+
325
+ it "should POST to add points with time field with precision defined in client initialization" do
326
+ time_in_seconds = Time.now.to_i
327
+ body = [{
328
+ "name" => "seriez",
329
+ "points" => [[87, "juan", time_in_seconds]],
330
+ "columns" => ["age", "name", "time"]
331
+ }]
332
+
333
+ stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
334
+ :query => {:u => "username", :p => "password", :time_precision => "s"},
335
+ :body => body
336
+ )
337
+
338
+ data = {:name => "juan", :age => 87, :time => time_in_seconds}
339
+
340
+ @influxdb.write_point("seriez", data).should be_a(Net::HTTPOK)
341
+ end
342
+
343
+ it "should POST to add points with time field with precision defined in call of write function" do
344
+ time_in_milliseconds = (Time.now.to_f * 1000).to_i
345
+ body = [{
346
+ "name" => "seriez",
347
+ "points" => [[87, "juan", time_in_milliseconds]],
348
+ "columns" => ["age", "name", "time"]
349
+ }]
350
+
351
+ stub_request(:post, "http://influxdb.test:9999/db/database/series").with(
352
+ :query => {:u => "username", :p => "password", :time_precision => "m"},
353
+ :body => body
354
+ )
355
+
356
+ data = {:name => "juan", :age => 87, :time => time_in_milliseconds}
357
+
358
+ @influxdb.write_point("seriez", data, false, "m").should be_a(Net::HTTPOK)
359
+ end
282
360
  end
283
361
 
284
362
  describe "#execute_queries" do
@@ -309,4 +387,21 @@ describe InfluxDB::Client do
309
387
  series.should ==(expected_series)
310
388
  end
311
389
  end
390
+
391
+ describe "#query" do
392
+
393
+ it 'should load JSON point value as an array of hashes' do
394
+ line_items = [{'id' => 1, 'product_id' => 2, 'quantity' => 1, 'price' => "100.00"}]
395
+
396
+ data = [{ :name => "orders", :columns => ["id", "line_items"], :points => [[1, line_items.to_json]]}]
397
+
398
+ stub_request(:get, "http://influxdb.test:9999/db/database/series").with(
399
+ :query => { :q => "select * from orders", :u => "username", :p => "password"}
400
+ ).to_return(
401
+ :body => JSON.generate(data)
402
+ )
403
+
404
+ @influxdb.query('select * from orders').should == {'orders' => [{'id' => 1, 'line_items' => line_items}]}
405
+ end
406
+ end
312
407
  end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe InfluxDB::PointValue do
4
+
5
+ describe 'load' do
6
+
7
+ it 'should raise error if json parsing fails' do
8
+ val = InfluxDB::PointValue.new('{invalid_json')
9
+ val.should_receive(:json?).and_return(true)
10
+ expect { val.load }.to raise_error(InfluxDB::JSONParserError)
11
+ end
12
+ end
13
+ end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: influxdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Persen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-03 00:00:00.000000000 Z
11
+ date: 2014-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
@@ -42,42 +42,42 @@ dependencies:
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ! '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: webmock
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ! '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  description: This is the official Ruby library for InfluxDB.
@@ -100,9 +100,11 @@ files:
100
100
  - lib/influxdb/errors.rb
101
101
  - lib/influxdb/logger.rb
102
102
  - lib/influxdb/max_queue.rb
103
+ - lib/influxdb/point_value.rb
103
104
  - lib/influxdb/version.rb
104
105
  - lib/influxdb/worker.rb
105
106
  - spec/influxdb/client_spec.rb
107
+ - spec/influxdb/point_value_spec.rb
106
108
  - spec/influxdb_spec.rb
107
109
  - spec/max_queue_spec.rb
108
110
  - spec/spec_helper.rb
@@ -116,22 +118,23 @@ require_paths:
116
118
  - lib
117
119
  required_ruby_version: !ruby/object:Gem::Requirement
118
120
  requirements:
119
- - - '>='
121
+ - - ! '>='
120
122
  - !ruby/object:Gem::Version
121
123
  version: '0'
122
124
  required_rubygems_version: !ruby/object:Gem::Requirement
123
125
  requirements:
124
- - - '>='
126
+ - - ! '>='
125
127
  - !ruby/object:Gem::Version
126
128
  version: '0'
127
129
  requirements: []
128
130
  rubyforge_project:
129
- rubygems_version: 2.1.11
131
+ rubygems_version: 2.0.7
130
132
  signing_key:
131
133
  specification_version: 4
132
134
  summary: Ruby library for InfluxDB.
133
135
  test_files:
134
136
  - spec/influxdb/client_spec.rb
137
+ - spec/influxdb/point_value_spec.rb
135
138
  - spec/influxdb_spec.rb
136
139
  - spec/max_queue_spec.rb
137
140
  - spec/spec_helper.rb