Eiji
Questions about Elixir Logger
Hey, I tried to debug how I can catch some things.
I created a new local application by mix new my_logger command.
My config/config.exs:
use Mix.Config
config :logger,
backends: [MyLogger],
handle_otp_reports: true,
handle_sasl_reports: true
and here is my main module:
defmodule MyLogger do
use GenEvent
def init(_) do
{:ok, %{}}
end
def handle_call({:configure, options}, _state) do
{:ok, :ok, %{}}
end
def handle_event({_level, gl, {Logger, _, _, _}}, state) when node(gl) != node() do
{:ok, state}
end
def handle_event({level, group_leader, {Logger, message, {date, time}, details}}, state) do
IO.inspect "catched?"
# stacktrace here ...
{:ok, state}
end
end
at end I run iex -S mix command.
In Interactive Elixir I can see already catched 3 log messages.
It works also when I try to execute an: Logger macros such as info.
I checked what data I could collect and it’s really good.
From here I have some questions:
- I know that
&System.stacktrace/0works only for exceptions. Is there any other way (logger configuration?) to get a stacktrace when message is logged? - Is there any way to catch also all
raise(I mean allow crash, but send info about it toLogger). I already tried set some logger configuration variables like @OvermindDL1 already wrote, but I don’t got a “catched?” message. - Is it possible (by configuration change?) to got passed argument values in stacktrace (optionally only for
Logger), so I could easily reproduce an logged message in user specific situations?
Marked As Solved
OvermindDL1
Unsure about that, worst case you could throw and catch an exception to get a stacktrace… sounds slow though
Any uncaught raise’s or any uncaught exception in general should kill its process and log to :sasl, which you can catch through there. However ‘caught’ exceptions are ‘caught’, thus handled, thus nothing reported, so you will never get a ‘catched’ message of any form, only uncaught exceptions. You’d have to decorate raise with a replacement macro or something to do that I’d think?
Stacktraces do not hold that much information, especially because that information might be gone by the time the exception is thrown if those names end up unused by the point the exception is thrown and, say, garbage collected, so I’m unsure if that would even be possible in all cases. At the very least you should have the information for the current application, module, function name, file name, and line number of a log, beyond that you need to add the extra information yourself (which you could easily add the passed in arguments to by adding them to the process log of metadata by calling something like Logger.metadata([:func_args, [blah, bleep]]) but that will get overwritten of course if calling any other function before that point. If you made a custom function (replace def with your own) then you could decorate a log call as much as you want safely, but you’d have to change your function definitions everywhere that you’d want to log that information. Remember that Elixir is about explicitness, minimize magical stuff. ![]()
I could easily be wrong on much of this, I use Logger to log, I’ve not made my own back-end yet. ^.^
Also Liked
OvermindDL1
You’d have to do it at the call site via a custom log function, it would not work within your logger. Sorry I forgot to say that. :-)[quote=“Eiji, post:3, topic:2237”]
hmm, I would like to catch all raise without try do … rescue … end code.
I do not expect too many mistakes, but I want to catch them all like Pokemons trainer ![]()
[/quote]
Hehe, you should be able to by turning on :sasl and such. Raise’s without try’s will eventually kill the process that it is in, which will be reported by :sasl. If it does not kill the process then there was a try that caught it. ![]()
The pointer honestly probably still exists on the stack itself until the function returns (thus no GC’ing it), but no clue how it would be accessible as for all intents and purposes it is dead at those times after its last use. A custom log function/macro could keep it alive though, but I’m pretty sure that would require a custom def regardless unless you use one of the :after_compile hooks or so…
OvermindDL1
The shell, sadly, does not live on an OTP tree (it lives ‘in’ it, but not managed by it, it is manually managed), so you will not get messages from it, but you will from anything attached to the OTP tree. ![]()
You could easily make a defLog or so macro that people can replaced def with that adds in all kinds of extra useful log metadata or so (and clears it when it exits). ![]()
That, to me, would be quite beautiful. ![]()







