Show HN: Dlg – Zero-cost printf-style debugging for Go

github.com

62 points by 0xFEE1DEAD 4 days ago


Hey HN,

I tend to use printf-style debugging as my primary troubleshooting method and only resort to gdb as a last resort.

While I like its ease of use printf debugging isn't without its annoyances, namely removing the print statements once you're done.

I used to use trace-level logging from proper logging libraries but adding trace calls in every corner quickly gets out of control and results in an overwhelming amount of output.

To scratch my own itch I created dlg - a minimal debugging library that disappears completely from production builds. Its API exposes just a single function, Printf [1].

dlg is optimized for performance in debug builds and, most importantly, when compiled without the dlg build tag, all calls are eliminated by the Go linker as if dlg was never imported.

For debug builds it adds optional stack trace generation configurable via environment variables or linker flags.

GitHub: https://github.com/vvvvv/dlg

Any feedback is much appreciated.

[1]: Actually two functions - there's also SetOutput.

mdaniel - 20 hours ago

How does the dead code elimination work when using args to Printf? If static strings are fed into an empty function, I can imagine it does nothing. However, this I have less of a firm grip upon

  dlg.Printf("the thing.Something is %+v", thing.Something())
since surely golang will still call Something, and still call Printf

And don't misunderstand me: it's a grave pet peeve of mine to do action inside the args to Printf but I can tell you it's a very common [anti-]pattern so I'd presume your users will want a story for how that interacts with the "disappears completely" claim

0points - 2 hours ago

> Any feedback is much appreciated.

There is way too much going on in this code whose feature essentially boils down to

    func Printf(f string, v ...any) {
        if CONDITION {
         fmt.Printf(f, v...)
        }
    }
Writing a stack trace is fully unrelated to Printf(), and should be separated.
smcameron - a day ago

> printf debugging isn't without its annoyances, namely removing the print statements once you're done.

Use something like stacked git[1], and then it's just one "stg pop" and poof, they're gone.

[1] https://stacked-git.github.io/

kitd - a day ago

Very cool!

Just one thought: I don't think your stack traces need to include the lines inside Printf itself and it adds to the noise a bit. Maybe just go up to the line where the call to Printf is made?

sigmonsays - 19 hours ago

it doesn't appear to truly be zero cost if you log variables that can't be eliminated. The only way (I believe) to implement zero cost is some type of macro system which go does not support.

negrel - 21 hours ago

Cool lib! I took the same approach for my zero cost debugging assertion Go library

https://github.com/negrel/assert

- 20 hours ago
[deleted]
sethammons - a day ago

In extreme processing needs, I suppose the elimination of a check that would happen with a level logger is a solid trade off.

My favored approach is a context aware level logger with structured logs going to an aggregator like Splunk.

Because it is context aware, custom filtering logic is available in a middleware.

latchkey - 19 hours ago

I'm curious why you prefer this over writing tests.