My own thoughts.
-
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.
-
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!
-
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":
// BEFORE
func PrepareContainer(ctx context.Context, container ContainerContext, locales []string, dryRun bool, allLocalesRequired bool) (*StatusResult, error) {
logger.Info(`Filling home page template`)
// AFTER
var tr = otel.Tracer("container_api")
func PrepareContainer(ctx context.Context, container ContainerContext, locales []string, dryRun bool, allLocalesRequired bool) (*StatusResult, error) {
ctx, span := tr.Start(ctx, "prepare_container")
defer span.End()
(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.
- 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.