Current section
Files
Jump to
Current section
Files
lib/logger_multicast_sender.ex
defmodule LoggerMulticastSender do
@moduledoc false
use GenServer
require Logger
@socket_retry_time 1000 # milliseconds between port open attempts
@packet_pacer_time 10 # milliseconds between multicasts
@queue_size 1024 # maximum lines to save in the queue
@socket_opts [:binary, {:broadcast, true}, {:active, false}, {:reuseaddr, true} ]
def init(target) do
Logger.debug "started multicast logging sender on target: #{inspect target}"
state = %{target: target, queue: [], socket: nil}
{:ok, state}
end
def handle_cast({:add_entry, entry}, state) do
queue = state.queue ++ [entry]
if (length(queue) > @queue_size) do
[_ | queue_tail] = queue
{:noreply, %{ state | queue: queue_tail}, @packet_pacer_time}
else
{:noreply, %{ state | queue: queue}, @packet_pacer_time}
end
end
# "handle a timer with no current socket - attempt to open it"
def handle_info(:timeout, %{socket: nil} = state) do
case :gen_udp.open(0, @socket_opts) do
{:ok, socket} ->
{:noreply, %{ state | socket: socket }, @packet_pacer_time}
_ ->
{:noreply, state, @socket_retry_time}
end
end
# "handle a timer with a valid socket - attempt to write to it"
def handle_info(:timeout, %{queue: queue, socket: socket, target: {addr, port}} = state) when (length(queue) > 0) do
[first | rest] = queue
case :gen_udp.send(socket, addr, port, first) do
:ok ->
{:noreply, %{state | queue: rest}, @packet_pacer_time}
_ ->
:gen_udp.close socket
{:noreply, %{state | socket: nil}, @socket_retry_time}
end
end
def handle_info(:timeout, state) do
{:noreply, state}
end
end