defmodule HAHandler.HAProxy do alias :procket, as: Socket @haproxy_socket "/run/haproxy.sock" def open_socket() do pad = 8 * (Socket.unix_path_max() - byte_size(@haproxy_socket)) sockaddr = Socket.sockaddr_common(1, byte_size(@haproxy_socket)) <> @haproxy_socket <> <<0::size(pad)>> family = 1 {:ok, socket} = Socket.socket(family, 1, 0) case Socket.connect(socket, sockaddr) do :ok -> {stdin, stdout} = {socket, socket} port = Port.open({:fd, stdin, stdout}, [{:line, 10_000}, :binary]) Process.link(port) {:ok, port} {:error, err} -> {:error, err} end end defp read_from_socket(socket, acc \\ "") do receive do {_port, {:data, {:noeol, data}}} -> read_from_socket(socket, acc <> data) {_port, {:data, {:eol, data}}} -> Poison.decode(acc <> data) _ -> {:error, :unexpected} after 5000 -> {:error, :timeout} end end def get_stats() do case open_socket() do {:ok, socket} -> send socket, {self(), {:command, "show stat json\n"}} case read_from_socket(socket) do {:ok, raw} -> for entry <- raw do attrs = entry |> Enum.filter(fn m -> get_in(m, ["field", "name"]) == "pxname" end) |> Enum.at(0) %{type: attrs |> Map.get("objType"), name: get_in(attrs, ["value", "value"])} end {:error, err} -> {:error, err} end {:error, err} -> {:error, err} end end end