Skip to content

Commit

Permalink
add ErrSilent wrapper when marshalling arguments and results
Browse files Browse the repository at this point in the history
  • Loading branch information
xhd2015 committed Apr 13, 2024
1 parent b950769 commit 861efeb
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 13 deletions.
4 changes: 2 additions & 2 deletions cmd/xgo/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package main
import "fmt"

const VERSION = "1.0.22"
const REVISION = "b41281e9fca79eb3bbde5e4347ab8f37763bc545+1"
const NUMBER = 176
const REVISION = "b95076921b299cab29e79a1642abf005462fb732+1"
const NUMBER = 177

func getRevision() string {
revSuffix := ""
Expand Down
4 changes: 2 additions & 2 deletions runtime/core/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

const VERSION = "1.0.22"
const REVISION = "b41281e9fca79eb3bbde5e4347ab8f37763bc545+1"
const NUMBER = 176
const REVISION = "b95076921b299cab29e79a1642abf005462fb732+1"
const NUMBER = 177

// these fields will be filled by compiler
const XGO_VERSION = ""
Expand Down
2 changes: 1 addition & 1 deletion runtime/test/trace/trace_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestMockedFuncShouldShowInTrace(t *testing.T) {
})
h()
})
data, err := trace.MarshalAnyJSON(root.Export())
data, err := trace.MarshalAnyJSON(root.Export(nil))
if err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 3 additions & 3 deletions runtime/trace/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ func MarshalAnyJSON(v interface{}) ([]byte, error) {
var err error
// mock the encoding json
trap.WithFuncOverride(newTypeEncoder, &trap.Interceptor{
Pre: func(ctx context.Context, f *core.FuncInfo, args, result core.Object) (interface{}, error) {
return nil, nil
},
// Pre: func(ctx context.Context, f *core.FuncInfo, args, result core.Object) (interface{}, error) {
// return nil, nil
// },
Post: func(ctx context.Context, f *core.FuncInfo, args, result core.Object, data interface{}) error {
if f != newTypeEncoder {
return nil
Expand Down
140 changes: 137 additions & 3 deletions runtime/trace/stack.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package trace

import (
"encoding/json"
"fmt"
"time"

"github.com/xhd2015/xgo/runtime/core"
Expand Down Expand Up @@ -30,21 +32,87 @@ type Stack struct {
//
// for example: google.golang.org/protobuf/internal/order
type ExportOptions struct {
// suppress error when marshalling
// arguments and results
DisableErrSilent bool
SizeLimit int // 0: default limit 4K
AppearanceLimit int // 0: default limit 100

FilterStack func(stack *StackExport) *StackExport

FilterRoot func(root *RootExport) *RootExport
MarshalJSON func(root *RootExport) ([]byte, error)
MarshalRoot func(root *RootExport) ([]byte, error)

stats map[string]map[string]*stat
}
type stat struct {
total int
current int
}

func (c *ExportOptions) getSizeLimit() int {
if c == nil || c.SizeLimit == 0 {
return 4 * 1024
}
return c.SizeLimit
}
func (c *ExportOptions) getAppearanceLimit() int {
if c == nil || c.AppearanceLimit == 0 {
return 100
}
return c.AppearanceLimit
}

func (c *Root) Export(opts *ExportOptions) *RootExport {
if c == nil {
return nil
}
if opts == nil {
opts = &ExportOptions{}
}
if opts.getAppearanceLimit() > 0 {
opts.stats = getStats(c)
}

return &RootExport{
Begin: c.Begin,
Children: (stacks)(c.Children).Export(opts),
}
}

func getStats(root *Root) map[string]map[string]*stat {
mapping := make(map[string]map[string]*stat)
var traverse func(stack *Stack)
traverse = func(st *Stack) {
if st == nil {
return
}
if st.FuncInfo != nil {
pkg := st.FuncInfo.Pkg
fn := st.FuncInfo.IdentityName
fnMapping := mapping[pkg]
if fnMapping == nil {
fnMapping = make(map[string]*stat)
mapping[pkg] = fnMapping
}
st := fnMapping[fn]
if st == nil {
st = &stat{}
fnMapping[fn] = st
}
st.total++
}

for _, st := range st.Children {
traverse(st)
}
}
for _, st := range root.Children {
traverse(st)
}
return mapping
}

type stacks []*Stack

func (c stacks) Export(opts *ExportOptions) []*StackExport {
Expand All @@ -58,6 +126,18 @@ func (c stacks) Export(opts *ExportOptions) []*StackExport {
if exportStack == nil {
continue
}
if exportStack.FuncInfo != nil && opts != nil && opts.stats != nil {
apprLimit := opts.getAppearanceLimit()
if apprLimit > 0 {
fnStat := opts.stats[exportStack.FuncInfo.Pkg][exportStack.FuncInfo.IdentityName]
if fnStat != nil && fnStat.total > apprLimit {
if fnStat.current >= apprLimit {
continue
}
fnStat.current++
}
}
}
list = append(list, exportStack)
}
return list
Expand All @@ -67,16 +147,29 @@ func (c *Stack) Export(opts *ExportOptions) *StackExport {
if c == nil {
return nil
}

var errMsg string
if c.Error != nil {
errMsg = c.Error.Error()
}
var args interface{} = c.Args
var results interface{} = c.Results

sizeLimit := opts.getSizeLimit()
if sizeLimit > 0 {
args = &LimitSize{args, sizeLimit}
results = &LimitSize{results, sizeLimit}
}
if opts == nil || !opts.DisableErrSilent {
args = &ErrSilent{args}
results = &ErrSilent{results}
}
stack := &StackExport{
FuncInfo: ExportFuncInfo(c.FuncInfo, opts),
Begin: c.Begin,
End: c.End,
Args: c.Args,
Results: c.Results,
Args: args,
Results: results,
Panic: c.Panic,
Error: errMsg,
Children: ((stacks)(c.Children)).Export(opts),
Expand Down Expand Up @@ -111,3 +204,44 @@ func ExportFuncInfo(c *core.FuncInfo, opts *ExportOptions) *FuncInfoExport {
Line: c.Line,
}
}

// make json err silent
type ErrSilent struct {
Data interface{}
}

func (c *ErrSilent) MarshalJSON() (data []byte, err error) {
defer func() {
if e := recover(); e != nil {
if pe, ok := e.(error); ok {
err = pe
} else {
err = fmt.Errorf("panic: %v", e)
}
}
if err != nil {
data = []byte(fmt.Sprintf(`{"error":%q}`, err.Error()))
err = nil
}
}()
data, err = json.Marshal(c.Data)
return
}

// make json err silent
type LimitSize struct {
Data interface{}
Limit int
}

func (c *LimitSize) MarshalJSON() ([]byte, error) {
data, err := json.Marshal(c.Data)
if err != nil {
return nil, err
}
if c.Limit <= 0 || c.Limit >= len(data) {
return data, nil
}
// shorten
return []byte(fmt.Sprintf(`{"size":%d, "sizeBeforeShrink":%d,"partialData":%q}`, c.Limit, len(data), string(data[:c.Limit]))), nil
}
4 changes: 2 additions & 2 deletions runtime/trace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,8 @@ func fmtStack(root *Root, opts *ExportOptions) (data []byte, err error) {
if opts.FilterRoot != nil {
exportRoot = opts.FilterRoot(exportRoot)
}
if opts.MarshalJSON != nil {
return opts.MarshalJSON(exportRoot)
if opts.MarshalRoot != nil {
return opts.MarshalRoot(exportRoot)
}
}
return MarshalAnyJSON(exportRoot)
Expand Down

0 comments on commit 861efeb

Please sign in to comment.