I absolutely loathe reinventing global state by passing "context" objects and the like everywhere. It's the dumbest thing in the world but no one ever questions it.
I absolutely loathe reinventing global state by passing "context" objects and the like everywhere. It's the dumbest thing in the world but no one ever questions it.
Mostly I just wish more languages had Lisp-style dynamic binding / "special variables". Logging is one of the perfect use cases for dynamic scope - you'd have your normal logger object/configuration as the top-level value of a global, and then let-bind it whenever you need to alter its value for all code executed within that specific scope.
Alas, about the only widely-used form of dynamic binding today is environment variables.
It's not perfect, since it uses JVM's thread-local storage under the hood; this can break when e.g. evaluating Futures in a ThreadPool. For variables which are rarely-overridden, like loggers, I do so with a wrapper that also switches the ExecutionContext to a new ThreadPool (urgh, multithreading...)
PS: I do the same for env vars too ;) http://www.chriswarbo.net/blog/2021-04-08-env_vars.html
As for the HN comment that prompted your blog article, I did a double-take reading it, because I could've sworn I wrote the exact same thing around the same time - turns out I did, though on a different thread :).
And if you did want tooling to help, then typically the formats were regular and so you could use ordinary text processing tools to help. sed, awk, grep. With structured logging putting everything into nested balanced expressions, you need parsing. Parsing works until you run across something the parser can't figure out. Say you have some Go code with a JSON logger object you're passing around. What if you want to log something but your logging object isn't passed to that function. (you could pass it everywhere but that increases the arity of every single method by 1, and are also reinventing global state poorly) You're SOL, now you're stuck with fmt.Println() and you just broke jq. No, jq does not handle this failure mode. No, Golang does not let you just spit out arbitrary JSON. Thy must use the logging object.
The only thing it helps is ingestion into databases for heavy machine processing. Which is fine, but don't make it the only or even default way software tools spit out logs. In every other way, introducing parsing into your workflow just slows it all down. The only way I can see structured logging making anyone's job easier is if they never understood how it all worked before.