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

internal: support optional filter expression for debug.stacks #23605

Merged
merged 3 commits into from Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -35,6 +35,7 @@ require (
github.com/google/uuid v1.1.5
github.com/gorilla/websocket v1.4.2
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29
github.com/hashicorp/go-bexpr v0.1.10 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/holiman/bloomfilter/v2 v2.0.3
github.com/holiman/uint256 v1.2.0
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Expand Up @@ -216,6 +216,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 h1:sezaKhEfPFg8W0Enm61B9Gs911H8iesGY5R8NDPtd1M=
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
Expand Down Expand Up @@ -307,6 +309,10 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
Expand Down
40 changes: 38 additions & 2 deletions internal/debug/api.go
Expand Up @@ -27,6 +27,7 @@ import (
"os"
"os/user"
"path/filepath"
"regexp"
"runtime"
"runtime/debug"
"runtime/pprof"
Expand All @@ -35,6 +36,7 @@ import (
"time"

"github.com/ethereum/go-ethereum/log"
"github.com/hashicorp/go-bexpr"
)

// Handler is the global debugging handler.
Expand Down Expand Up @@ -189,10 +191,44 @@ func (*HandlerT) WriteMemProfile(file string) error {
return writeProfile("heap", file)
}

// Stacks returns a printed representation of the stacks of all goroutines.
func (*HandlerT) Stacks() string {
// Stacks returns a printed representation of the stacks of all goroutines. It
// also permits the following optional filters to be used:
// - filter: boolean expression of packages to filter for
func (*HandlerT) Stacks(filter *string) string {
buf := new(bytes.Buffer)
pprof.Lookup("goroutine").WriteTo(buf, 2)

// If any filtering was requested, execute them now
if filter != nil && len(*filter) > 0 {
expanded := *filter

// The input filter is a logical expression of package names. Transform
// it into a proper boolean expression that can be fed into a parser and
// interpreter:
//
// E.g. (eth || snap) && !p2p -> (eth in Value || snap in Value) && p2p not in Value
expanded = regexp.MustCompile("[:/\\.A-Za-z0-9_-]+").ReplaceAllString(expanded, "`$0` in Value")
expanded = regexp.MustCompile("!(`[:/\\.A-Za-z0-9_-]+`)").ReplaceAllString(expanded, "$1 not")
expanded = strings.Replace(expanded, "||", "or", -1)
expanded = strings.Replace(expanded, "&&", "and", -1)
log.Info("Expanded filter expression", "filter", *filter, "expanded", expanded)

expr, err := bexpr.CreateEvaluator(expanded)
if err != nil {
log.Error("Failed to parse filter expression", "expanded", expanded, "err", err)
return ""
}
// Split the goroutine dump into segments and filter each
dump := buf.String()
buf.Reset()

for _, trace := range strings.Split(dump, "\n\n") {
if ok, _ := expr.Evaluate(map[string]string{"Value": trace}); ok {
buf.WriteString(trace)
buf.WriteString("\n\n")
}
}
}
return buf.String()
}

Expand Down
3 changes: 2 additions & 1 deletion internal/web3ext/web3ext.go
Expand Up @@ -278,7 +278,8 @@ web3._extend({
new web3._extend.Method({
name: 'stacks',
call: 'debug_stacks',
params: 0,
params: 1,
inputFormatter: [null],
outputFormatter: console.log
}),
new web3._extend.Method({
Expand Down