Fork me on GitHub

Project Notes

#136 InfluxDb 2.x with Ruby

Testing out the official ruby client calling a InfluxDb 2.0.0-beta server running in Docker.

Notes

The official influxdb-client-ruby gem has been released to support InfluxDb 2.x. This test is running with InfluxDb 2.0.0-beta.

Installing Ruby Gems

The Gemfile is setup for bundler:

$ gem install bundler
$ bundle install

At the time or writing, this isntalls v1.1.0 of the influxdb-client-ruby gem.

Running InfluxDb in Docker

I’m using a Dockerized version of InfluxDb 2.0.0-beta for testing:

$ ../about/influx_control.sh start
Stopping/removing any previous docker container..
myinfluxdb
myinfluxdb
Starting  container with web access on port 9999..
c701849eecda6715baa45d1c8ee6286e81328b22bfaf633af66ede45e2227d71

Overview of the InfluxDb2 gem

The official influxdb-client-ruby gem is very new and still subject to some basic bug fixes. The InflusDb v2 API documented following OpenAPI (previously known as swagger) guidelines, and OpenAPI Generator is used to generate the underlying models in the gem.

I would summarize the gem’s capabilities as follows (with the caveat that my exposure to the gem is still quite limited):

  • it is focused on solving the flux query and result structure handling, so capabilities are currently limited to write, query and delete data.
  • it does not provide direct support for setup and management commands, though arguably these are trivially handled with direct Net:HTTP or RestClient requests.
  • it is (intentionally?) not very idiomatic:
    • queries must be made in Flux syntax. The gem takes care of the hard work of creating a valid query
    • results are presented as FluxTable / FluxColumn / FluxRecord objects that must be further processed to be compatible with the typical end-use of the query.
  • Some improvements it would be nice to see in the gem:
    • an option to present results in basic ruby data types (array of hashes or array of arrays) to make it simpler for gluing together the results of InfluxDb queries typically applications such as ActiveRecord updates or streaming data out via a RESTful Rails API
    • take care of some annoying usability issues such as needing to use_ssl: false when that could/should be implied by the protocol in the URI provided

Stream Some Data

For some random data, I’m using the w command, that includes some processor stats in line 1:

$ w | head -1
23:21  up 18 days, 21:48, 15 users, load averages: 2.82 2.93 2.83

The stream_stats.rb example posts load averages every 5 seconds to a series called lck_cpu with a series tag indicating past 1, 5, and 15 minute averages.

By default, the script sends the data in line protocol format, but it also demonstrates sending in hash and point format (selected with a command line parameter).

$ bundle exec ./stream_stats.rb
Streaming some stats to bucket:demo1 every 5 seconds..
Posting [2.51, 2.55, 2.56] at 1583400081000000000..
["lck_cpu,series=past1 utilization=2.51 1583400081000000000", "lck_cpu,series=past5 utilization=2.55 1583400081000000000", "lck_cpu,series=past15 utilization=2.56 1583400081000000000"]
Posting [2.63, 2.57, 2.56] at 1583400086000000000..
["lck_cpu,series=past1 utilization=2.63 1583400086000000000", "lck_cpu,series=past5 utilization=2.57 1583400086000000000", "lck_cpu,series=past15 utilization=2.56 1583400086000000000"]
...

Streaming in hash format:

$ bundle exec ./stream_stats.rb hash
Streaming some stats to bucket:demo1 every 5 seconds..
Posting [2.82, 2.61, 2.58] at 1583400092000000000..
[{:name=>"lck_cpu", :tags=>{:series=>"past1"}, :fields=>{:utilization=>2.82}, :time=>1583400092000000000}, {:name=>"lck_cpu", :tags=>{:series=>"past5"}, :fields=>{:utilization=>2.61}, :time=>1583400092000000000}, {:name=>"lck_cpu", :tags=>{:series=>"past15"}, :fields=>{:utilization=>2.58}, :time=>1583400092000000000}]
Posting [2.75, 2.6, 2.57] at 1583400097000000000..
[{:name=>"lck_cpu", :tags=>{:series=>"past1"}, :fields=>{:utilization=>2.75}, :time=>1583400097000000000}, {:name=>"lck_cpu", :tags=>{:series=>"past5"}, :fields=>{:utilization=>2.6}, :time=>1583400097000000000}, {:name=>"lck_cpu", :tags=>{:series=>"past15"}, :fields=>{:utilization=>2.57}, :time=>1583400097000000000}]
...

Streaming in point format:

$ bundle exec ./stream_stats.rb point
Streaming some stats to bucket:demo1 every 5 seconds..
Posting [2.93, 2.64, 2.59] at 1583400102000000000..
[#<InfluxDB2::Point:0x00007f90950ecba8 @name="lck_cpu", @tags={"series"=>"past1"}, @fields={"utilization"=>2.93}, @time=1583400102000000000, @precision="ns">, #<InfluxDB2::Point:0x00007f90950ec4c8 @name="lck_cpu", @tags={"series"=>"past5"}, @fields={"utilization"=>2.64}, @time=1583400102000000000, @precision="ns">, #<InfluxDB2::Point:0x00007f90950e7bf8 @name="lck_cpu", @tags={"series"=>"past15"}, @fields={"utilization"=>2.59}, @time=1583400102000000000, @precision="ns">]
Posting [3.02, 2.66, 2.6] at 1583400107000000000..
[#<InfluxDB2::Point:0x00007f90950b7930 @name="lck_cpu", @tags={"series"=>"past1"}, @fields={"utilization"=>3.02}, @time=1583400107000000000, @precision="ns">, #<InfluxDB2::Point:0x00007f90950b74f8 @name="lck_cpu", @tags={"series"=>"past5"}, @fields={"utilization"=>2.66}, @time=1583400107000000000, @precision="ns">, #<InfluxDB2::Point:0x00007f90950b7110 @name="lck_cpu", @tags={"series"=>"past15"}, @fields={"utilization"=>2.6}, @time=1583400107000000000, @precision="ns">]
...

The Data Explorer is a really nice new feature of InfluxDb2. Here’s how the data looks as it streams in:

lck_cpu_in_the_data_explorer

Query Data

The query_stats.rb example queries the most recent data points for the lck_cpu measurement. Flux data structures are not deconstructed for printing:

$ bundle exec ./query_stats.rb
Querying the most recent lck_cpu stats from bucket:demo1..

Record: 0
#<InfluxDB2::FluxColumn:0x00007fcfe5968db0 @index=0, @label="result", @data_type="string", @group=false, @default_value="_result">
#<InfluxDB2::FluxColumn:0x00007fcfe5968b30 @index=1, @label="table", @data_type="long", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968a90 @index=2, @label="_start", @data_type="dateTime:RFC3339", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968a18 @index=3, @label="_stop", @data_type="dateTime:RFC3339", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968838 @index=4, @label="_time", @data_type="dateTime:RFC3339", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe59685b8 @index=5, @label="_value", @data_type="double", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968478 @index=6, @label="_field", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968310 @index=7, @label="_measurement", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968108 @index=8, @label="series", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxRecord:0x00007fcfe595aeb8 @table=0, @values={"result"=>nil, "table"=>0, "_start"=>"1970-01-01T00:00:00+00:00", "_stop"=>"2020-03-05T11:06:29+00:00", "_time"=>"2020-03-05T09:21:47+00:00", "_value"=>3.02, "_field"=>"utilization", "_measurement"=>"lck_cpu", "series"=>"past1"}>

Record: 1
#<InfluxDB2::FluxColumn:0x00007fcfe5968db0 @index=0, @label="result", @data_type="string", @group=false, @default_value="_result">
#<InfluxDB2::FluxColumn:0x00007fcfe5968b30 @index=1, @label="table", @data_type="long", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968a90 @index=2, @label="_start", @data_type="dateTime:RFC3339", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968a18 @index=3, @label="_stop", @data_type="dateTime:RFC3339", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968838 @index=4, @label="_time", @data_type="dateTime:RFC3339", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe59685b8 @index=5, @label="_value", @data_type="double", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968478 @index=6, @label="_field", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968310 @index=7, @label="_measurement", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968108 @index=8, @label="series", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxRecord:0x00007fcfe5949fc8 @table=1, @values={"result"=>nil, "table"=>1, "_start"=>"1970-01-01T00:00:00+00:00", "_stop"=>"2020-03-05T11:06:29+00:00", "_time"=>"2020-03-05T09:21:47+00:00", "_value"=>2.6, "_field"=>"utilization", "_measurement"=>"lck_cpu", "series"=>"past15"}>

Record: 2
#<InfluxDB2::FluxColumn:0x00007fcfe5968db0 @index=0, @label="result", @data_type="string", @group=false, @default_value="_result">
#<InfluxDB2::FluxColumn:0x00007fcfe5968b30 @index=1, @label="table", @data_type="long", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968a90 @index=2, @label="_start", @data_type="dateTime:RFC3339", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968a18 @index=3, @label="_stop", @data_type="dateTime:RFC3339", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968838 @index=4, @label="_time", @data_type="dateTime:RFC3339", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe59685b8 @index=5, @label="_value", @data_type="double", @group=false, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968478 @index=6, @label="_field", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968310 @index=7, @label="_measurement", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxColumn:0x00007fcfe5968108 @index=8, @label="series", @data_type="string", @group=true, @default_value=nil>
#<InfluxDB2::FluxRecord:0x00007fcfe5942598 @table=2, @values={"result"=>nil, "table"=>2, "_start"=>"1970-01-01T00:00:00+00:00", "_stop"=>"2020-03-05T11:06:29+00:00", "_time"=>"2020-03-05T09:21:47+00:00", "_value"=>2.66, "_field"=>"utilization", "_measurement"=>"lck_cpu", "series"=>"past5"}>

Credits and References

About LCK#136 databasesinfluxdbdockerruby
Project Source on GitHub Return to the Project Catalog

LittleCodingKata is my collection of programming exercises, research and code toys broadly spanning things that relate to programming and software development (languages, frameworks and tools).

These range from the trivial to the complex and serious. Many are inspired by existing work and I'll note credits and references where applicable. The focus is quite scattered, as I variously work on things new and important in the moment, or go back to revisit things from the past.

This is primarily a personal collection for my own edification and learning, but anyone who stumbles by is welcome to borrow, steal or reference the work here. And if you spot errors or issues I'd really appreciate some feedback - create an issue, send me an email or even send a pull-request.

LittleArduinoProjects LittleModelArt More on my blog