Instream
InfluxDB driver for Elixir
Warning
This module is highly experimental at the moment and may behave or change unexpectedly.
Tested influxdb version: 0.9.3
(see .travis.yml
to be sure)
Setup
Add Instream as a dependency to your mix.exs
file:
defp deps do
[ { :instream, "~> 0.5" } ]
end
You should also update your applications to include all necessary projects:
def application do
[ applications: [ :instream ] ]
end
Testing
To run the tests you need to have the http-authentication enabled.
Using the statements from the .travis.yml
you can generate all necessary
users for the tests with their proper privileges.
Usage
Connections
Defining a connection requires defining a module:
defmodule MyApp.MyConnection do
use Instream.Connection, otp_app: :my_app
end
The :otp_app
name and the name of the module can be freely chosen.
They only need to be linked to an entry in your config.exs
:
config :my_app, MyApp.MyConnection,
hosts: [ "localhost" ],
pool: [ max_overflow: 0, size: 1 ],
port: 8086,
scheme: "http",
writer: Instream.Writer.JSON
You now have a connection definition you can hook into your supervision tree:
Supervisor.start_link(
[ MyApp.MyConnection.child_spec ],
strategy: :one_for_one
)
Authentication
To connect to an influxdb instance with http_auth enabled you have to configure your credentials:
config :my_app, MyApp.MyConnection,
auth: [ method: :basic, username: "root", password: "root" ]
For method
you can choose between header authentication (basic auth) using
:basic
or query parameters using :query
. If nothing or an invalid value
is given the connection will be made using :basic
authentication..
Queries
Every query can be executed asynchronously by passing [async: true]
to
MyApp.MyConnection.execute()
. The result will then always be an immediate
:ok
without waiting for the query to be actually executed.
Administrative Queries
Managing Databases:
# create "my_database"
"my_database"
|> Instream.Cluster.Database.create()
|> MyApp.MyConnection.create()
# drop "my_database"
"my_database"
|> Instream.Cluster.Database.drop()
|> MyApp.MyConnection.execute()
Managing Retention Policies:
# create "my_rp" retention policy
Instream.Cluster.RetentionPolicy.create(
"my_rp", "my_database", "DURATION 1h REPLICATION 3 DEFAULT"
)
|> MyApp.MyConnection.execute()
# drop "my_rp" retention policy
Instream.Cluster.RetentionPolicy.drop("my_rp", "my_database")
|> MyApp.MyConnection.execute()
Data Queries
Writing data:
%{
database: "my_database",
points: [
%{
measurement: "some_measurement",
tags: %{ foo: "foo", bar: "bar" },
fields: %{ value: 0.66 }
}
]
}
|> Instream.Data.Write.query()
|> MyApp.MyConnection.execute([ async: true ])
Reading data:
# passing database to execute/1
"SELECT * FROM some_measurement"
|> Instream.Data.Read.query()
|> MyApp.MyConnection.execute(database: "my_database")
# defining database in the query
"SELECT * FROM \"my_database\".\"default\".\"some_measurement\""
|> Instream.Data.Read.query()
|> MyApp.MyConnection.execute()
Series Defintions
If you do not want to define the raw maps for writing data you can pre-define a seriesfor later usage:
defmodule MySeries do
use Instream.Series
series do
database :my_database
measurement :my_measurement
tag :bar
tag :foo
field :value
end
end
You can then use this module to assemble a (single!) data point for writing:
data = %MySeries{}
data = %{ data | fields: %{ data.fields | value: 17 }}
data = %{ data | tags: %{ data.tags | bar: "bar", foo: "foo" }}
data
|> Instream.Data.Write.query()
|> MyApp.MyConnection.execute()