Disable logging on specific route?

Hey there,

I have an endpoint that’s used to check to see if an instance is up and available (for use with a node balancer). The node balancer will hit this endpoint once a second or so. Obviously that produces a lot of unnecessary log chatter, so I’m trying to figure out how to disable the request logging for this endpoint only.

I noticed that in Phoenix.Controller there’s an option under Plug Pipeline called “log” - but I’m not sure if it’s relevant and how to use it if it is.

Anyone else figured this out before?

7 Likes

I figured it out :slight_smile: thanks to @benwilson512 and others!

The answer is to use pipelines:

  • Remove the Plug.Logger line from the endpoint.ex file.
  • Add a pipeline which doesn’t include the Logger
  • Add plug Plug.Logger to all other pipelines
  • Add pipe_through <pipeline which doesn't include logger> to the scope you don’t want to log.
17 Likes

Hi

I know this post has been a while but I have the same situation like this now.

I have a health_check controller which receives ping every xx secs, and would be ideal the logger to be turned off for it.

But the current phoenix version does not have Plug.Logger in endpoint.ex any more so I don’t where to disable it and then apply it in router.ex via different pipeline.

Anyone has idea?

elixir: 1.9.1
phoenix: 1.4.9

Kind regards
Rain

scope log: false do
  get "/pages/:id", PageController, :show
end

or

get "/pages/:id", PageController, :show, log: false

https://hexdocs.pm/phoenix/Phoenix.Router.html#scope/2
https://hexdocs.pm/phoenix/Phoenix.Router.html#get/4

15 Likes

thank you for you reply, however I cannot get it work as the documentation

> mix phx.new --version
Phoenix v1.4.9

> mix phx.new phx_app
....

and then I open router.ex, tried both

  scope "/", PhxAppWeb, log: false do
    pipe_through :browser

    get "/", PageController, :index
  end

and

  scope "/", PhxAppWeb do
    pipe_through :browser

    get "/", PageController, :index, log: false
  end

still I can see the logs

[info] GET /
[info] Sent 200 in 286µs

Regards

2 Likes

Confirmed. The option on the scope does not work.

And I don’t like the pipeline workaround.

I use this plug:

defmodule HelloWeb.Plug.HealthCheck do
  import Plug.Conn

  def init(opts), do: opts

  def call(%Plug.Conn{request_path: "/healthy"} = conn, _opts) do
    conn
    |> send_resp(200, "")
    |> halt()
  end

  def call(conn, _opts), do: conn
end

And then endpoint.ex uses it like this plug(HelloWeb.Plug.HealthCheck) as the first thing that gets defined. This way it does the least amount of work possible. No controller or route needed and your normal pipeline gets ignored.

Pretty sure I grabbed that snippet and slightly modified it from one of @jola’s blog posts.

8 Likes

it works like charm!! Thanks mate ~

2 Likes

It may be best to mark yours as the best solution as not to confuse others.

This StackOverflow post also provides two alternatives approaches:

Pre-Telemetry (by Wile E. Coyote):

Define a custom plug to replace Plug.Logger in endpoint.ex:

defmodule MyApp.Logger do
  def init(_opts), do: {}

  def call(%{path_info: ["ping"]} = conn, _opts) do
    Plug.Logger.call(conn, :error)
  end
  def call(conn, _opts) do
    Plug.Logger.call(conn, :info)
  end
end

Post-Telemetry (by Ilja Everilä):

Define a custom Telemetry Plug and replace the plug in endpoint.ex:

defmodule MyWeb.Plugs.Telemetry do
  @behaviour Plug

  @impl true
  def init(opts), do: Plug.Telemetry.init(opts)

  @impl true
  def call(%{path_info: ["ping"]} = conn, {start_event, stop_event, opts}) do
    Plug.Telemetry.call(conn, {start_event, stop_event, Keyword.put(opts, :log, :debug)})
  end
  def call(conn, args), do: Plug.Telemetry.call(conn, args)
end
1 Like

I just ran into this. I believe the scope option is not about those GET / and Sent 200 in 286µs logs, it’s about these debug logs you see:

[debug] Processing with PhxDisableLogWeb.PageController.index/2
  Parameters: %{}
  Pipelines: [:browser]

You will notice that the log: false option on scope does disable these log entries.

The other request logs are disabled by adding log: false to the Plug.Telemetry plug (in endpoint.ex), but this then applies to all routes. I am not aware of an approach to disable these on a per request basis (without resorting to your own logging).

1 Like

For anyone that stumbles across this question in the future, I wrote a library to do this exact thing but with any plug GitHub - akoutmos/unplug: Unplug allows you to conditionally execute your Elixir plugs at run-time

Using Unplug, you can provide a predicate module that gets evaluated under the context of the current plug, and you can specify whether you want the attached plug to be executed or not.

5 Likes

This is the best solution for my problem. I just wanted to stop the log spam of /health hits from my PaaS.