influxdb 0.0.14 → 0.0.15

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 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