Open cch1 opened 5 months ago
Hi,
It is possible to create separate loggers and use them independently if you use the log function µ/log*
instead of the convenience macro µ/log
and µ/trace
.
In practice, this is not convenient at all, as you have to propagate down the current logger in every single function that might want to use it. Like you suggested, one alternative is to use dynamic binding which is also supported. However it becomes less effective when tasks spanning multiple threads.
The recommended approach is to use just one logger and then have two publishers that will publish only the events on the subsystem you want.
;; add the system as a key-value pair or local-context
(μ/log :order-completed, :system :myapp/system-A, :order-id order-id )
;; start independent publishers
(u/start-publisher!
{:type :simple-file
:filename "/tmp/mulog/system-A-events.log"
:transform
(fn [events]
(filter #(= (:system %) :myapp/system-A)) events))})
(u/start-publisher!
{:type :simple-file
:filename "/tmp/mulog/system-B-events.log"
:transform
(fn [events]
(filter #(= (:system %) :myapp/system-B)) events))})
The value :myapp/system-A
might be injected via a dynamic var in your code, or passed down as parameter, or injected as TheadLocal via the µ/with-context
. This approach is so much simpler to handle.
Anyway, I will keep this ticket open, and evaluate if it is worthy to extend the logging macros to accept the logger explicitly.
Thanks for the assessment -I agree with it without exception.
I will add that in my practice, it's common to have development and test systems running concurrently -and even occasionally a production system (particularly if one is not diligently shutting them down). Having all the log statements include a differentiating key/value combo and the configured publishers filter on that would be annoying and further diverge production from test/development. I am soundly opposed to having the running subsystems (everything that logs and the publishers) be aware of what system they are running in.
My current solution is to use a wrapper around µ/log*
that requires the logger (ring buffer) as a parameter but otherwise mimics the signature of µ/log
Each system gets a dedicated buffer and the only prod/dev/test differentiator is where the publishers send the log.
I occasionally have two independent "systems" operating concurrently in one JVM. I have found that mulog events from system A will randomly appear in the output of the publisher of system B and vice-versa. This is the inevitable problem with the stateful log buffer being held in a global (dynamic) var.
With careful use of
binding
andbound-fn
it might be possible to overcome this problem but the generally accepted standard for Clojure libs and SPIs is to at least allow for explicit configuration and to only fall back to global mutable state when explicit stateful parameters are not supplied. This appears to have been taken into consideration in thestart-publisher!
function which has an arity to explicitly supply the buffer to be published.Would it be possible for mulog to expose an explicit interface to
log
that does not rely on global mutable state?