Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It is recommended that go+ further enhance the stack information when errors occur. #1713

Open
sqhua opened this issue Feb 8, 2024 · 1 comment
Labels

Comments

@sqhua
Copy link

sqhua commented Feb 8, 2024

Proposal

if my code like this : main->add3->add2->add

`
import (
"strconv"
"runtime"
"strings"
)

func add3(x, y string) (int, error) {
return add2(x, y )
}

func add2(x, y string) (int, error) {
return add(x, y )
}

func add(x, y string) (int, error) {
return strconv.atoi(x)? + strconv.atoi(y)?, nil
}

sum, err := add3("9999", "kkkk")
_, _ = sum, err
println err
println "this is ending"

`

this is the original output:

==> errors stack a:
. main.add3()
. bin/a.gop:16 strconv.atoi(y)

but I hope the error output add the info like this:

main.add
. bin/a.gop:16
main.add2
. bin/a.gop:12
main.add3
. bin/a.gop:7
main.main()
. bin/a.gop:19

here is my modify in source code:

...\go\pkg\mod\github.com\qiniu\x@v1.13.3\errors\errors.go

The added content is in bold font

// Frame represents an error frame.
type Frame struct {
Err error
Func string
Args []interface{}
Code string
File string
Line int
Stack []byte
}

// NewFrame creates a new error frame.
func NewFrame(err error, code, file string, line int, fn string, args ...interface{}) *Frame {
stack := make([]byte, 2048)
length := runtime.Stack(stack, false)

return &Frame{Err: err, Func: fn, Args: args, Code: code, File: file, Line: line , Stack: stack[:length] }
}

func errorDetail(b []byte, p *Frame) []byte {
if f, ok := p.Err.(*Frame); ok {
//fmt.Println( "sqhua errors.go Debug2: ", p )
b = errorDetail(b, f)
} else {
b = append(b, p.Err.Error()...)
b = append(b, "\n\n==> errors stack a:\n"...)
}
b = append(b, p.Func...)
b = append(b, '(')
b = argsDetail(b, p.Args)
b = append(b, ")\n\t"...)
b = append(b, p.File...)
b = append(b, ':')
b = strconv.AppendInt(b, int64(p.Line), 10)
b = append(b, ' ')
b = append(b, p.Code...)
b = append(b, '\n')
b = append(b, '\n')
b = append(b, parseStack( 20, string(p.Stack))...)
b = append(b, '\n')

return b
}

func parseStack(n int, stack string) string {
stackLines := strings.Split(stack, "\n")
var parsedStack string
for i, line := range stackLines {
if i < 3 { //skip the gop inter func call
continue
}
if i >= n {
break
}
parsedStack = parsedStack + "\n" + line
}
return parsedStack
}

Background

Currently, go+ only outputs the line of code where the error occurred, but not the call chain.

Workarounds

when coding, this feature is useful, and help C# or Java player to easy use go+

/

@sqhua
Copy link
Author

sqhua commented Feb 18, 2024

If the default output is detailed stack information, it may also result in too much information. When developing in Java, it was also very painful to look at the log files when using frameworks like Spring with deep call stacks. Therefore, it can be considered to add a stack_level configuration item to indicate the depth of the output, with a default value of 0, which is the current gop's output_mode.


进一步的建议:
如果默认输出了详细stack信息,也可能造成信息过多。之前做Java开发时,用到Spring等调用栈过深的框架时,看那些Log日志也很头痛。因此可以考虑在哪加个stack_level配置项,表示要输出的深度,默认是0,也就是当前gop的输出方式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants