Current section
Files
Jump to
Current section
Files
lib/luger.ex
defmodule Luger do
@moduledoc """
A plug for logging basic request information in the format:
17:26:06.192 [info] POST /path - 200 - 794µs - 127.0.0.1
## Options
* `:include_ip` - Whether or not to include the remote_ip field in the log
message. Default is `true`.
* `:level` - The log level at which this plug should log its request info.
Default is `:info`.
"""
defstruct [:level, :include_ip]
# inherit behaviour of Plug
@behaviour Plug
# add some typing
@opaque t :: %__MODULE__{}
# add a message alias
alias __MODULE__.Message
# we need the logger
require Logger
@doc """
Initializes the logger by creating a struct containing options.
"""
@spec init(options :: Keyword.t) :: level :: atom
def init(options \\ []) when is_list(options),
do: %__MODULE__{
level: Keyword.get(options, :level, :info),
include_ip: !!Keyword.get(options, :include_ip, true)
}
@doc """
Called on each request, triggers a log to happen on send.
"""
@spec call(conn :: Conn.t, level :: atom) :: conn :: Conn.t
def call(conn, %{ level: :none }),
do: conn
def call(conn, %{ level: level } = opts) do
before_time = :os.timestamp()
Plug.Conn.register_before_send(conn, fn(conn) ->
Logger.log(level, fn ->
diff = :timer.now_diff(:os.timestamp(), before_time)
conn
|> Message.create(diff, opts)
|> Message.join
end)
conn
end)
end
# Forward some requests through to the Message module.
defdelegate create(conn, duration, opts),
to: Message
defdelegate join(message),
to: Message
defdelegate split(message),
to: Message
@doc false
defmacro __using__(_) do
import PrePlug, only: [pre_plug: 1]
quote location: :keep do
unless Module.get_attribute(__MODULE__, :pre_plugs) do
use PrePlug
end
pre_plug Luger
end
end
end