fluxter v0.4.0 Fluxter behaviour

InfluxDB writer for Elixir that uses InfluxDB’s line protocol over UDP.

To get started with Fluxter, you have to create a module that calls use Fluxter, like this:

defmodule MyApp.Fluxter do
  use Fluxter
end

This way, MyApp.Fluxter becomes an InfluxDB connection pool. Each Fluxter pool provides a start_link/0 function that starts that pool and connects to InfluxDB; this function needs to be invoked before being able to send data to InfluxDB. Typically, you won’t call start_link/0 directly as you’ll want to add Fluxter pools to your application’s supervision tree; for example:

def start(_type, _args) do
  import Supervisor.Spec

  children = [
    supervisor(MyApp.Fluxter, []),
    # ...
  ]
  Supervisor.start_link(children, strategy: :one_for_one)
end

Once a Fluxter pool is started, its write/2,3 and measure/2,3,4 functions can successfully be used to send points to the data store. A Fluxter pool implements the Fluxter behaviour, so you can read documentation for the callbacks the behaviour provides to know more about these functions.

Configuration

Fluxter can be configured either globally or on a per-pool basis.

The global configuration will affect all Fluxter pools; it can be specified by configuring the :fluxter application:

config :fluxter,
  host: "metrics.example.com",
  port: 1122

The per-pool configuration can be specified by configuring the pool module under the :fluxter application:

config :fluxter, MyApp.Fluxter,
  host: "metrics.example.com",
  port: 1122,
  pool_size: 10

The following is a list of all the supported options:

  • :host - (binary) the host to send metrics to. Defaults to "127.0.0.1".
  • :port - (integer) the port (on :host) to send the metrics to. Defaults to 8092.
  • :prefix - (binary or nil) all metrics sent to the data store through the configured Fluxter pool will be prefixed by the value of this option. If nil, metrics will not be prefixed. Defaults to nil.
  • :pool_size - (integer) the size of the connection pool for the given Fluxter pool. This option can only be configured on a per-pool basis; configuring it globally for the :fluxter application has no effect. Defaults to 5.

Batching

Fluxter supports “batching”: a batch is a metric aggregator designed to locally aggregate an numeric value and flush the aggregated value only once to the storage, as a single metric. This is very useful when you have the need to write a high number of metrics in a very short amount of time. Doing so can have a negative impact on the speed of your code and can also cause network packet drops.

For example, code like the following:

for i <- 1_000_000 do
  my_operation(i)
  MyApp.Fluxter.write("my_operation_success", [host: "eu-west"], 1)
end

can take advantage of batching:

{:ok, batch} = MyApp.Fluxter.start_batch("my_operation_success", [host: "eu-west"])
for i <- 1_000_000 do
  my_operation(i)
  MyApp.Fluxter.write_to_batch(batch, 1)
end
MyApp.Fluxter.flush_batch(batch)

Summary

Callbacks

Flushes the given batch by writing its aggregated value as a single metric

Should be the same as measure(name, [], [], fun)

Should be the same as measure(name, tags, [], fun)

Measures the execution time of fun and writes it as a metric named name

Should be the same as start_batch(name, [], [])

Should be the same as start_batch(name, tags, [])

Starts a batch for a metric named name

Starts this Fluxter pool

Should be the same as write(name, [], fields)

Writes a metric to the data store

Adds the extra value to the given batch

Types

field_value :: number | boolean | binary

Callbacks

flush_batch(batch)

Specs

flush_batch(batch :: pid) :: :ok

Flushes the given batch by writing its aggregated value as a single metric.

This function performs a fire-and-forget operation (a cast) on the given batch, hence it will always return :ok.

This function will also stop the batch process after the metric is flushed.

See the “Batching” section in the documentation for Fluxter for more information on batches.

Examples

Assuming a MyApp.Fluxter Fluxter pool exists:

iex> MyApp.Fluxter.flush_batch(batch)
:ok
measure(name, fun)

Specs

measure(name :: String.Chars.t, fun :: (() -> result)) :: result when result: any

Should be the same as measure(name, [], [], fun).

measure(name, tags, fun)

Specs

measure(name :: String.Chars.t, tags, fun :: (() -> result)) :: result when result: any

Should be the same as measure(name, tags, [], fun).

measure(name, tags, fields, fun)

Specs

measure(name :: String.Chars.t, tags, fields, fun :: (() -> result)) :: result when result: any

Measures the execution time of fun and writes it as a metric named name.

This function is just an utility function to measure the execution time of a given function fun. The name and tags arguments work in the same way as in c:write/3.

fun’s execution time is prepended as a field called value to the already existing list of fields. This means that if there’s already a field called value in fields, it will be overridden by the measurement. This also means that fields must be a list of key-value pairs (field name and value): simple floats, integers, booleans, and binaries as values for fields are not supported like they are in c:write/3.

This function returns whatever fun returns.

Examples

Assuming a MyApp.Fluxter Fluxter pool exists:

iex> MyApp.Fluxter.measure "task_exec_time", [host: "us-east"], fn ->
...>   1 + 1
...> end
2
start_batch(name)

Specs

start_batch(name :: String.Chars.t) :: {:ok, pid}

Should be the same as start_batch(name, [], []).

start_batch(name, tags)

Specs

start_batch(name :: String.Chars.t, tags) :: {:ok, pid}

Should be the same as start_batch(name, tags, []).

start_batch(name, tags, fields)

Specs

start_batch(name :: String.Chars.t, tags, fields) :: {:ok, pid}

Starts a batch for a metric named name.

The purpose of this batch is to aggregate a numeric metric: values aggregated in the batch will only be written to the storage as a single metric when the batch is “flushed” (see c:flush_batch/1). tags and fields will be tags and fields attached to the metric when it’s flushed. The aggregated value of the metric will be prepended to fields as a field called value; this means that if there’s already a field called value in fields, it will be overridden.

This function returns {:ok, pid} where pid is the pid of the new batch.

See the “Batching” section in the documentation for Fluxter for more information on batches.

Examples

Assuming a MyApp.Fluxter Fluxter pool exists:

iex> MyApp.Fluxter.start_batch("hits", [host: "us-west"])
{:ok, #PID<...>}
start_link()

Specs

start_link :: Supervisor.on_start

Starts this Fluxter pool.

A Fluxter pool is a set of processes supervised by a supervisor; this function starts all that processes and that supervisor.

Usually, you’ll want to use a Fluxter pool in the supervision tree of your application:

def start(_type, _args) do
  import Supervisor.Spec

  children = [
    supervisor(MyApp.Fluxter, []),
    # ...
  ]
  Supervisor.start_link(children, strategy: :one_for_one)
end
write(name, arg1)

Specs

write(name :: String.Chars.t, field_value | fields) :: :ok

Should be the same as write(name, [], fields).

write(name, tags, arg2)

Specs

write(name :: String.Chars.t, tags, field_value | fields) :: :ok

Writes a metric to the data store.

name is the name of the metric to write. tags is a list of key-value pairs that specifies tags (as name and value) for the metric to write; note that tag values are converted to strings as InfluxDB only support string values for tags. fields can either be a list of key-value pairs, in which case it specifies a list of fields (as name and value), or a single value (specifically, a boolean, float, integer, or binary). In the latter case, the default field name of value will be used: calling write("foo", [], 4.3) is the same as calling write("foo", [], value: 4.3).

The return value is always :ok as writing is a fire-and-forget operation.

Examples

Assuming a MyApp.Fluxter Fluxter pool exists:

iex> MyApp.Fluxter.write("cpu_temp", [host: "eu-west"], 68)
:ok
write_to_batch(batch, extra)

Specs

write_to_batch(batch :: pid, extra :: number) :: :ok

Adds the extra value to the given batch.

This function adds the extra value (a number) to the current value of the given batch. To subtract, just use a negative number to add to the current value of batch.

This function performs a fire-and-forget operation (a cast) on the given batch, hence it will always return :ok.

See the “Batching” section in the documentation for Fluxter for more information on batches.

Examples

Assuming a MyApp.Fluxter Fluxter pool exists:

iex> MyApp.Fluxter.write_to_batch(batch, 1)
:ok