go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/errors/annotate_example_test.go (about) 1 // Copyright 2016 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package errors 16 17 import ( 18 "fmt" 19 ) 20 21 func someProcessingFunction(val int) error { 22 if val == 1 { 23 // New and Reason automatically include stack information. 24 return Reason("bad number: %d", val).Err() 25 } 26 if err := someProcessingFunction(val - 1); err != nil { 27 // correctly handles recursion 28 return Annotate(err, "").InternalReason("val(%d)", val).Err() 29 } 30 return nil 31 } 32 33 func someLibFunc(vals ...int) error { 34 for i, v := range vals { 35 if err := someProcessingFunction(v); err != nil { 36 return Annotate(err, "processing %d", v). 37 InternalReason("secret(%s)/i(%d)", "value", i).Err() 38 } 39 } 40 return nil 41 } 42 43 type MiscWrappedError struct{ error } 44 45 func (e *MiscWrappedError) Error() string { return fmt.Sprintf("super wrapper(%s)", e.error.Error()) } 46 func (e *MiscWrappedError) Unwrap() error { return e.error } 47 48 func errorWrapper(err error) error { 49 if err != nil { 50 err = &MiscWrappedError{err} 51 } 52 return err 53 } 54 55 func someIntermediateFunc(vals ...int) error { 56 errch := make(chan error) 57 go func() { 58 defer close(errch) 59 errch <- Annotate(errorWrapper(someLibFunc(vals...)), "could not process").Err() 60 }() 61 me := MultiError(nil) 62 for err := range errch { 63 if err != nil { 64 me = append(me, err) 65 } 66 } 67 if me != nil { 68 return Annotate(me, "while processing %v", vals).Err() 69 } 70 return nil 71 } 72 73 func ExampleAnnotate() { 74 if err := someIntermediateFunc(3); err != nil { 75 err = Annotate(err, "top level").Err() 76 fmt.Println("Public-facing error:\n ", err) 77 fmt.Println("\nfull error:") 78 for _, l := range FixForTest(RenderStack(err, "runtime", "_test")) { 79 fmt.Println(l) 80 } 81 } 82 83 // Output: 84 // Public-facing error: 85 // top level: while processing [3]: could not process: super wrapper(processing 3: bad number: 1) 86 // 87 // full error: 88 // original error: bad number: 1 89 // 90 // GOROUTINE LINE 91 // #? go.chromium.org/luci/common/errors/annotate_example_test.go:24 - errors.someProcessingFunction() 92 // reason: bad number: 1 93 // 94 // #? go.chromium.org/luci/common/errors/annotate_example_test.go:26 - errors.someProcessingFunction() 95 // internal reason: val(2) 96 // 97 // #? go.chromium.org/luci/common/errors/annotate_example_test.go:26 - errors.someProcessingFunction() 98 // internal reason: val(3) 99 // 100 // From frame 2 to 3, the following wrappers were found: 101 // unknown wrapper *errors.MiscWrappedError 102 // 103 // #? go.chromium.org/luci/common/errors/annotate_example_test.go:35 - errors.someLibFunc() 104 // reason: processing 3 105 // internal reason: secret(value)/i(0) 106 // 107 // From frame 3 to 4, the following wrappers were found: 108 // internal reason: MultiError 1/1: following first non-nil error. 109 // 110 // #? go.chromium.org/luci/common/errors/annotate_example_test.go:59 - errors.someIntermediateFunc.func1() 111 // reason: could not process 112 // 113 // ... skipped SOME frames in pkg "runtime"... 114 // 115 // GOROUTINE LINE 116 // #? go.chromium.org/luci/common/errors/annotate_example_test.go:68 - errors.someIntermediateFunc() 117 // reason: while processing [3] 118 // 119 // #? go.chromium.org/luci/common/errors/annotate_example_test.go:74 - errors.ExampleAnnotate() 120 // reason: top level 121 // 122 // #? testing/run_example.go:XXX - testing.runExample() 123 // #? testing/example.go:XXX - testing.runExamples() 124 // #? testing/testing.go:XXX - testing.(*M).Run() 125 // #? ./_testmain.go:XXX - main.main() 126 // ... skipped SOME frames in pkg "runtime"... 127 }