forked from fl00r/go-tarantool-1.6
-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
api: support errors extended information
Since Tarantool 2.4.1, iproto error responses contain extended info with backtrace [1]. After this patch, Error would contain ExtendedInfo field (BoxError object), if it was provided. Error() handle now will print extended info, if possible. 1. https://www.tarantool.io/en/doc/latest/dev_guide/internals/box_protocol/#responses-for-errors Part of #209
- Loading branch information
1 parent
500da07
commit 3ebb1e9
Showing
8 changed files
with
359 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
package tarantool | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// BoxError is a type representing Tarantool `box.error` object: a single | ||
// MP_ERROR_STACK object with a link to the previous stack error. | ||
// See https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_error/error/ | ||
// | ||
// Since 1.10.0 | ||
type BoxError struct { | ||
// Type is error type that implies its source (for example, "ClientError"). | ||
Type string | ||
// File is a source code file where the error was caught. | ||
File string | ||
// Line is a number of line in the source code file where the error was caught. | ||
Line uint32 | ||
// Msg is the text of reason. | ||
Msg string | ||
// Errno is the ordinal number of the error. | ||
Errno uint32 | ||
// Code is the number of the error as defined in `errcode.h`. | ||
Code uint32 | ||
// Fields are additional fields depending on error type. For example, if | ||
// type is "AccessDeniedError", then it will include "object_type", | ||
// "object_name", "access_type". | ||
Fields map[interface{}]interface{} | ||
// Prev is the previous error in stack. | ||
Prev *BoxError | ||
} | ||
|
||
// Error converts a BoxError to a string. | ||
func (e *BoxError) Error() string { | ||
return fmt.Sprintf("%s (%s, code 0x%x), see %s:%d", | ||
e.Msg, e.Type, e.Code, e.File, e.Line) | ||
} | ||
|
||
// Depth computes the count of errors in stack, including the current one. | ||
func (e *BoxError) Depth() int { | ||
depth := int(0) | ||
|
||
cur := e | ||
for cur != nil { | ||
cur = cur.Prev | ||
depth++ | ||
} | ||
|
||
return depth | ||
} | ||
|
||
func decodeBoxError(d *decoder) (*BoxError, error) { | ||
var l, larr, l1, l2 int | ||
var errorStack []BoxError | ||
var err error | ||
|
||
if l, err = d.DecodeMapLen(); err != nil { | ||
return nil, err | ||
} | ||
|
||
for ; l > 0; l-- { | ||
var cd int | ||
if cd, err = d.DecodeInt(); err != nil { | ||
return nil, err | ||
} | ||
switch cd { | ||
case KeyErrorStack: | ||
if larr, err = d.DecodeArrayLen(); err != nil { | ||
return nil, err | ||
} | ||
|
||
errorStack = make([]BoxError, larr) | ||
|
||
for i := 0; i < larr; i++ { | ||
if l1, err = d.DecodeMapLen(); err != nil { | ||
return nil, err | ||
} | ||
|
||
for ; l1 > 0; l1-- { | ||
var cd1 int | ||
if cd1, err = d.DecodeInt(); err != nil { | ||
return nil, err | ||
} | ||
switch cd1 { | ||
case KeyErrorType: | ||
if errorStack[i].Type, err = d.DecodeString(); err != nil { | ||
return nil, err | ||
} | ||
case KeyErrorFile: | ||
if errorStack[i].File, err = d.DecodeString(); err != nil { | ||
return nil, err | ||
} | ||
case KeyErrorLine: | ||
if errorStack[i].Line, err = d.DecodeUint32(); err != nil { | ||
return nil, err | ||
} | ||
case KeyErrorMessage: | ||
if errorStack[i].Msg, err = d.DecodeString(); err != nil { | ||
return nil, err | ||
} | ||
case KeyErrorErrno: | ||
if errorStack[i].Errno, err = d.DecodeUint32(); err != nil { | ||
return nil, err | ||
} | ||
case KeyErrorErrcode: | ||
if errorStack[i].Code, err = d.DecodeUint32(); err != nil { | ||
return nil, err | ||
} | ||
case KeyErrorFields: | ||
var mapk, mapv interface{} | ||
|
||
errorStack[i].Fields = make(map[interface{}]interface{}) | ||
|
||
if l2, err = d.DecodeMapLen(); err != nil { | ||
return nil, err | ||
} | ||
for ; l2 > 0; l2-- { | ||
if mapk, err = d.DecodeInterface(); err != nil { | ||
return nil, err | ||
} | ||
if mapv, err = d.DecodeInterface(); err != nil { | ||
return nil, err | ||
} | ||
errorStack[i].Fields[mapk] = mapv | ||
} | ||
default: | ||
if err = d.Skip(); err != nil { | ||
return nil, err | ||
} | ||
} | ||
} | ||
|
||
if i > 0 { | ||
errorStack[i-1].Prev = &errorStack[i] | ||
} | ||
} | ||
default: | ||
if err = d.Skip(); err != nil { | ||
return nil, err | ||
} | ||
} | ||
} | ||
|
||
if len(errorStack) > 0 { | ||
return &errorStack[0], nil | ||
} | ||
|
||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.