Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

µ/log and µ/trace should accept a logger #121

Open
cch1 opened this issue Apr 11, 2024 · 2 comments
Open

µ/log and µ/trace should accept a logger #121

cch1 opened this issue Apr 11, 2024 · 2 comments
Assignees
Labels
enhancement New feature or request

Comments

@cch1
Copy link

cch1 commented Apr 11, 2024

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 and bound-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 the start-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?

@BrunoBonacci
Copy link
Owner

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.

@BrunoBonacci BrunoBonacci self-assigned this Apr 12, 2024
@BrunoBonacci BrunoBonacci changed the title Global Mutable State µ/log and µ/trace should accept a logger Apr 12, 2024
@BrunoBonacci BrunoBonacci added the enhancement New feature or request label Apr 12, 2024
@cch1
Copy link
Author

cch1 commented Apr 12, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants