InfluxElixir.Write.LineProtocol (InfluxElixir v0.1.35)

Copy Markdown View Source

Encodes Point structs into InfluxDB line protocol format.

Handles tag sorting, field type encoding, escaping, multi-point delimiters, and timestamp conversion.

Line Protocol Format

measurement[,tag_key=tag_val]... field_key=field_val[,field_key=field_val]... [timestamp]

Field Type Encoding

  • Integers: suffixed with i (e.g. 42i)
  • Floats: as-is (e.g. 0.64)
  • Strings: double-quoted (e.g. "hello")
  • Booleans: true or false

Escaping Rules

  • Measurement names: spaces, commas, backslashes
  • Tag keys/values: spaces, commas, equals, backslashes
  • Field keys: spaces, commas, equals, backslashes
  • Field string values: double-quotes, backslashes

Validation

A point that no InfluxDB accepts is refused here, with a tagged error, rather than encoded into a line the server rejects — or worse, one it misreads. Line protocol has no escape for a newline outside a quoted string value, so a newline in a measurement, tag key, tag value or field key ends the line early and the remainder is parsed as a second line: verified against InfluxDB 3, tags: %{"host" => "a\nb"} stores a bogus measurement b. The checks, each verified against the engine:

ProblemError
No fields:empty_fields
Empty measurement:empty_measurement
Measurement not a string, containing a newline, or starting with #{:invalid_measurement, value}
Tag key empty, not a string, or containing a newline{:invalid_tag_key, key}
Tag value empty, not a string, or containing a newline{:invalid_tag_value, key, value}
Tag key time (reserved on every version){:reserved_tag_key, "time"}
Field key empty, not a string, or containing a newline{:invalid_field_key, key}
Field value not an integer, float, string or boolean, or an integer outside 64 bits{:invalid_field_value, key, value}
Timestamp not a DateTime, integer or nil{:invalid_timestamp, value}

A measurement, tag key, tag value or field key that ends in a backslash is refused with the same error as the other problems with that name: both versions reject the line even though the backslash is escaped. A measurement starting with # is a comment line to both, which drop it silently inside a batch, and escaping it (#) stores the backslash. An integer field must fit in a signed 64-bit integer; there is no unsigned field type on a Point.

A field named time is left to the server: InfluxDB 3 rejects it and InfluxDB 2 drops it silently. So is a tab in a name: InfluxDB 3 refuses the line and InfluxDB 2 stores the tab. A newline inside a string field value is fine — it is quoted, and both versions store it.

Summary

Functions

Encodes a Point or list of Points into InfluxDB line protocol binary.

Encodes a Point or list of Points into InfluxDB line protocol binary.

Types

encode_result()

@type encode_result() :: {:ok, binary()} | {:error, term()}

Functions

encode(point_or_points, opts \\ [])

Encodes a Point or list of Points into InfluxDB line protocol binary.

Returns {:ok, binary} on success or {:error, reason} on failure; see "Validation" in the moduledoc for the reasons.

Options

  • :precision - the unit of the write the line is for (:second, :millisecond, :microsecond, :nanosecond, or the short spellings write/3 takes: :s, "ms", "us", "u", "n", ...). A DateTime timestamp is written in that unit, truncated; without it (or for :auto) in nanoseconds. A DateTime written in nanoseconds to a write with precision: :second is out of range on the server (verified), so pass the write's precision here. An integer timestamp is written as given: it is already in the caller's unit.

Examples

iex> point = InfluxElixir.Write.Point.new("cpu", %{"value" => 0.64})
iex> {:ok, lp} = InfluxElixir.Write.LineProtocol.encode(point)
iex> lp
"cpu value=0.64"

iex> point = InfluxElixir.Write.Point.new("cpu", %{"count" => 42},
...>   tags: %{"host" => "server01"},
...>   timestamp: 1_630_424_257_000_000_000
...> )
iex> {:ok, lp} = InfluxElixir.Write.LineProtocol.encode(point)
iex> lp
"cpu,host=server01 count=42i 1630424257000000000"

iex> point = InfluxElixir.Write.Point.new("cpu", %{"v" => 1}, tags: %{"host" => ""})
iex> InfluxElixir.Write.LineProtocol.encode(point)
{:error, {:invalid_tag_value, "host", ""}}

encode!(point_or_points, opts \\ [])

Encodes a Point or list of Points into InfluxDB line protocol binary.

Raises ArgumentError on failure.

Examples

iex> point = InfluxElixir.Write.Point.new("cpu", %{"value" => 0.64})
iex> InfluxElixir.Write.LineProtocol.encode!(point)
"cpu value=0.64"