Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Used by "mix format"
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
line_length: 120
]
31 changes: 26 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
/_build
/cover
/deps
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
plug_logger_json-*.tar

# Temporary files for e.g. tests.
/tmp

# Misc.
.local.plt
doc/
.elixir_ls
33 changes: 19 additions & 14 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
# Changelog

## Master
All notable changes to this project will be documented in this file.

## 0.7.0
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## v0.7.0 - 2019-04-22
* Updated Readme
* Updated Dependencies
* Ran Formatter
* Updated Dependencies
* Ran Formatter
* Fixed warnings up to 1.8
* Support nested param filtering

## 0.6.0
* Extra configration that allows control of logging debug fields.
## v0.6.0 - 2017-12-26
* Extra configuration that allows control of logging debug fields.
* Allow built-in logging keys to be suppressed
* Add Elixir 1.5.3 official support
* Add Erlang/OTP 20.1 official support
* Update dev & test dependencies

## 0.5.0
* Extra attributes configration that allows for logging custom metrics
## v0.5.0 - 2017-08-21
* Extra attributes configuration that allows for logging custom metrics
* Add Elixir 1.5.1
* Add Erlang/OTP 20
* Add Erlang/OTP 19.3 to test suite

## v0.4.0
## v0.4.0 - 2017-03-18
* Breaking Changes!
* Log errors with logger level `error` instead of `info`
* Change `status` field to an integer type instead of string
* Drop official support of Elixir 1.2 and OTP 18
* Add support for Elixir 1.4 and OTP 19.1 & 19.2
* Update depedencies
* Update dependencies
* Fix dialyzer warnings

## v0.3.1
* Update depedencies
## v0.3.1 - 2017-01-05
* Update dependencies
* Fix Elixir 1.4 warnings

## v0.3.0
## v0.3.0 - 2016-11-22
* Breaking Changes!
* Drop the `fastly_duration` log value
* Add the ability to change verbosity. Log levels warn/debug will return everything from 0.2 minus fastly_duration. Log levels info/error will return a subset of warn/debug that is missing params, client_ip, & client_version.

## v0.2
## v0.2.0 - 2016-10-26
* Add support for error logging tagged with the request id. Errors now are bunched up as a single JSON message in addition to the standard output for easier parsing of errors and matching requests to the resulting error.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2016 Bleacher Report
Copyright (c) 2016 Bleacher Report

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
109 changes: 66 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
# PlugLoggerJson
[![Hex pm](http://img.shields.io/hexpm/v/plug_logger_json.svg?style=flat)](https://hex.pm/packages/plug_logger_json)
# Plug Logger JSON

[![Build Status](https://travis-ci.org/bleacherreport/plug_logger_json.svg?branch=master)](https://travis-ci.org/bleacherreport/plug_logger_json)
[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://github.com/bleacherreport/plug_logger_json/blob/master/LICENSE)
[![Module Version](https://img.shields.io/hexpm/v/plug_logger_json.svg)](https://hex.pm/packages/plug_logger_json)
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/plug_logger_json/)
[![Total Download](https://img.shields.io/hexpm/dt/plug_logger_json.svg)](https://hex.pm/packages/plug_logger_json)
[![License](https://img.shields.io/hexpm/l/plug_logger_json.svg)](https://github.com/bleacherreport/plug_logger_json/blob/master/LICENSE)
[![Last Updated](https://img.shields.io/github/last-commit/bleacherreport/plug_logger_json.svg)](https://github.com/bleacherreport/plug_logger_json/commits/master)


A comprehensive JSON logger Plug.

## Dependencies

* Plug
* Poison
* `Plug`
* `Poison`

## Elixir & Erlang Support

The support policy is to support the last 2 major versions of Erlang and the three last minor versions of Elixir.

## Installation

1. add plug_logger_json to your list of dependencies in `mix.exs`:
1. Add `:plug_logger_json` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[{:plug_logger_json, "~> 0.7.0"}]
[
{:plug_logger_json, "~> 0.7.0"}
]
end
```

2. ensure plug_logger_json is started before your application (Skip if using Elixir 1.4 or greater):
2. Ensure `:plug_logger_json` is started before your application (Skip if using Elixir 1.4 or greater):

```elixir
def application do
Expand Down Expand Up @@ -64,53 +71,55 @@ config :logger, :console,

Do the following:

* update deps in `mix.exs` with the following:
* Update deps in `mix.exs` with the following:

```elixir
def deps do
[{:logger_file_backend, "~> 0.0.10"}]
end
```
```elixir
def deps do
[
{:logger_file_backend, "~> 0.0.10"}
]
end
```

* add to your `config/config.exs` or `config/env_name.exs`:
* Add to your `config/config.exs` or `config/env_name.exs`:

```elixir
config :logger,
format: "$message\n",
backends: [{LoggerFileBackend, :log_file}, :console]
```elixir
config :logger,
format: "$message\n",
backends: [{LoggerFileBackend, :log_file}, :console]

config :logger, :log_file,
format: "$message\n",
level: :info,
metadata: [:request_id],
path: "log/my_pipeline.log"
```
config :logger, :log_file,
format: "$message\n",
level: :info,
metadata: [:request_id],
path: "log/my_pipeline.log"
```

* ensure you are using `Plug.Parsers` (Phoenix adds this to `endpoint.ex` by default) to parse params as well as request body:
* Ensure you are using `Plug.Parsers` (Phoenix adds this to `endpoint.ex` by default) to parse params as well as request body:

```elixir
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Poison
```
```elixir
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Poison
```

## Error Logging

In `router.ex` of your Phoenix project or in your plug pipeline:

* add `require Logger`,
* add `use Plug.ErrorHandler`,
* add the following two private functions:
* Add `require Logger`,
* Add `use Plug.ErrorHandler`,
* Add the following two private functions:

```elixir
defp handle_errors(%Plug.Conn{status: 500} = conn, %{kind: kind, reason: reason, stack: stacktrace}) do
Plug.LoggerJSON.log_error(kind, reason, stacktrace)
send_resp(conn, 500, Poison.encode!(%{errors: %{detail: "Internal server error"}}))
end
```elixir
defp handle_errors(%Plug.Conn{status: 500} = conn, %{kind: kind, reason: reason, stack: stacktrace}) do
Plug.LoggerJSON.log_error(kind, reason, stacktrace)
send_resp(conn, 500, Poison.encode!(%{errors: %{detail: "Internal server error"}}))
end

defp handle_errors(_, _), do: nil
```
defp handle_errors(_, _), do: nil
```

## Extra Attributes

Expand Down Expand Up @@ -178,6 +187,20 @@ Before submitting your pull request, please run:
* `mix credo --strict`,
* `mix coveralls`,
* `mix dialyzer`,
* update changelog.
* Update changelog.

Please squash your pull request's commits into a single commit with a message and detailed description explaining the commit.

## Copyright and License

Copyright (c) 2016 Bleacher Report

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
46 changes: 29 additions & 17 deletions lib/plug/logger_json.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defmodule Plug.LoggerJSON do
@moduledoc """
A plug for logging basic request information in the format:

```json
{
"api_version": "N/A"
Expand All @@ -22,33 +23,37 @@ defmodule Plug.LoggerJSON do
```

To use it, just plug it into the desired module.
plug Plug.LoggerJSON, log: :debug

plug Plug.LoggerJSON, log: :debug

## Options

* `:log` - The log level at which this plug should log its request info.
Default is `:info`.
Default is `:info`.

* `:extra_attributes_fn` - Function to call with `conn` to add additional
fields to the requests. Default is `nil`. Please see "Extra Fields" section
for more information.
fields to the requests. Default is `nil`. Please see "Extra Fields" section
for more information.

## Extra Fields

Additional data can be logged alongside the request by specifying a function
to call which returns a map:

def extra_attributes(conn) do
map = %{
"user_id" => get_in(conn.assigns, [:user, :user_id]),
"other_id" => get_in(conn.private, [:private_resource, :id]),
"should_not_appear" => conn.private[:does_not_exist]
}
def extra_attributes(conn) do
map = %{
"user_id" => get_in(conn.assigns, [:user, :user_id]),
"other_id" => get_in(conn.private, [:private_resource, :id]),
"should_not_appear" => conn.private[:does_not_exist]
}

map
|> Enum.filter(&(&1 !== nil))
|> Enum.into(%{})
end
map
|> Enum.filter(&(&1 !== nil))
|> Enum.into(%{})
end

plug Plug.LoggerJSON, log: Logger.level,
extra_attributes_fn: &MyPlug.extra_attributes/1
plug Plug.LoggerJSON, log: Logger.level,
extra_attributes_fn: &MyPlug.extra_attributes/1

In this example, the `:user_id` is retrieved from `conn.assigns.user.user_id`
and added to the log if it exists. In the example, any values that are `nil`
Expand Down Expand Up @@ -237,7 +242,14 @@ defmodule Plug.LoggerJSON do
"-" <>
zero_pad(month, 2) <>
"-" <>
zero_pad(day, 2) <> "T" <> zero_pad(hour, 2) <> ":" <> zero_pad(minute, 2) <> ":" <> zero_pad(second, 2) <> "Z"
zero_pad(day, 2) <>
"T" <>
zero_pad(hour, 2) <>
":" <>
zero_pad(minute, 2) <>
":" <>
zero_pad(second, 2) <>
"Z"
end

@spec phoenix_attributes(map()) :: map()
Expand Down
Loading