https://github.com/mneudert/plug_accesslog
Plug for writing access logs
https://github.com/mneudert/plug_accesslog
Last synced: 30 days ago
JSON representation
Plug for writing access logs
- Host: GitHub
- URL: https://github.com/mneudert/plug_accesslog
- Owner: mneudert
- License: apache-2.0
- Created: 2015-01-10T13:46:02.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2022-01-04T10:50:55.000Z (over 3 years ago)
- Last Synced: 2025-02-27T17:35:10.762Z (about 2 months ago)
- Language: Elixir
- Size: 326 KB
- Stars: 31
- Watchers: 3
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- freaking_awesome_elixir - Elixir - Plug for writing access logs. (Framework Components)
- fucking-awesome-elixir - plug_accesslog - Plug for writing access logs. (Framework Components)
- awesome-elixir - plug_accesslog - Plug for writing access logs. (Framework Components)
README
# Plug.AccessLog
Plug for writing access logs.
## Setup
To use the plug in your projects, edit your mix.exs file and add the project as a dependency:
```elixir
defp deps do
[
# ...
{:plug_accesslog, "~> 0.15.0"},
# ...
]
end
```## Usage
Add the plug to your plug pipeline/router:
```elixir
defmodule AppRouter do
use Plug.Routerplug Plug.AccessLog,
format: :clf,
file: "/path/to/your/logs/access.log"plug :match
plug :dispatchget "/hello" do
send_resp(conn, 200, "world")
endmatch _ do
send_resp(conn, 404, "oops")
end
end
```__Note__: The usage examples apply to a usecase where your are using `plug` directly without any framework. Using the `plug Plug.AccessLog` line in a framework based on `plug` should be no problem. Please refer to your frameworks individual documentation or source to find a suitable place.
### WAL Configuration
All log messages that will be written to a file are collected in a WAL process
before actual writing. The messages will be fetched in a configurable interval
to be written to the logfiles:```elixir
config :plug_accesslog,
:wal,
flush_interval: 100
```The time is configured as "milliseconds between writing and flushing". The default value is `100` milliseconds.
### Custom Formatters
If you want to extend the formatting capabilities or replace existing ones you can define a custom formatter pipeline to use:
```elixir
defmodule CustomFormatter do
@behaviour Plug.AccessLog.Formatterdef format(format, conn) do
# manipulate to your liking
format
end
enddefmodule Router do
use Plug.Routerplug Plug.AccessLog,
format: :clf,
formatters: [CustomFormatter, Plug.AccessLog.DefaultFormatter],
file: "/path/to/your/logs/access.log"
end
```If you do not configure a list of formatters only the `DefaultFormatter` will be used. If you define an empty list then no formatting will take place.
All formatters are called in the order they are defined in.
### File Configuration
There are two ways to define the file you want log entries to be written to:
```elixir
defmodule Router do
use Plug.Routerplug Plug.AccessLog, file: "/static/configuration.log"
plug Plug.AccessLog, file: {:system, "SYS_ENV_VAR_WITH_FILE_PATH"}
plug Plug.AccessLog, file: {:system, "SYS_ENV_VAR", "/path/to/default.log"}
end
```### Do Not Log Filter
To filter the requests before logging you can configure a "do not log" filter function:
```elixir
defmodule LogFilter do
def dontlog?(%{request_path: "/favicon.ico"}), do: true
def dontlog?(_conn), do: false
enddefmodule Router do
use Plug.Routerplug Plug.AccessLog,
dontlog: &LogFilter.dontlog?/1,
format: :clf,
file: "/path/to/your/logs/access.log"
end
```If the function you pass to the plug returns `true` the request will not be logged.
### Logging Functions
To have the parsed log message sent to a logging function instead of writing it to a file you can configure a logging function:
```elixir
defmodule InfoLogger do
def log(msg), do: Logger.log(:info, msg)
enddefmodule Router do
use Plug.Routerplug Plug.AccessLog,
format: :clf,
fun: &InfoLogger.log/1
end
```If a logging function is configured the configured file (if any) will be ignored.
## Log Format
The default format is [CLF](http://en.wikipedia.org/wiki/Common_Log_Format).
### Available formats
Besides a self defined format you can use one of the predefined aliases:
```
:agent
> %{User-Agent}i
> curl/7.35.0:clf
> %h %l %u %t "%r" %>s %b
> 127.0.0.1 - - [10/Jan/2015:14:46:18 +0100] "GET / HTTP/1.1" 200 31337:clf_vhost
> %v %h %l %u %t "%r" %>s %b
> www.example.com 127.0.0.1 - - [10/Jan/2015:14:46:18 +0100] "GET / HTTP/1.1" 200 31337:combined
> %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"
> 127.0.0.1 - - [22/Jan/2015:19:33:58 +0100] "GET / HTTP/1.1" 200 2 "http://www.example.com/previous_page" "curl/7.35.0":combined_vhost
> %v %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"
> www.example.com 127.0.0.1 - - [22/Jan/2015:19:33:58 +0100] "GET / HTTP/1.1" 200 2 "http://www.example.com/previous_page" "curl/7.35.0":referer
> %{Referer}i -> %U
> http://www.example.com/previous_page -> /
```For more details about each formatting token and potential modifications please refer to the `Plug.AccessLog.DefaultFormatter` module.
## Benchmarking
A small utility script is provided to check how long it might take to process requests and write the log messages to your disk:
```shell
mix run utils/bench.exs
```This call will send of a total of 10k requests and wait for them to be written to the disk.
Looking at the data written to `utils/bench.log` might give a hint at what overhead the log writing is introducing. As with all "benchmarks" of any kind: take the measurements with a pinch of salt and run them in dozens of different conditions yourself.
## License
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)