Skip to content

Commit

Permalink
Incerement more default verbosity level
Browse files Browse the repository at this point in the history
  • Loading branch information
pmendelski committed Mar 21, 2023
1 parent 45c8e55 commit 62c8aae
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 117 deletions.
165 changes: 94 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,93 +94,116 @@ The default verbosity level is 5.

Verbosity level samples generated with `go run ./samples`:
```
>>> Verbosity: 0
>>> Format: 0
foo failed
>>> Verbosity: 1
>>> Format: 1
foo failed
caused by: bar failed
>>> Verbosity: 2
>>> Format: 2
foo failed
main.foo:34
main.main:10
runtime.main:250
runtime.goexit:1598
main.foo():19
main.main():10
runtime.main():250
runtime.goexit():1598
caused by: bar failed
main.bar:38
main.foo:33
main.main:10
runtime.main:250
runtime.goexit:1598
main.bar():23
main.foo():18
main.main():10
runtime.main():250
runtime.goexit():1598
>>> Verbosity: 3
>>> Format: 3
foo failed
./samples.go:34
./samples.go:10
go1.20.2/rc/runtime/proc.go:250
go1.20.2/rc/runtime/asm_amd64.s:1598
./samples.go:19
./samples.go:10
go1.20.2/rc/runtime/proc.go:250
go1.20.2/rc/runtime/asm_amd64.s:1598
caused by: bar failed
./samples.go:38
./samples.go:33
./samples.go:10
go1.20.2/rc/runtime/proc.go:250
go1.20.2/rc/runtime/asm_amd64.s:1598
./samples.go:23
./samples.go:18
./samples.go:10
go1.20.2/rc/runtime/proc.go:250
go1.20.2/rc/runtime/asm_amd64.s:1598
>>> Verbosity: 4
>>> Format: 4
foo failed
./samples.go:34 main.foo
./samples.go:10 main.main
go1.20.2/rc/runtime/proc.go:250 runtime.main
go1.20.2/rc/runtime/asm_amd64.s:1598 runtime.goexit
./samples.go:19 foo()
./samples.go:10 main()
go1.20.2/rc/runtime/proc.go:250 main()
go1.20.2/rc/runtime/asm_amd64.s:1598 goexit()
caused by: bar failed
./samples.go:38 main.bar
./samples.go:33 main.foo
./samples.go:10 main.main
go1.20.2/rc/runtime/proc.go:250 runtime.main
go1.20.2/rc/runtime/asm_amd64.s:1598 runtime.goexit
./samples.go:23 bar()
./samples.go:18 foo()
./samples.go:10 main()
go1.20.2/rc/runtime/proc.go:250 main()
go1.20.2/rc/runtime/asm_amd64.s:1598 goexit()
>>> Verbosity: 5 (DEFAULT)
>>> Format: 5
foo failed
./samples.go:34
main.foo
./samples.go:10
main.main
go1.20.2/rc/runtime/proc.go:250
runtime.main
go1.20.2/rc/runtime/asm_amd64.s:1598
runtime.goexit
main.foo()
./samples.go:19
main.main()
./samples.go:10
runtime.main()
go1.20.2/rc/runtime/proc.go:250
runtime.goexit()
go1.20.2/rc/runtime/asm_amd64.s:1598
caused by: bar failed
./samples.go:38
main.bar
./samples.go:33
main.foo
./samples.go:10
main.main
go1.20.2/rc/runtime/proc.go:250
runtime.main
go1.20.2/rc/runtime/asm_amd64.s:1598
runtime.goexit
>>> Verbosity: 6
main.bar()
./samples.go:23
main.foo()
./samples.go:18
main.main()
./samples.go:10
runtime.main()
go1.20.2/rc/runtime/proc.go:250
runtime.goexit()
go1.20.2/rc/runtime/asm_amd64.s:1598
>>> Format: 6
foo failed
/Users/mendlik/Development/go/go-errors/samples/samples.go:34
main.foo
/Users/mendlik/Development/go/go-errors/samples/samples.go:10
main.main
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/proc.go:250
runtime.main
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/asm_amd64.s:1598
runtime.goexit
./samples.go:19
foo()
./samples.go:10
main()
go1.20.2/rc/runtime/proc.go:250
main()
go1.20.2/rc/runtime/asm_amd64.s:1598
goexit()
caused by: bar failed
/Users/mendlik/Development/go/go-errors/samples/samples.go:38
main.bar
/Users/mendlik/Development/go/go-errors/samples/samples.go:33
main.foo
/Users/mendlik/Development/go/go-errors/samples/samples.go:10
main.main
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/proc.go:250
runtime.main
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/asm_amd64.s:1598
runtime.goexit
./samples.go:23
bar()
./samples.go:18
foo()
./samples.go:10
main()
go1.20.2/rc/runtime/proc.go:250
main()
go1.20.2/rc/runtime/asm_amd64.s:1598
goexit()
>>> Format: 7
foo failed
/Users/mendlik/Development/go/go-errors/samples/samples.go:19
main.foo()
/Users/mendlik/Development/go/go-errors/samples/samples.go:10
main.main()
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/proc.go:250
runtime.main()
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/asm_amd64.s:1598
runtime.goexit()
caused by: bar failed
/Users/mendlik/Development/go/go-errors/samples/samples.go:23
main.bar()
/Users/mendlik/Development/go/go-errors/samples/samples.go:18
main.foo()
/Users/mendlik/Development/go/go-errors/samples/samples.go:10
main.main()
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/proc.go:250
runtime.main()
/Users/mendlik/.sdkvm/sdk/go/1.20.2/src/runtime/asm_amd64.s:1598
runtime.goexit()
```
2 changes: 2 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package errors

import (
"io"
"path"
"runtime"
"runtime/debug"
)

var Config struct {
StackTraceFormatter func(err *Error, verbosity int) string
FrameFormatter func(w io.Writer, frame *Frame, verbosity int) string
Verbosity int
BasePath string
BaseCachePath string
Expand Down
51 changes: 35 additions & 16 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,29 @@ func (e *Error) StackTraceString(verbosity int) string {
}
for i := 0; i < n; i++ {
frame := stacktrace[i]
switch verbosity {
case 2:
fmt.Fprintf(buf, "\t%s:%d\n", frame.RelFuncName(), frame.Line())
case 3:
fmt.Fprintf(buf, "\t%s:%d\n", frame.RelFile(), frame.Line())
case 4:
fmt.Fprintf(buf, "\t%s:%d %s\n", frame.RelFile(), frame.Line(), frame.RelFuncName())
case 5:
fmt.Fprintf(buf, "\t%s:%d\n", frame.RelFile(), frame.Line())
fmt.Fprintf(buf, "\t\t%s\n", frame.RelFuncName())
default:
fmt.Fprintf(buf, "\t%s:%d\n", frame.File(), frame.Line())
fmt.Fprintf(buf, "\t\t%s\n", frame.FuncName())
if Config.FrameFormatter != nil {
Config.FrameFormatter(buf, &frame, verbosity)
} else {
switch verbosity {
case 2:
fmt.Fprintf(buf, "\t%s():%d\n",
frame.FuncName(), frame.FileLine())
case 3:
fmt.Fprintf(buf, "\t%s:%d\n",
frame.RelFileName(), frame.FileLine())
case 4:
fmt.Fprintf(buf, "\t%s:%d %s()\n",
frame.RelFileName(), frame.FileLine(), frame.ShortFuncName())
case 5:
fmt.Fprintf(buf, "\t%s()\n", frame.FuncName())
fmt.Fprintf(buf, "\t\t%s:%d\n", frame.RelFileName(), frame.FileLine())
case 6:
fmt.Fprintf(buf, "\t%s:%d\n", frame.RelFileName(), frame.FileLine())
fmt.Fprintf(buf, "\t\t%s()\n", frame.ShortFuncName())
default:
fmt.Fprintf(buf, "\t%s:%d\n", frame.File(), frame.FileLine())
fmt.Fprintf(buf, "\t\t%s()\n", frame.FuncName())
}
}
}
if n < len(stacktrace) {
Expand Down Expand Up @@ -276,9 +286,9 @@ func (f Frame) File() string {
return file
}

// Line returns the Line number of source code of the
// FileLine returns the FileLine number of source code of the
// function for this Frame's pc.
func (f Frame) Line() int {
func (f Frame) FileLine() int {
fn := runtime.FuncForPC(f.Pc())
if fn == nil {
return 0
Expand All @@ -305,8 +315,17 @@ func (f Frame) RelFuncName() string {
return name
}

// function name relative to main package
func (f Frame) ShortFuncName() string {
name := f.FuncName()
i := strings.LastIndex(name, "/")
name = name[i+1:]
i = strings.Index(name, ".")
return name[i+1:]
}

// file name relateive to BasePath or BaseCachePath
func (f Frame) RelFile() string {
func (f Frame) RelFileName() string {
name := f.File()
relPath, ok := trimBasePath(Config.BasePath, name)
if ok {
Expand Down
23 changes: 4 additions & 19 deletions samples/samples.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,10 @@ import (

func main() {
err := foo()
// 0: error
fmt.Printf("\n>>> Format: 0\n%s", errors.Formatv(err, 0))
// 1: error + causes
fmt.Printf("\n>>> Format: 1\n%s", errors.Formatv(err, 1))
// 2: error + causes with stack traces of relative func names and lines
fmt.Printf("\n>>> Format: 2\n%s", errors.Formatv(err, 2))
// 3: error + causes with stack traces of relative file names and lines
fmt.Printf("\n>>> Format: 3\n%s", errors.Formatv(err, 3))
// 4: error + causes with stack traces of relative file names and lines
// ...and relative func names
fmt.Printf("\n>>> Format: 4\n%s", errors.Formatv(err, 4))
// 5: like 4 but in single line
fmt.Printf("\n>>> Format: 5\n%s", errors.Formatv(err, 5))
// 6: like 4 but uses absolute file names and func names
fmt.Printf("\n>>> Format: 6\n%s", errors.Formatv(err, 6))

// standard errors are formatted with err.Error()
goerr := fmt.Errorf("go error")
fmt.Printf("\n>>> Format go error:\n%s", errors.Format(goerr))
for i := 0; i < 8; i++ {
fmt.Printf(">>> Format: %d\n", i)
fmt.Println(errors.Formatv(err, i))
}
}

func foo() error {
Expand Down
2 changes: 1 addition & 1 deletion test/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (suite *ErrorsSuite) TestAs() {

func frameRelFile(err *errors.Error, idx int) string {
frame := err.StackTrace()[idx]
return frame.RelFile()
return frame.RelFileName()
}

func frameRelFunc(err *errors.Error, idx int) string {
Expand Down
24 changes: 14 additions & 10 deletions test/format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,34 @@ func (suite *FormatSuite) TestFormats() {
{0, []string{"foo failed\n"}},
{1, []string{"foo failed\ncaused by: bar failed\n"}},
{2, []string{
"foo failed\n\t\\./test_test.foo:\\d+",
"caused by: bar failed\n\t\\./test_test.bar:\\d+",
"foo failed\n\tgithub.com/coditory/go-errors/test_test.foo\\(\\):\\d+",
"caused by: bar failed\n\tgithub.com/coditory/go-errors/test_test.bar\\(\\):\\d+",
}},
{3, []string{
"foo failed\n\t\\./test/format_test.go:\\d+",
"caused by: bar failed\n\t\\./test/format_test.go:\\d+",
}},
{4, []string{
"foo failed\n\t\\./test/format_test.go:\\d+ \\./test_test.foo",
"caused by: bar failed\n\t\\./test/format_test.go:\\d+ \\./test_test.bar",
"foo failed\n\t\\./test/format_test.go:\\d+ foo\\(\\)",
"caused by: bar failed\n\t\\./test/format_test.go:\\d+ bar\\(\\)",
}},
{5, []string{
"foo failed\n\t./test/format_test.go:\\d+\n\t\t\\./test_test.foo",
"\ncaused by: bar failed\n\t./test/format_test.go:\\d+\n\t\t\\./test_test.bar",
"foo failed\n\tgithub.com/coditory/go-errors/test_test.foo\\(\\)\n\t\t\\./test/format_test.go:\\d+\n",
"\ncaused by: bar failed\n\tgithub.com/coditory/go-errors/test_test.bar\\(\\)\n\t\t\\./test/format_test.go:\\d+\n",
}},
{6, []string{
"foo failed\n\t.+/test/format_test.go:\\d+\n\t\tgithub.com/coditory/go-errors/test_test.foo\n",
"\ncaused by: bar failed\n\t.+/test/format_test.go:\\d+\n\t\tgithub.com/coditory/go-errors/test_test.bar\n",
"foo failed\n\t./test/format_test.go:\\d+\n\t\tfoo\\(\\)",
"\ncaused by: bar failed\n\t./test/format_test.go:\\d+\n\t\tbar\\(\\)",
}},
{7, []string{
"foo failed\n\t.+/test/format_test.go:\\d+\n\t\tgithub.com/coditory/go-errors/test_test.foo\\(\\)\n",
"\ncaused by: bar failed\n\t.+/test/format_test.go:\\d+\n\t\tgithub.com/coditory/go-errors/test_test.bar\\(\\)\n",
}},
}
tests = append(tests, tests[len(tests)-1])
tests[len(tests)-1].verbosity = 100
tests = append(tests, tests[0])
tests[len(tests)-1].verbosity = -100
tests = append(tests, tests[len(tests)-2])
tests[len(tests)-1].verbosity = 100
for _, tt := range tests {
name := fmt.Sprintf("Verbosity:%d", tt.verbosity)
suite.Run(name, func() {
Expand Down

0 comments on commit 62c8aae

Please sign in to comment.