diff --git a/lib/statix.ex b/lib/statix.ex index 6a275f2..b70ca6a 100644 --- a/lib/statix.ex +++ b/lib/statix.ex @@ -331,9 +331,18 @@ defmodule Statix do @doc false def new_conn(module) do - {host, port, prefix} = load_config(module) - conn = Conn.new(host, port) + {conn, prefix} = + case load_config(module) do + {:inet, {host, port, prefix}} -> + conn = Conn.new(host, port) + {conn, prefix} + + {:local, {socket_path, prefix}} -> + {Conn.new(:local, socket_path), prefix} + end + header = IO.iodata_to_binary([conn.header | prefix]) + %{conn | header: header, sock: module} end @@ -362,12 +371,16 @@ defmodule Statix do {prefix1, env1} = Keyword.pop_first(env1, :prefix) {prefix2, env2} = Keyword.pop_first(env2, :prefix) + prefix = build_prefix(prefix1, prefix2) env = Keyword.merge(env1, env2) - host = Keyword.get(env, :host, "127.0.0.1") - port = Keyword.get(env, :port, 8125) - prefix = build_prefix(prefix1, prefix2) - {host, port, prefix} + if env[:local] do + {:local, {env[:socket_path], prefix}} + else + host = Keyword.get(env, :host, "127.0.0.1") + port = Keyword.get(env, :port, 8125) + {:inet, {host, port, prefix}} + end end defp build_prefix(part1, part2) do diff --git a/lib/statix/conn.ex b/lib/statix/conn.ex index b25d3be..ce8e6db 100644 --- a/lib/statix/conn.ex +++ b/lib/statix/conn.ex @@ -1,27 +1,37 @@ defmodule Statix.Conn do @moduledoc false - defstruct [:sock, :header] + defstruct [:sock, :header, :type] alias Statix.Packet require Logger + def new(:local, path) do + header = Packet.header(:local, path) + %__MODULE__{header: header, type: :local} + end + def new(host, port) when is_binary(host) do new(string_to_charlist(host), port) end def new(host, port) when is_list(host) or is_tuple(host) do {:ok, addr} = :inet.getaddr(host, :inet) - header = Packet.header(addr, port) - %__MODULE__{header: header} + header = Packet.header(:inet, addr, port) + %__MODULE__{header: header, type: :inet} end - def open(%__MODULE__{} = conn) do + def open(%__MODULE__{type: :inet} = conn) do {:ok, sock} = :gen_udp.open(0, active: false) %__MODULE__{conn | sock: sock} end + def open(%__MODULE__{type: :local} = conn) do + {:ok, sock} = :gen_udp.open(0, [:local, active: false]) + %__MODULE__{conn | sock: sock} + end + def transmit(%__MODULE__{header: header, sock: sock}, type, key, val, options) when is_binary(val) and is_list(options) do result = diff --git a/lib/statix/packet.ex b/lib/statix/packet.ex index fd84ccf..01fc149 100644 --- a/lib/statix/packet.ex +++ b/lib/statix/packet.ex @@ -5,8 +5,9 @@ defmodule Statix.Packet do otp_release = :erlang.system_info(:otp_release) @addr_family if(otp_release >= '19', do: [1], else: []) + @inet_local [5] - def header({n1, n2, n3, n4}, port) do + def header(:inet, {n1, n2, n3, n4}, port) do true = Code.ensure_loaded?(:gen_udp) anc_data_part = @@ -27,6 +28,14 @@ defmodule Statix.Packet do ] ++ anc_data_part end + def header(:local, socket_path) do + @inet_local ++ + [ + byte_size(socket_path), + socket_path + ] + end + def build(header, name, key, val, options) do [header, key, ?:, val, ?|, metric_type(name)] |> set_option(:sample_rate, options[:sample_rate])