Current section

Files

Jump to
new_relixir lib new_relixir polling.ex
Raw

lib/new_relixir/polling.ex

defmodule NewRelixir.Polling do
use GenServer
require Logger
@polling_interval Application.get_env(:new_relixir, :polling_interval) || 30_000
## API
def start_link(pull_fun, error_cb \\ &default_error_cb/2) do
GenServer.start_link(__MODULE__, %{pull_fun: pull_fun, error_cb: error_cb})
end
## Callbacks
def init(state) do
timer = :erlang.send_after(@polling_interval, self(), :pull)
{:ok, Map.put(state, :timer, timer)}
end
def handle_call(_msg, _from, state) do
{:reply, :ok, state}
end
def handle_cast(_msg, state) do
{:noreply, state}
end
def handle_info(:pull, %{pull_fun: pull_fun, error_cb: error_cb, timer: old_timer}) do
:erlang.cancel_timer(old_timer)
timer = :erlang.send_after(@polling_interval, self(), :pull)
# when running in heroku, hostname will be set in env var DYNO
hostname = if env_hostname = System.get_env("DYNO") do
env_hostname
else
{:ok, hostname} = :inet.gethostname()
hostname
end
try do
case pull_fun.() do
{[], [], _internval} ->
:ok
{metrics, errors, {start_time, end_time}} ->
metrics = [
round(start_time / 1000),
round(end_time / 1000),
metrics
]
try do
NewRelixir.Agent.push(hostname, metrics, errors)
rescue
error -> error_cb.(:push_failed, error)
end
end
rescue
error -> error_cb.(:pull_failed, error)
end
{:noreply, %{pull_fun: pull_fun, error_cb: error_cb, timer: timer}}
end
def handle_info(_msg, state) do
{:noreply, state}
end
## Private functions
defp default_error_cb(:pull_failed, err_msg) do
Logger.error("NewRelixir.Polling: pull failed: #{inspect err_msg}")
end
defp default_error_cb(:push_failed, err_msg) do
Logger.error("NewRelixir.Polling: push failed: #{inspect err_msg}")
end
end