-
Notifications
You must be signed in to change notification settings - Fork 47
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
ClojureScript support? #53
Comments
Hi @filipesilva , At the moment I don't have a ClojureScript use case for it, but I will look into this and come back with a design. For everyone else: please vote the issue if you think that μ/log on ClojureScript would be useful to you. |
Hello Bruno, I'm on my path to pick a log library to use in some of my libraries like Pathom. I love the concepts of mulog, but since my libraries are cljc I can't use mulog with the lack of Clojurescript support. How hard you think would be to give just a minimal implementation for CLJS? I mean, it doesn't need to support any fancy storing mechanism, the first version can have only the What do you think? |
Hi all, There are a number of hurdles to overcome for a ClojureScript implementation, I will expose here my thoughts so that I can gather some feedback from your side. Expected behaviour
For example, assuming I want to trace the execution of (μ/with-context {:order order-id, :user user-id}
(μ/trace ::availability
[:product-id product-id]
(product-availability product-id))) Let's assume that the (process-order)
└── (availability)
├── (warehouse-availability)
├── (shopping-carts)
└── (availability-estimator) If all the functions above are wrapped in a μ/trace call you will be able to see the relationship between the calls and their outcome and duration in a distributed tracing tool (like Zipkin), here is an example: (1) A reasonable assumption would be that if (2) Secondly, every call to In my opinion, the above two requirements are key to make the ClojureScript ChallengesFlakesFlakes are unique identifiers, in a single application context they are monotonic, extremely cheap to create and homomorphic in respect to the ordering in their string representation. Thread-local contextμ/log on the JVM makes used of Thread-local variables to store the local context. A ClojureScript implementation would need a different approach. Event propagationIn order for the μ/log's events generated on the client to end up in the backend publishers and centralised logging systems, the client-side will need to piggyback on a "special" backend endpoint. Propage tracing IDsSimilarly to the previous point, in order for the distributed tracing to work correctly, the client-initiated calls will need to pass tracing headers back to the server application on every interaction. Again, due to the many different ways/libraries which can be adopted on the client-side this challenge isn't easy. SummaryAll the above challenges are fairly easy to solve in a specific context. When a specific set of libraries is defined, it is fairly easy to plug this in. However, provide a general approach that will work on all/most of the commonly used libraries on both: client-side and server-side is not an easy challenge. If you have ideas on how to solve the above challenges, feel free to comment below. I'm interested to see whether there is a common solution that can be adopted. |
Hi @BrunoBonacci, thanks for describing the expectations and hard parts in so much detail. I'll try to provide some input on them. FlakesIf performance is the main consideration here, I don't quite see why it'd be any different than the performance hit of everything else on ClojureScript/Javascript. I scanned https://github.com/BrunoBonacci/mulog/blob/master/mulog-core/java/com/brunobonacci/mulog/core/Flake.java a bit and didn't see anything there that'd make me think it's a problem in Javascript. There is a notable exception though, the nanosecond precision. Don't think it's really possible in the current JS engines. Thread-local contextI think the lack of multithreading on javascript means this is just a matter of storing state as usual. It's possible that a JS app would use web workers, but they share no state and communicate via message passing, so they'd just be another separate client. Event propagation & Propagate tracing IDsI think the problems described in these two sections hinge heavily on the premise of integrated logging between client and server apps, as you described in ClojureScript apps today already use third-party logging services like Amplitude and Posthog. My (rough, maybe ignorant) expectation is that'd I should be able to make a μ/log publisher myself that'd mimic what the JS clients for those services do: collect the logging items, batch them, send them to some configured backend. I think https://github.com/BrunoBonacci/mulog/blob/master/doc/publishers/slack-publisher.md is a good example. This looks like the kind of producer that would be the same in CLJS. I understand that there are concerns about using secrets and auth on CLJS apps, but those problems are outside μ/log (e.g. firebase does just fine with js config, I can configure my server to only accept calls from my official domain, etc). I can also imagine that the integrated logging CLJS producer could just be another producer, meaning the special endpoint you mentioned does not need to be encoded in the CLJS μ/log design but rather deferred to producer implementations. Deferring this integrated producer looks like it'd leave CLJS μ/log aligned with the current CLJ μ/log design. |
One comment on the nanosecond precision, this is doable in the browser, but the accuracy vary from vendor to vendor. In Chrome for example its enabled by default and we can get nano time using |
I think your request is not what Bruno is concerned about. There are 2 parts to mulog, logging and tracing. For just logging data from a browser, sure, you can define an endpoint and shovel the data there. But mulog also provides tracing support. Imagine the scenario where a user clicks a button and you initiate a request to the backend (which is awfully common). You want to end up with a trace like
i.e. the trace that initialized in the browser is the parent trace of your backend trace. In order to achieve that you have to send the backend your client-side trace-id (otherwise the server's If we cut the scope of the request and you only wish to have cljs side logging then I think the task is simpler, since you only need to get |
As for tracing, OpenTelemetry is getting traction and I think sending and reading their standardized headers would enable interop. @BrunoBonacci if you'd choose to use their headers for sending over the tracing context you could let users leverage the ecosystem. You wouldn't need to add support for all the http libraries, just serialize the context into a clojure map of their http headers and let the users plug those headers into their requests. |
@BrunoBonacci - for the
Let me know your thoughts, super interested in having a cljs implementation (without which it's not quite usable for certain classes of projects). |
Hi there 👋
Does it make sense for μ/log to be used from ClojureScript, and if so, is this something you'd be interested in supporting?
I've been looking at alternatives to Amplitude and Sentry for our web app, and it feels like what we'd mostly need is something like μ/log + elasticsearch. To some extent that could be achieved via a backend that's running μ/log, but that begs the question of why not run μ/log directly in ClojureScript.
Do you have thoughts on this?
Cheers,
Filipe
The text was updated successfully, but these errors were encountered: