Hello,
when do you use one over the other? I can’t really find docs about this. The following just prints both data structures, making me wonder why there are two different ways of doing it. The only difference I can see is that you can set context on a per-Fiber basis while emit sends volatile data.
require "log"
Log.with_context(x: { y: 1 }) do
Log.error do |emitter|
emitter.emit("...", a: { b: 2 })
end
end
While Crystal’s docs are usually fantastic, I have found the logging module hard to understand. Personally I would have loved more elaborate infos on the various building blocks. They are scattered among the different submodules and it’s rarely clear to me when to use what.
As a use case, I’m trying to build a class where the logging calls of all instance methods will be prefixed with the value of a certain instance property. It doesn’t seem like the Log module supports that, so I guess I have to build a custom log method for my class which I then call. But I wonder which of the two syntaxes I should use.
As an aside, I also wonder: If I do
Log.trace { my_large_var.to_json }
this appears to create a heap var, as the log backend abstraction is indifferent to the consumer, aka you cannot access the IO here. Logging in particular is a use case of perhaps wanting to write to a file or in memory WAL thousands of times per second. This could be ugly wrt performance, it seems to me. Even the official performance guide recommends to work on IO instead of string operations. Am I missing something? Or should we perhaps just always instead do
Log.trace &.emit(my_large_var.to_json)
?