@@ -356,10 +356,14 @@ defmodule Logger do
356356 ## Erlang/OTP handlers
357357
358358 Handlers represent the ability to integrate into the logging system to
359- handle each logged message/event. Elixir's Logger automatically sets a
360- default handler based on Erlang's `:logger_std_h`, which you can configure
361- using the `:default_handler` boot configuration outlined above. You may
362- also attach additional handlers when you boot your application.
359+ handle each logged message/event.
360+
361+ ### Built-in handlers
362+
363+ Elixir's Logger automatically sets a default handler based on Erlang's
364+ `:logger_std_h`, which you can configure using the `:default_handler` boot
365+ configuration outlined above. You may also attach additional handlers
366+ when you boot your application.
363367
364368 To do so, you must list a series of handlers under the `:logger` key
365369 of your application configuration. For example, to setup an additional
@@ -381,24 +385,47 @@ defmodule Logger do
381385
382386 Each handler has the shape `{:handler, name, handler_module, config_map}`.
383387 Once defined, a handler can be explicitly attached in your
384- `c:Application.start/2` callback with `add_handlers/1`:
388+ `c:Application.start/2` callback, typically in `lib/my_app/application.ex`
389+ with `Logger.add_handlers/1`:
385390
386391 Logger.add_handlers(:my_app)
387392
388393 You can also add, remove, and update handlers at runtime with the help
389394 of the Erlang's [`:logger`](`:logger`) module.
390395
396+ ### Custom handlers
397+
391398 You may also develop your own handlers. Handlers run in the same
392399 process as the process logging the message/event. This gives developers
393400 flexibility but they should avoid performing any long running action in
394401 such handlers, as it may slow down the action being executed considerably.
395- At the moment, there is no built-in overload protection for Erlang handlers,
396- so it is your responsibility to implement it.
397402
398- Alternatively, you can use the
399- [`:logger_backends`](https://github.com/elixir-lang/logger_backends) project.
400- It sets up a log handler with overload protection and allows incoming events
401- to be dispatched to multiple backends.
403+ You must implement the [`:logger_handler`](`:logger_handler`) behaviour
404+ to define custom handlers, which has only one required callback:
405+
406+ defmodule MyApp.CustomHandler do
407+ @behaviour :logger_handler
408+
409+ def log(event, _config) do
410+ IO.inspect(event)
411+ end
412+ end
413+
414+ Then you must define the handler in your configuration file:
415+
416+ config :my_app, :logger, [
417+ {:handler, :my_handler, MyApp.CustomHandler, _config = %{}}
418+ ]
419+
420+ And attach it on your application start using `Logger.add_handlers/1`,
421+ as in the previous section.
422+
423+ Note there is no built-in overload protection for Erlang handlers,
424+ so it is your responsibility to implement it if necessary. One alternative is
425+ to use the [`:logger_backends`](https://github.com/elixir-lang/logger_backends)
426+ project, which sets up a log handler with overload protection and allows
427+ incoming events to be dispatched to multiple backends, although one must be
428+ careful for backends to not become a bottleneck during logging.
402429
403430 ### Filtering
404431
0 commit comments