Current section
Files
Jump to
Current section
Files
lib/logger_loggly_backend.ex
defmodule LoggerLogglyBackend do
use GenEvent
def init({__MODULE__, name}) do
{:ok, configure(name, [])}
end
def handle_call({:configure, opts}, %{name: name}) do
{:ok, :ok, configure(name, opts)}
end
defp meet_level?(_lvl, nil), do: true
defp meet_level?(lvl, min) do
Logger.compare_levels(lvl, min) != :lt
end
def handle_event({_level, gl, _event}, state)
when node(gl) != node() do
{:ok, state}
end
def handle_event({level, _gl, {Logger, msg, ts, md}}, state) do
if meet_level?(level, state.level) do
log_event(level, msg, ts, md, state)
end
{:ok, state}
end
defp take_metadata(metadata, keys) do
List.foldr keys, [], fn key, acc ->
case Keyword.fetch(metadata, key) do
{:ok, val} -> [{key, val} | acc]
:error -> acc
end
end
end
defp format_event(level, msg, ts, md, %{format: format, metadata: keys}) do
Logger.Formatter.format(format, level, msg, ts, take_metadata(md, keys))
end
defp log_event(level, msg, ts, md, state) do
output = format_event(level, msg, ts, md, state)
HTTPoison.post(state.url, output, %{"content-type": "text/plain"}, timeout: state.timeout)
end
defp configure(name, opts) do
env = Application.get_env(:logger, name, [])
opts = Keyword.merge(env, opts)
Application.put_env(:logger, name, opts)
format = Keyword.get(opts, :format) |> Logger.Formatter.compile
level = Keyword.get(opts, :level, :info)
tags = Keyword.get(opts, :tags, [])
token = Keyword.get(opts, :token, System.get_env("LOGGLY_TOKEN"))
type = Keyword.get(opts, :type, :inputs)
timeout = Keyword.get(opts, :timeout, 5000)
metadata = Keyword.get(opts, :metadata, [])
host = Keyword.get(opts, :host, "http://logs-01.loggly.com")
%{name: name, format: format,
url: "#{host}/#{type}/#{token}/tag/#{Enum.join(tags, ",")}",
level: level, metadata: metadata, tags: tags, timeout: timeout}
end
end