defmodule Telegraf do use Supervisor @external_resource "README.md" @moduledoc "README.md" |> File.read!() |> String.split("") |> Enum.fetch!(1) @typedoc "Name of the telegraf instance." @type name :: atom() @opts_definition [ name: [ type: :atom, doc: "Name of the telegraf instance.", required: true ], transport: [ type: :atom, doc: "A module implementing `Telegraf.Transport` behaviour.", default: Telegraf.Transport.UnixSocket ], transport_options: [ type: :keyword_list, doc: "Options passed to the transport adapter. " <> "Checkout each transport adapter docs for a detailed description of the options.", default: [] ], serializer: [ type: :atom, doc: "A module implementing `Telegraf.Serializer` behaviour.", default: Telegraf.Serializer.LineProtocol ] ] @doc """ Starts a #{inspect(__MODULE__)} supervisor. ## Supported options #{NimbleOptions.docs(@opts_definition)} """ def start_link(opts) do opts = validate_options!(opts) name = Keyword.fetch!(opts, :name) Supervisor.start_link(__MODULE__, opts, name: name) end @impl Supervisor def init(opts) do name = Keyword.fetch!(opts, :name) transport = Keyword.fetch!(opts, :transport) serializer = Keyword.fetch!(opts, :serializer) transport_options = Keyword.fetch!(opts, :transport_options) :persistent_term.put({__MODULE__, name}, {transport, serializer}) name |> transport.children(transport_options) |> Supervisor.init(strategy: :one_for_one) end @doc """ Sends a metric to the telegraf daemon ```elixir metric = %Telegraf.Metric{ name: "weather", tag_set: %{location: "us-midwest"}, field_set: %{temperature: 82}, timestamp: System.os_time() } Telegraf.send(MyTelegraf, metric) ``` """ @spec send(name(), Metric.t() | [Metric.t()], Keyword.t()) :: :ok | {:error, term()} def send(name, metric_or_metrics, opts \\ []) do {transport, serializer} = :persistent_term.get({__MODULE__, name}) message = metric_or_metrics |> List.wrap() |> serializer.serialize() transport.send(name, message, opts) end defp validate_options!(opts) do case NimbleOptions.validate(opts, @opts_definition) do {:ok, opts} -> opts {:error, %NimbleOptions.ValidationError{message: message}} -> raise ArgumentError, "invalid configuration given to #{inspect(__MODULE__)}.start_link/1, " <> message end end end