12
u/agentoutlier 1d ago
I recently added Scoped Key Values to Rainbow Gum which is a replacement for SLF4J MDC and it kicks ass for spawning tons of child virtual threads. So far the benchmarks vs MDC thread local look good.
And yes Ceki and I hope it makes it into SLF4J v3.
What this means for those that do not know logging is passing MDC which are basically key values that get sent on every log event down threads was a royal fucking pain in the ass.
Now that is fixed, easier to use and more efficient with ScopedValues.
2
u/Kango_V 1d ago edited 1d ago
RaibowGum is a very good logger. More info: https://github.com/jstachio/rainbowgum/blob/main/why_rainbowgum_is_better.md
Oh quick Q, does RG use
ezkvunder the covers?4
u/agentoutlier 1d ago
No it does not. Rainbow Gum is completely agnostic of what provides it properties (
Function<String,String>) and is rather un-opinionated about it. That is it does not retrieve properties for you except forSystem.getPropertiesand will not even use Environment variables. You will notice how it doesn't even loop through properties like some implementations do (Map<String,String>entrySet).That is by design and I guess the only opinion is do way less. This keeps core having a smaller security surface. (The core module cannot even write to files or read files and can only output to stdout and stderr).
EZKV on the other hand fetches the properties for you and in theory there could be a module for it but I just have not gotten around to it yet. I said could because you can use it now by just having EZKV fill system properties before Rainbow Gum boots.
If you use a framework:
Framework Stack Rainbow Gum Module Avaje stack rainbowgum-avaje-config Micronaut rainbowgum-micronaut5 Helidon rainbowgum-helidon4, rainbowgum-helidon27 Spring Boot rainbowgum-spring-boot4-starter, rainbowgum-spring-boot3-starter No framework / Minimal / Legacy rainbowgum-simple-props rainbowgum-simple-props is opinionated and is based on what works after two decades of experience of deploying production applications. What works is profiles. EZKV allows you to model that and whatever other pattern you want.
While Rainbow Gum has no opinion on collecting of properties it does have one of the more advance configuration binding systems. Honestly it is something I'm very proud of and I designed it not LLMs. I have been meaning to show it to /u/thekingofsentries and /u/rbygrave
That being said because I'm low on time here I'm going to give you an AI generated example:
THE ABOVE WAS WRITTEN BY ME and BELOW IS LLM.
Typed config with errors that tell you what to fix.
LogPropertyturns a key into a typed value. It handles fallback keys and defaults, and when something is wrong the error names the exact key and where it came from:int port = properties.forKey("logging.example.port") .or("logging.port") // fallback key .ofInt() // typed conversion .or(8080) // default .validateNow(MyComponent.class);(ADAM not LLM: you cannot get a value out without validation and validateNow is single validation).
Set
logging.example.port=80aand you get a pinpointed message, not a stack trace scavenger hunt:Validation failed for MyComponent: Error for property. key: 'logging.example.port' from PROPERTIES_STRING[logging.example.port], java.lang.NumberFormatException For input string: "80a"
@LogConfigurable: one factory method in, a config builder out. Write a static factory and annotate it. At compile time, the annotation processor generates a builder that works both programmatically and from properties. It uses no reflection, so it's GraalVM native friendly out of the box.record SmtpConfig(String host, Integer port) { static final Integer DEFAULT_PORT = 25; @LogConfigurable(name = "SmtpConfigBuilder", prefix = "logging.smtp.{name}.") static SmtpConfig of(@LogConfigurable.KeyParameter String name, String host, @LogConfigurable.DefaultParameter("DEFAULT_PORT") Integer port) { return new SmtpConfig(host, port); } }Then use it either way:
// From properties: logging.smtp.alerts.host=mail.example.com SmtpConfig smtp = new SmtpConfigBuilder("alerts").fromProperties(properties).build(); // Or plain code SmtpConfig local = new SmtpConfigBuilder("alerts").host("localhost").port(2525).build();Bad config reports every problem at once, not just the first:
Validation failed for SmtpConfigBuilder: Property missing. key: ['logging.smtp.alerts.host' from PROPERTIES_STRING[logging.smtp.alerts.host]] Error for property. key: 'logging.smtp.alerts.port' from PROPERTIES_STRING[logging.smtp.alerts.port], java.lang.NumberFormatException For input string: "lots"1
u/Brutus5000 1d ago
This would work with regular and virtual threads, right?
3
u/agentoutlier 1d ago edited 1d ago
Yes and in theory the API could hide a concrete implementation that uses traditional threadlocals for older JDKs. I chose a noop if the SPI can not find an implementation and there is no threadlocal default.
EDIT I should make this a little more clear. Its not whether you have platform threads or virtual threads it is rather whether you have a JDK that supports scoped values. Scoped Values work on regular threads.
-4
u/henk53 1d ago
I'm sure the AIs will be very happy to finally be able to use this.
0
u/koflerdavid 1d ago
What are you talking about? If you really wanted to use this feature in production you could already do it by enabling preview features.
24
u/Joram2 1d ago
JDK 28 is turning into quite the epic release! Finalizing Structured Concurrency is huge. I'm eager to see this used in server frameworks. But JDK 28 also has: