Skip to content

Commit 09f8164

Browse files
committed
Do not crash when Plug is not added to project dependencies
Closes #118
1 parent be34c26 commit 09f8164

File tree

6 files changed

+103
-101
lines changed

6 files changed

+103
-101
lines changed

lib/logger_json/formatters/basic.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ defmodule LoggerJSON.Formatters.Basic do
1515
}
1616
"""
1717
import Jason.Helpers, only: [json_map: 1]
18-
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, Plug, RedactorEncoder}
18+
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, RedactorEncoder}
1919

2020
@behaviour LoggerJSON.Formatter
2121

@@ -83,8 +83,8 @@ defmodule LoggerJSON.Formatters.Basic do
8383
),
8484
client:
8585
json_map(
86-
user_agent: get_header(conn, "user-agent"),
87-
ip: remote_ip(conn)
86+
user_agent: LoggerJSON.Formatter.Plug.get_header(conn, "user-agent"),
87+
ip: LoggerJSON.Formatter.Plug.remote_ip(conn)
8888
)
8989
)
9090
end

lib/logger_json/formatters/datadog.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ defmodule LoggerJSON.Formatters.Datadog do
4242
}
4343
"""
4444
import Jason.Helpers, only: [json_map: 1]
45-
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, Code, Plug, RedactorEncoder}
45+
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, Code, RedactorEncoder}
4646

4747
@behaviour LoggerJSON.Formatter
4848

@@ -197,9 +197,9 @@ defmodule LoggerJSON.Formatters.Datadog do
197197
if Code.ensure_loaded?(Plug.Conn) do
198198
defp format_http_request(%{conn: %Plug.Conn{} = conn} = meta) do
199199
request_url = Plug.Conn.request_url(conn)
200-
user_agent = get_header(conn, "user-agent")
201-
remote_ip = remote_ip(conn)
202-
referer = get_header(conn, "referer")
200+
user_agent = LoggerJSON.Formatter.Plug.get_header(conn, "user-agent")
201+
remote_ip = LoggerJSON.Formatter.Plug.remote_ip(conn)
202+
referer = LoggerJSON.Formatter.Plug.get_header(conn, "referer")
203203

204204
%{
205205
http:

lib/logger_json/formatters/elastic.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ defmodule LoggerJSON.Formatters.Elastic do
9797
```
9898
"""
9999
import Jason.Helpers, only: [json_map: 1]
100-
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, Plug, RedactorEncoder}
100+
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, RedactorEncoder}
101101

102102
@behaviour LoggerJSON.Formatter
103103

@@ -230,13 +230,13 @@ defmodule LoggerJSON.Formatters.Elastic do
230230
# - user_agent.original: https://www.elastic.co/guide/en/ecs/8.11/ecs-user_agent.html
231231
defp format_http_request(%{conn: %Plug.Conn{} = conn}) do
232232
json_map(
233-
"client.ip": remote_ip(conn),
233+
"client.ip": LoggerJSON.Formatter.Plug.remote_ip(conn),
234234
"http.version": Plug.Conn.get_http_protocol(conn),
235235
"http.request.method": conn.method,
236-
"http.request.referrer": get_header(conn, "referer"),
236+
"http.request.referrer": LoggerJSON.Formatter.Plug.get_header(conn, "referer"),
237237
"http.response.status_code": conn.status,
238238
"url.path": conn.request_path,
239-
"user_agent.original": get_header(conn, "user-agent")
239+
"user_agent.original": LoggerJSON.Formatter.Plug.get_header(conn, "user-agent")
240240
)
241241
end
242242
end

lib/logger_json/formatters/google_cloud.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ defmodule LoggerJSON.Formatters.GoogleCloud do
8989
}
9090
"""
9191
import Jason.Helpers, only: [json_map: 1]
92-
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, Code, Plug, RedactorEncoder}
92+
import LoggerJSON.Formatter.{MapBuilder, DateTime, Message, Metadata, Code, RedactorEncoder}
9393

9494
@behaviour LoggerJSON.Formatter
9595

@@ -224,9 +224,9 @@ defmodule LoggerJSON.Formatters.GoogleCloud do
224224
request_method = conn.method |> to_string() |> String.upcase()
225225
request_url = Plug.Conn.request_url(conn)
226226
status = conn.status
227-
user_agent = get_header(conn, "user-agent")
228-
remote_ip = remote_ip(conn)
229-
referer = get_header(conn, "referer")
227+
user_agent = LoggerJSON.Formatter.Plug.get_header(conn, "user-agent")
228+
remote_ip = LoggerJSON.Formatter.Plug.remote_ip(conn)
229+
referer = LoggerJSON.Formatter.Plug.get_header(conn, "referer")
230230

231231
json_map(
232232
protocol: Plug.Conn.get_http_protocol(conn),

lib/logger_json/plug.ex

Lines changed: 87 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,109 @@
1-
defmodule LoggerJSON.Plug do
2-
@moduledoc """
3-
A telemetry handler that logs request information in JSON format.
1+
if Code.ensure_loaded?(Plug) do
2+
defmodule LoggerJSON.Plug do
3+
@moduledoc """
4+
A telemetry handler that logs request information in JSON format.
45
5-
This module is not recommended to be used in production, as it can be
6-
costly to log every single database query.
7-
"""
8-
require Logger
6+
This module is not recommended to be used in production, as it can be
7+
costly to log every single database query.
8+
"""
9+
require Logger
910

10-
@doc """
11-
Attaches the telemetry handler to the given event.
11+
@doc """
12+
Attaches the telemetry handler to the given event.
1213
13-
### Available options
14+
### Available options
1415
15-
* `:level` - log level which is used to log requests. Defaults to `:info`.
16+
* `:level` - log level which is used to log requests. Defaults to `:info`.
1617
17-
### Dynamic log level
18+
### Dynamic log level
1819
19-
In some cases you may wish to set the log level dynamically
20-
on a per-query basis. To do so, set the `:level` option to
21-
a tuple, `{Mod, Fun, Args}`. The query and map of time measures
22-
will be prepended to the provided list of arguments.
20+
In some cases you may wish to set the log level dynamically
21+
on a per-query basis. To do so, set the `:level` option to
22+
a tuple, `{Mod, Fun, Args}`. The query and map of time measures
23+
will be prepended to the provided list of arguments.
2324
24-
When invoked, your function must return a
25-
[`Logger.level()`](`t:Logger.level()/0`) or `false` to
26-
disable logging for the request.
25+
When invoked, your function must return a
26+
[`Logger.level()`](`t:Logger.level()/0`) or `false` to
27+
disable logging for the request.
2728
28-
### Examples
29+
### Examples
2930
30-
Attaching the telemetry handler to the `MyApp.Repo` events with the `:info` log level:
31+
Attaching the telemetry handler to the `MyApp.Repo` events with the `:info` log level:
3132
32-
# in the endpoint
33-
plug Plug.Telemetry, event_prefix: [:myapp, :plug]
33+
# in the endpoint
34+
plug Plug.Telemetry, event_prefix: [:myapp, :plug]
3435
35-
# in your application.ex
36-
LoggerJSON.Plug.attach("logger-json-requests", [:myapp, :plug, :stop], :info)
36+
# in your application.ex
37+
LoggerJSON.Plug.attach("logger-json-requests", [:myapp, :plug, :stop], :info)
3738
38-
To make plug broadcast those events see [`Plug.Telemetry`](https://hexdocs.pm/plug/Plug.Telemetry.html) documentation.
39+
To make plug broadcast those events see [`Plug.Telemetry`](https://hexdocs.pm/plug/Plug.Telemetry.html) documentation.
3940
40-
You can also attach to the `[:phoenix, :endpoint, :stop]` event to log request latency from Phoenix endpoints:
41+
You can also attach to the `[:phoenix, :endpoint, :stop]` event to log request latency from Phoenix endpoints:
4142
42-
LoggerJSON.Plug.attach("logger-json-phoenix-requests", [:phoenix, :endpoint, :stop], :info)
43-
"""
44-
def attach(name, event, level) do
45-
:telemetry.attach(name, event, &__MODULE__.telemetry_logging_handler/4, level)
46-
end
43+
LoggerJSON.Plug.attach("logger-json-phoenix-requests", [:phoenix, :endpoint, :stop], :info)
44+
"""
45+
def attach(name, event, level) do
46+
:telemetry.attach(name, event, &__MODULE__.telemetry_logging_handler/4, level)
47+
end
4748

48-
@doc """
49-
A telemetry handler that logs requests in a structured format.
50-
"""
51-
@spec telemetry_logging_handler(
52-
event_name :: [atom()],
53-
query_time :: %{duration: non_neg_integer()},
54-
metadata :: %{conn: Plug.Conn.t()},
55-
level :: Logger.level() | {module :: module(), function :: atom(), arguments :: [term()]} | false
56-
) :: :ok
57-
def telemetry_logging_handler(_event_name, %{duration: duration}, %{conn: conn}, level) do
58-
duration = System.convert_time_unit(duration, :native, :microsecond)
59-
60-
if level = level(level, conn) do
61-
Logger.log(
62-
level,
63-
fn ->
64-
%{
65-
method: method,
66-
request_path: request_path,
67-
state: state,
68-
status: status
69-
} = conn
70-
71-
[
72-
method,
73-
?\s,
74-
request_path,
75-
?\s,
76-
"[",
77-
connection_type(state),
78-
?\s,
79-
status(status),
80-
"in ",
81-
duration(duration),
82-
"]"
83-
]
84-
end,
85-
conn: conn,
86-
duration_μs: duration
87-
)
49+
@doc """
50+
A telemetry handler that logs requests in a structured format.
51+
"""
52+
@spec telemetry_logging_handler(
53+
event_name :: [atom()],
54+
query_time :: %{duration: non_neg_integer()},
55+
metadata :: %{conn: Plug.Conn.t()},
56+
level :: Logger.level() | {module :: module(), function :: atom(), arguments :: [term()]} | false
57+
) :: :ok
58+
def telemetry_logging_handler(_event_name, %{duration: duration}, %{conn: conn}, level) do
59+
duration = System.convert_time_unit(duration, :native, :microsecond)
60+
61+
if level = level(level, conn) do
62+
Logger.log(
63+
level,
64+
fn ->
65+
%{
66+
method: method,
67+
request_path: request_path,
68+
state: state,
69+
status: status
70+
} = conn
71+
72+
[
73+
method,
74+
?\s,
75+
request_path,
76+
?\s,
77+
"[",
78+
connection_type(state),
79+
?\s,
80+
status(status),
81+
"in ",
82+
duration(duration),
83+
"]"
84+
]
85+
end,
86+
conn: conn,
87+
duration_μs: duration
88+
)
89+
end
8890
end
89-
end
9091

91-
defp connection_type(:set_chunked), do: "Chunked"
92-
defp connection_type(_), do: "Sent"
92+
defp connection_type(:set_chunked), do: "Chunked"
93+
defp connection_type(_), do: "Sent"
9394

94-
defp status(nil), do: ""
95-
defp status(status), do: [status |> Plug.Conn.Status.code() |> Integer.to_string(), ?\s]
95+
defp status(nil), do: ""
96+
defp status(status), do: [status |> Plug.Conn.Status.code() |> Integer.to_string(), ?\s]
9697

97-
def duration(duration) do
98-
if duration > 1000 do
99-
[duration |> div(1000) |> Integer.to_string(), "ms"]
100-
else
101-
[Integer.to_string(duration), "µs"]
98+
def duration(duration) do
99+
if duration > 1000 do
100+
[duration |> div(1000) |> Integer.to_string(), "ms"]
101+
else
102+
[Integer.to_string(duration), "µs"]
103+
end
102104
end
103-
end
104105

105-
defp level({m, f, a}, conn), do: apply(m, f, [conn | a])
106-
defp level(level, _conn) when is_atom(level), do: level
106+
defp level({m, f, a}, conn), do: apply(m, f, [conn | a])
107+
defp level(level, _conn) when is_atom(level), do: level
108+
end
107109
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule LoggerJSON.Mixfile do
22
use Mix.Project
33

44
@source_url "https://github.com/Nebo15/logger_json"
5-
@version "6.0.0"
5+
@version "6.0.1"
66

77
def project do
88
[

0 commit comments

Comments
 (0)