There have been multiple accounts created with the sole purpose of posting advertisement posts or replies containing unsolicited advertising.

Accounts which solely post advertisements, or persistently post them may be terminated.

Tracing: structured logging, but better in every way

TLDR; The author argues that free-form logging is quite useless/expensive to use. They also argue that structured logging is less effective than tracing b/c of mainly the difficulty of inferring timelines and causality.


I find the arguments very plausible.

In fact I very rarely use logs produced by several services b/c most of the times they just confuse me. The only time that I heavily use logs is troubleshooting a single service and looking at its stdout (or kubectl log.)

However I have very little experience w/ tracing (I’ve used it in my hobby projects but, obviously, they never represent the reality of complex distributed systems.)

Have you got real world experience w/ tracing in larger systems? Care to share your take on the topic?

ttmrichter ,

My own thoughts.

  1. Instead of defining the difference between logging and tracing, the author spams the screen with pages’ worth of examples of why logging is bad, then jumps into tracing by immediately referencing code that uses a specific tracing library (OpenTelemetry Tracer) without at any point explaining what that code is actually doing to someone who is not familiar with it already. To me this smacks of preaching to the choir since if you’re already familiar with this tool, you’re likely already a) familiar with what “tracing” is compared to “logging”, and b) probably a tracing advocate to begin with. If you want to persuade an undecided or unfamiliar audience, confusing them and/or making assumptions about what they know or don’t know is … suboptimal.
  2. If you’re going to screen dump your code in your rant, FUCKING COMMENT IT YOU GIT! I don’t want to have to read through 100 lines of code in an unfamiliar language written to an unfamiliar architecture to find the three (!) lines that are actually on the fucking topic!
  3. If you’re going to show changes in your code, put before/after snapshots side by side so I don’t have to go scrolling back to the uncommented hundred-line blob to see what changed. It’s not that hard. Using his own damned example from “Step 1”:

<span style="font-style:italic;color:#969896;">// BEFORE
</span><span style="color:#323232;">func PrepareContainer(ctx context.Context, container ContainerContext, locales []string, dryRun bool, allLocalesRequired bool) (</span><span style="font-weight:bold;color:#a71d5d;">*</span><span style="color:#323232;">StatusResult, error) {
</span><span style="color:#323232;">	logger.Info(</span><span style="color:#183691;">`Filling home page template`</span><span style="color:#323232;">)
</span>

<span style="font-style:italic;color:#969896;">// AFTER
</span><span style="font-weight:bold;color:#a71d5d;">var </span><span style="color:#323232;">tr </span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#323232;">otel.Tracer(</span><span style="color:#183691;">"container_api"</span><span style="color:#323232;">)
</span><span style="color:#323232;">
</span><span style="color:#323232;">func PrepareContainer(ctx context.Context, container ContainerContext, locales []string, dryRun bool, allLocalesRequired bool) (</span><span style="font-weight:bold;color:#a71d5d;">*</span><span style="color:#323232;">StatusResult, error) {
</span><span style="color:#323232;">	ctx, span :</span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#323232;">tr.Start(ctx, </span><span style="color:#183691;">"prepare_container"</span><span style="color:#323232;">)
</span><span style="color:#323232;">	defer span.End()
</span>

(And while you’re at it, how 'bout explaining the fucking code you wrote? How hard is it to add a line explaining what that defer span.End() nonsense is? Remember, you’re trying to sell people on the need for tracing. If they already know what you’re talking about you’re preaching to the choir, son.)

Of course in “The Result” he talks about the diff between the two functions … but doesn’t actually provide that diff. Instead he provides another hundred-line blob kept far away from the original so you have to bounce back and forth between them to spot the differences. Side-by-side diffs are a thing and there’s plenty of tools that make supplying them trivial. Maybe the author should think about using them.

  1. The technique this guy is espousing, if I’m reading it right, sounds fine but only in limited realms. This would kill development in my realm (small embedded systems), for example. If you have (effectively, from my domain’s perspective) infinite RAM, CPU, persistent storage, and bandwidth, then yes, this is likely a very good technique. (I can’t be certain, of course, because he hasn’t actually explained anything, just blasted uncommented code while referencing a library he assumes we know about. The only reason I followed any of it is because I’m familiar with Erlang’s tooling for this kind of stuff which puts what he’s showing off to shame.) But if your RAM is limited (hint: measured in 2-digit KB and shared by your stack(s), heap, and static memory), if your CPU is a blazing-fast 80MHz, and if you think 1MB of persistent storage (which your program binary has to share) is a true bucket of gold in wealth, and, yes, if you’re transmitting over a communications link that would have '80s-era modem jockies looking on you with pity, then maybe, just maybe, tracing isn’t so great an idea after all.
krnpnk ,

Some thoughts from my side (coming from another domain - more embedded):

  • Whether you use a message string or a named bool does not change anything. It’s still logging.
  • It’s of course nice to just trace everything and filter / search afterwards, but in embedded for example your machine may just crash if you try that. For that log levels are the traditional way to filter before a log is written.
  • I don’t get how timestamping / ordering is necessarily worse for logging. Maybe it’s just the framework that is used?
  • You sure can have hierarchical information in log frameworks

In my opinion log levels sure make sense, but it may vary wildly depending on what you’re doing. We run our software in different environments:

  • Development machines / VMs
  • Development boards
  • Production ECUs

And it’s run by different sets of people:

  • Devs
  • Integrators
  • Customers

Depending on the combination of where / who you get different requirements.

I get that Logging is hard and often you get messages with a wrong log level or you’re missing a message at a crucial point etc. But tracing is not better in every way - they should complement each other.

bahmanm OP ,
@bahmanm@lemmy.ml avatar

Thanks for sharing your insights.


Thinking out loud here…

In my experience with traditional logging and distributed systems, timestamps and request IDs do store the information required to partially reconstruct a timeline:

  • In the case of a linear (single branch) timeline you can always “query” by a request ID and order by the timestamps and that’s pretty much what tracing will do too.
  • Things, however, get complicated when you’ve a timeline w/ multiple branches.
    For example, consider the following relatively simple diagram.
    Reconstructing the causality and join/fork relations between the executions nodes is almost impossible using traditional logs whereas a tracing solution will turn this into a nice visual w/ all the spans and sub-spans.

https://lemmy.ml/pictrs/image/9e00ce74-96e5-4961-8579-7a25f48f92ce.png

That said, logs do shine when things go wrong; when you start your investigation by using a stacktrace in the logs as a clue. That (stacktrace) is something that I’m not sure a tracing solution will be able to provide.


they should complement each other

Yes! You nailed it 💯

Logs are indispensable for troubleshooting (and potentially nothing else) while tracers are great for, well, tracing the data/request throughout the system and analyse the mutations.

bahmanm OP ,
@bahmanm@lemmy.ml avatar

I’m not sure how this got cross-posted! I most certainly didn’t do it 🤷‍♂️

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • [email protected]
  • lifeLocal
  • goranko
  • All magazines