distefam

distefam

Configuring Logger Handlers at Runtime

I am trying to use the third-party schlagert/syslog erlang library for sending logs to Papertrail and running into some inconsistencies and issues around configuration.

If I configure it as follows, it sends logs to Papertrail correctly:

config :syslog,
  protocol: {:rfc5424, :udp},
  dest_host: ~c"my.papertrail.url,
  dest_port: my_papertrail_port,
  facility: :local0,
  app_name: "my_app_name",
  formatter: Logger.Formatter.new(
    format: "$message $metadata\n", metadata: [...]
  )

But, if I follow the documented instructions for integrating Erlang/OTP Handlers and use the exact same configuration I am able to see the correct handler and configuration when running iex> :logger.get_handler_config(), but no logs are sent to Papertrail.

config :my_app, :logger, [
  {:handler, :papertrail, :syslog_logger_h,
   %{
     config: %{
       protocol: {:rfc5424, :udp},
       dest_host: ~c"my.papertrail.url",
       dest_port: my_papertrail_port,
       facility: :local0,
       app_name: "my_app"
     },
     formatter:
          Logger.Formatter.new(
            format: "$message $metadata\n",
            metadata: [:event, :result, :context]
          )
   }}
]

Note, when I do it this recommended way, I do call Logger.add_handlers(:my_app) from my Application.start/2 function. Also, when I do this I have two handlers from syslog, one called :syslog and the other called :papertrail. If I try to use the above code but replace :papertrail with :syslog it fails with an error saying that handler was already added.

I wouldn’t mind doing things the way that works, but the issue is that I have to hard-code the values for dest_host and dest_port in my config.exs module. If I omit those (or set them to dummy values) and then call :logger.update_handler_config in my Application.start/2 function it shows the updated handler config but doesn’t actually seem to affect what :syslog does as I don’t see any logs in Papertrail. So, there doesn’t seem to be any good way to configure this custom handler at runtime. I’ve tried calling :logger.update_handler_config for both :syslog and :papertrail and neither works.

One hypothesis I have is that :syslog is started by Mix because it’s in my deps function. When starting, it looks into my config.exs file for values and initializes with these values. It’s outside of my application in a way so calling :logger.update_handler_config doesn’t work. But, another oddity is that if I call :logger.update_handler_config and just change the formatter: configuration, that does take effect. So, it seems that I can’t update some configuration values while others do work.

I’m at a loss. All I want to do is send logs to Papertrail and it’s turning out to be far more complex than anticipated.

First Post!

MRdotB

MRdotB

I ran some tests and then reviewed the source code. It appears that it is not possible to specify dest_host and dest_port per handler.

I’m using this listener as my syslog:

socat -u UDP-RECV:12345,fork SYSTEM:'tee -a /tmp/syslog.txt'

Logging in iex with the following configuration sends two logs to my syslog.txt:

# Disable the default logger
config :syslog, [{:logger, []}]

# It seems only this dest_port is read from the config
config :syslog, dest_port: 12345

config :syslog_test, :logger, [
  {:handler, :one, :syslog_logger_h, %{
     config: %{
       # This is ignored
       dest_port: 123456
     }
   }},
  {:handler, :two, :syslog_logger_h, %{
     config: %{
       # This is ignored
       dest_port: 123456
     }
   }}
]
iex> require Logger
iex> Logger.add_handlers(:syslog_test)
iex> Logger.info("hello")

When I run Logger.info("hello"), two messages are sent via UDP to my listener on port 12345, appending two hello logs to my file.

Looking at the logger handler code in the library here:
https://github.com/schlagert/syslog/blob/master/src/syslog_logger_h.erl#L253

Following the logs, you’ll see that the syslog_logger is a gen_server responsible for sending the log from all handlers over UDP.
https://github.com/schlagert/syslog/blob/master/src/syslog_logger.erl

This gen_server is launched at startup, and its state contains the dest_port and dest_host, which cannot be changed at runtime.

The library would need to be modified to support different dest_host and dest_port per handler.

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

Other popular topics Top

mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement