Skip to content

Logger.add_backend/1 doesn't outlast Logger.BackendSupervisor #378

@garthk

Description

@garthk

Environment

  • Elixir version (elixir -v): 1.9.4
  • Erlang/OTP version (erl): 22
  • Sentry version (mix deps): 7.2.0
  • Operating system: any

Description

README advises:

To set this up, add {:ok, _} = Logger.add_backend(Sentry.LoggerBackend) to your application's start function.

… but Logger.add_backend/2 says:

Backends added by this function are not persisted. Therefore if the Logger application or supervision tree is restarted, the backend won't be available. If you need this guarantee, then configure the backend via the application environment.

Let's try that out:

$ iex -S mix
iex(1)> Logger |> Process.whereis() |> :sys.get_state()
[
  {Logger.Backends.Console, false,
   %Logger.Backends.Console{
…

iex(2)> Logger.add_backend(Sentry.LoggerBackend)       
{:ok, #PID<0.1405.0>}

iex(3)> Logger |> Process.whereis() |> :sys.get_state()
[
  {Sentry.LoggerBackend, false,
   %Sentry.LoggerBackend{
     ignore_plug: true,
     include_logger_metadata: false,
     level: nil
   }},
…

iex(4)> Logger.BackendSupervisor |> Process.whereis() |> Process.exit(:kill)    
true
 
16:45:20.008 [error] GenServer #PID<0.1405.0> terminating
** (stop) killed
Last message: {:EXIT, #PID<0.1169.0>, :killed}
State: {Logger, Sentry.LoggerBackend}
 
16:45:20.008 [error] GenServer #PID<0.1170.0> terminating
** (stop) killed
Last message: {:EXIT, #PID<0.1169.0>, :killed}
State: {Logger, Logger.Backends.Console}

iex(14)> Logger |> Process.whereis() |> :sys.get_state()                         
[
  {Logger.Backends.Console, false,
   %Logger.Backends.Console{
…

Uh oh. The Elixir docs are right: Sentry.LoggerBackend is gone. (The same happens if you call Logger.add_backend/1 from MyApp.start/2 rather than the iex prompt.)

If we apply the docs' advice to configure the backend via the application environment e.g. through config/config.exs

config :logger,
  backends: [:console, Sentry.LoggerBackend]

config :logger, Sentry.LoggerBackend,
  # non-default so we can see it made it
  include_logger_metadata: true

… and check things out again in iex:

$ iex -S mix
iex(1)> Logger |> Process.whereis() |> :sys.get_state()
[
  {Sentry.LoggerBackend, false,
   %Sentry.LoggerBackend{
     ignore_plug: true,
     include_logger_metadata: true,
     level: nil
   }},
…

iex(2)> Logger.BackendSupervisor |> Process.whereis() |> Process.exit(:kill)
true

05:47:53.592 [error] GenServer #PID<0.1170.0> terminating
** (stop) killed
Last message: {:EXIT, #PID<0.1169.0>, :killed}
State: {Logger, Logger.Backends.Console}
        function=error_info/7 module=gen_server line=889 file=gen_server.erl pid=<0.1170.0> 
05:47:53.592 [error] GenServer #PID<0.1171.0> terminating
** (stop) killed
Last message: {:EXIT, #PID<0.1169.0>, :killed}
State: {Logger, Sentry.LoggerBackend}
        function=error_info/7 module=gen_server line=889 file=gen_server.erl pid=<0.1171.0> 

iex(3)> Logger |> Process.whereis() |> :sys.get_state()                     
[
  {Sentry.LoggerBackend, false,
   %Sentry.LoggerBackend{
     ignore_plug: true,
     include_logger_metadata: true,
     level: nil
   }},
…

That'll do!

I also found Logger.BackendSupervisor |> Process.whereis() |> :sys.get_state() helpful while checking this out.

Expected Behavior

Installed as advised, Sentry.LoggerBackend survives a restart of Logger.BackendSupervisor.

Actual Behavior

Installed as advised, Sentry.LoggerBackend does not survive a restart of Logger.BackendSupervisor. I wouldn't worry, much, except we've killed it before and will no doubt kill it again.

Steps to Reproduce

Logger.BackendSupervisor |> Process.whereis() |> Process.exit(:kill)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions