Skip to content

Instantly share code, notes, and snippets.

@podhmo
Created May 29, 2024 11:14
Show Gist options
  • Save podhmo/0cb5aee7963e02ca9126498c16bb1fd0 to your computer and use it in GitHub Desktop.
Save podhmo/0cb5aee7963e02ca9126498c16bb1fd0 to your computer and use it in GitHub Desktop.

stack traceをいい感じに読みやすいようにしたい

これを https://go.dev/play/p/CCIw0yBEFuh

{
  "message": "hmm",
  "trace": "goroutine 1 [running]:\nruntime/debug.Stack()\n\t/usr/local/go-faketime/src/runtime/debug/stack.go:24 +0x5e\nmain.main.func1()\n\t/tmp/sandbox697180827/prog.go:12 +0x3f\npanic({0x4a8260?, 0x4e3120?})\n\t/usr/local/go-faketime/src/runtime/panic.go:770 +0x132\nmain.f5(...)\n\t/tmp/sandbox697180827/prog.go:37\nmain.f4(...)\n\t/tmp/sandbox697180827/prog.go:34\nmain.f3(...)\n\t/tmp/sandbox697180827/prog.go:31\nmain.f2(...)\n\t/tmp/sandbox697180827/prog.go:28\nmain.f1(...)\n\t/tmp/sandbox697180827/prog.go:25\nmain.f0(...)\n\t/tmp/sandbox697180827/prog.go:22\nmain.main()\n\t/tmp/sandbox697180827/prog.go:18 +0x45\n"
}
package main
import (
"encoding/json"
"os"
"runtime/debug"
)
func main() {
defer func() {
if r := recover(); r != nil {
st := debug.Stack()
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(map[string]any{"trace": string(st), "message": r})
}
}()
f0()
}
func f0() {
f1()
}
func f1() {
f2()
}
func f2() {
f3()
}
func f3() {
f4()
}
func f4() {
f5()
}
func f5() {
panic("hmm")
}
@podhmo
Copy link
Author

podhmo commented May 29, 2024

\n\tを普通に改行やタブと判断してJSONとしてはinvalidだけれど以下のような形で表示してくれても良い。

{
  "message": "hmm",
  "trace": "goroutine 1 [running]:
runtime/debug.Stack()
	/usr/local/go-faketime/src/runtime/debug/stack.go:24 +0x5e
main.main.func1()
	/tmp/sandbox697180827/prog.go:12 +0x3f
panic({0x4a8260?, 0x4e3120?})
	/usr/local/go-faketime/src/runtime/panic.go:770 +0x132
main.f5(...)
	/tmp/sandbox697180827/prog.go:37
main.f4(...)
	/tmp/sandbox697180827/prog.go:34
main.f3(...)
	/tmp/sandbox697180827/prog.go:31
main.f2(...)
	/tmp/sandbox697180827/prog.go:28
main.f1(...)
	/tmp/sandbox697180827/prog.go:25
main.f0(...)
	/tmp/sandbox697180827/prog.go:22
main.main()
	/tmp/sandbox697180827/prog.go:18 +0x45
"
}

@podhmo
Copy link
Author

podhmo commented May 29, 2024

JSONを壊さない範囲ではarrayにしてあげても良い。

$ cat /tmp/a.json | jqfpy 'd = get(); d["trace"] = [x.replace("\t", "    ") for x in d["trace"].split("\n")]; d'
{
  "message": "hmm",
  "trace": [
    "goroutine 1 [running]:",
    "runtime/debug.Stack()",
    "    /usr/local/go-faketime/src/runtime/debug/stack.go:24 +0x5e",
    "main.main.func1()",
    "    /tmp/sandbox697180827/prog.go:12 +0x3f",
    "panic({0x4a8260?, 0x4e3120?})",
    "    /usr/local/go-faketime/src/runtime/panic.go:770 +0x132",
    "main.f5(...)",
    "    /tmp/sandbox697180827/prog.go:37",
    "main.f4(...)",
    "    /tmp/sandbox697180827/prog.go:34",
    "main.f3(...)",
    "    /tmp/sandbox697180827/prog.go:31",
    "main.f2(...)",
    "    /tmp/sandbox697180827/prog.go:28",
    "main.f1(...)",
    "    /tmp/sandbox697180827/prog.go:25",
    "main.f0(...)",
    "    /tmp/sandbox697180827/prog.go:22",
    "main.main()",
    "    /tmp/sandbox697180827/prog.go:18 +0x45",
    ""
  ]
}

@podhmo
Copy link
Author

podhmo commented May 29, 2024

"\t" のネスト関係をそのまま利用するとかはどうなんだろう?あとは単純にJSONで返すとかもあるけれど見づらそう。
そして検索に引っかかる形が嬉しい。そうなると変にネストさせたりしない方が都合が良いのかもしれない。

@podhmo
Copy link
Author

podhmo commented May 29, 2024

💭 githubのissueに貼るのならJSONにこだわらなくても良いな。一行になっていて展開されていないのは厳しそう。

@podhmo
Copy link
Author

podhmo commented May 29, 2024

あとでクエリー的なもので集約したり集計したりするならそういう条件が書けるような形式になってると嬉しい。

@podhmo
Copy link
Author

podhmo commented May 29, 2024

たぶん、元のスタックトレース自体をJSON化するのは見づらいと思う [{"file": "...", "line": 44, "text": "..."}, ...] みたいなスタイル。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment