Skip to content

Instantly share code, notes, and snippets.

@flibustenet
Created June 10, 2023 19:51
Show Gist options
  • Save flibustenet/ed0d449ab91a2a6b187469175fe15a18 to your computer and use it in GitHub Desktop.
Save flibustenet/ed0d449ab91a2a6b187469175fe15a18 to your computer and use it in GitHub Desktop.
Simple explicit stack trace
package main
import (
"errors"
"fmt"
"runtime"
"strings"
)
// f1 call f2() and show the trace
func f1() error {
err := f2()
if err != nil {
return Tracef("f1 call f2: %trace %v", err)
}
return nil
}
// f2 call notrace() and show the trace
func f2() error {
err := notrace()
if err != nil {
return Tracef("f2 call notrace: %trace %v", err)
}
return nil
}
// notrace don't show any trace
func notrace() error {
return errors.New("simple error with no trace")
}
func main() {
fmt.Println(f1())
}
// Wrapf return formated error with added %trace and %w
func Wrapf(err error, s string, vals ...any) error {
vals = append(vals, err)
return linef(2, s+"\n%trace%w", vals...)
}
// Tracef replace %trace by func() file:line
// fmt.Errorf("blabla %trace %w") will output
// blabla method() file:line %w
func Tracef(s string, vals ...any) error {
return linef(2, s, vals...)
}
// linef replace %trace with method + file:line
func linef(skip int, s string, vals ...any) error {
pc, file, line, ok := runtime.Caller(skip)
if ok {
info := fmt.Sprintf("\n> %s()\n> %s:%d\n",
runtime.FuncForPC(pc).Name(), file, line)
s = strings.Replace(s, "%trace", info, 1)
}
return fmt.Errorf(s, vals...)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment