Current section

Files

Jump to
kvasir_agent_server lib kvasir agent_server metrics.ex
Raw

lib/kvasir/agent_server/metrics.ex

defmodule Kvasir.AgentServer.Metrics do
@default_port 8125
@supported_protocols ~W(statsd+udp statsd2+udp statsd statsd2 udp)
@spec open(binary | URI.t()) :: {:ok, port, [byte, ...]}
def open(url) do
case URI.parse(url) do
%URI{scheme: s, host: h, port: p} when s in @supported_protocols ->
open(h, p || @default_port)
_ ->
raise "Invalid metrics url: #{inspect(url)}."
end
end
@spec open(
host :: binary | charlist | {byte, byte, byte, byte},
port :: binary | integer
) :: {:ok, port, [byte, ...]}
def open(host, port) do
true = Code.ensure_loaded?(:gen_udp)
h = if(is_binary(host), do: String.to_charlist(host), else: host)
p = if(is_binary(port), do: String.to_integer(port), else: port)
parent = self()
spawn_link(fn ->
{:ok, socket} = :gen_udp.open(0, active: false)
send(parent, {:socket, socket})
:timer.sleep(:infinity)
end)
socket =
receive do
{:socket, s} -> s
end
{:ok, socket, build_header(h, p)}
end
### UDP Building ###
otp_release = :erlang.system_info(:otp_release)
@addr_family if(otp_release >= '19', do: [1], else: [])
defp build_header(host, port) do
{ip1, ip2, ip3, ip4} =
if is_tuple(host) do
host
else
{:ok, ip} = :inet.getaddr(host, :inet)
ip
end
anc_data_part =
if function_exported?(:gen_udp, :send, 5) do
[0, 0, 0, 0]
else
[]
end
@addr_family ++
[
:erlang.band(:erlang.bsr(port, 8), 0xFF),
:erlang.band(port, 0xFF),
:erlang.band(ip1, 0xFF),
:erlang.band(ip2, 0xFF),
:erlang.band(ip3, 0xFF),
:erlang.band(ip4, 0xFF)
] ++ anc_data_part
end
end