A big thanks to Clojurists Together, Nubank, and other sponsors of my open source work! I realise that it’s a tough time for a lot of folks and businesses lately, and that sponsorships aren’t always easy 🙏
Hi folks! 👋 I hope those of you in summer are enjoying the nice weather ☀️
Have some chonky updates for today!
Timbre is a pure Clojure/Script logging library.
Timbre v6.6.0-RC1 is out now. There’s some internal improvements, but the highlight is added out-the-box support for Java logging interop via SLF4J.
This is handled via a new SLF4J provider/backend dependency available on Clojars - instructions here.
The implementation is back-ported from Telemere and includes support for legacy and modern (“fluent”) SLF4J logging APIs, MDC (context key/vals), markers, etc.
This was one of the upvoted items on my open source roadmap, and definitely something nice to have officially supported.
Previously many Timbre users used the separate slf4j-timbre library for such interop - and I’d like to say a warm thanks to that library’s original author Farid Zakaria and steward / maintainer rufoa.
Their job was a challenging one - needing to keep up with internal changes to Timbre over time, etc. With the new approach, Timbre’s SLF4J support will now always be automatically kept in sync and tested with Timbre’s latest release, which should help minimize future maintenance headaches.
Telemere is a modern rewrite of Timbre that offers an improved API to cover traditional logging, structured logging, tracing, basic performance measurement, and more.
My big focus recently has been Telemere, with 8 new beta releases since June.
The latest as of this post is v1.0.0-beta22 (2024-08-28).
The basic API has been stable, including re: signal creation and signal content - but I’ve been continuing to polish things in preparation for RC1 (expected next month).
Recent improvements include:
This was another upvoted item from my open source roadmap, and quite a bit of work to get just right.
Telemere can now send signals as OpenTelemetry LogRecords
with correlated tracing data to configured OpenTelemetry
Java exporters.
This allows output to go (via configured exporters) to a wide variety of targets like Jaeger, Zipkin, AWS X-Ray, AWS CloudWatch, etc.
See here for instructions.
A couple nice properties of the way Telemere handles OpenTelemetry interop:
Aside from configuring OpenTelemetry Java itself, Telemere’s OpenTelemetry interop doesn’t require any use of or familiarity with the OpenTelemetry Java API or concepts. So if you’re like me, you’ll be pleased to know that you can basically avoid all the usual OpenTelemetry API nonsense. You just use Telemere as you normally would, and it’ll act as your Clojure interface to OTel.
Creating OpenTelemetry tracing spans and attaching attributes can be expensive, which violates a unique design goal of Telemere - to make it possible to dynamically filter costs as you filter signals. Telemere works around this by creating only minimal spans at first (to enable full interop with auto-instrumentation and other OTel tools), and saving all the expensive work for the post-filter signal handlers. Basically this gives you best of both worlds: full auto interop, but also lazy costs well-suited to Telemere’s rich filtering architecture.
For feedback and/or experience reports, please feel free to ping me on the Slack channel or GitHub.
A major focus for Telemere has been the docs and examples.
My hope is to build something friendly enough for complete beginners.
If you haven’t looked at them yet (or recently), it might be worth checking out the README, Wiki, or API docs.
Some good starting points:
Telemere now offers guidance for library authors/maintainers that might like to use Telemere in their own library, and offers a new super lightweight Facade API.
For a library using the facade:
tools.logging
.Telemere may seem a bit of an odd animal at first since it looks like a logging library that’s hesitating to call itself a logging library. As it took shape, I struggled with how to describe it.
What I’d say today: Telemere’s basically meant to be a one-stop API for all the most common observability needs. These include traditional (string-oriented) logging, structured logging (arb nested Clojure data), events, tracing, and basic performance monitoring.
What I realised thinking about this problem space over the years - is that all of the above share fundamental ideas and needs:
I suspected that a single API would do - but I wasn’t sure until I
tried. When I did try, what I ended up with was actually a single
macro (signal!
)
that handles all of the above through a handful of options.
I’m honestly very happy with the result - I find it elegant, easy to use and to understand, and deeply flexible. And I’m proud of the particular combination of ease-of-use and power - since these goals are often in conflict.
I’ll note that Telemere’s approach is possible only in a Lisp. And certain aspects of its implementation (esp. re: interop) are possible only in Clojure. So the value proposition here is unique.
At the risk of being overly blunt: observability matters, and in my opinion Telemere offers a code-side observability story that’s competitive with anything else I’m aware of in any language.
Part of my motivation in pursuing this particular project has been to try to use Clojure’s unique strengths to offer a unique and compelling advantage to Clojure projects/businesses/teams. Clojure enables Telemere, Telemere helps enable inexpensive and effective observability, observability helps enable more robust and debuggable systems. And robust debuggable systems can help enable successful projects.
So the idea (hope) is to be both a practical tool, and a sort of reference example of one of the kinds of tangible, real-world advantages made possible by Clojure.
As always please do help vote on what you’d like to see me working on!
My aim is to release v1 RC1 in September, then v1 final before the end of 2024.
The big stuff is all done, what remains is to give folks the opportunity to kick tyres and report issues or request changes before locking down the API.
Please also vote on which signal handlers would be most useful.
After that, my hope will be for Telemere to basically be stable - and to redirect future efforts toward education and promotion. Telemere enables a lot of powerful but non-obvious stuff, which I’ll need to do more work to explain.
Tempel is a new data security framework for Clojure.
I’d like to release v1 final before the end of 2024. Still have some last features to think through and design (multi-factor authentication, etc.).
Tufte offers simple performance monitoring for Clojure/Script.
Once Telemere v1 RC1 is out, I’ll be ready to prepare Tufte v3 - which’ll include a move to the exact same signal architecture powering Telemere.
Tufte and Telemere will then share identical terminology, capabilities, and API for filtering, handlers, etc.
The two already work well together, but interop will be even smoother after v3. The aim is to offer Telemere and Tufte as partner (complementary) libraries to enable unique next-gen observability capabilities for Clojure and ClojureScript applications.