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 2 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")
Copy link
Contributor

@holiman holiman Sep 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expanded = regexp.MustCompile("[/\\.A-Za-z0-9_-]+").ReplaceAllString(expanded, "`$0` in Value")
expanded = regexp.MustCompile("!(`[/\\.A-Za-z0-9_-]+`)").ReplaceAllString(expanded, "$1 not")
expanded = regexp.MustCompile("[/\\:.A-Za-z0-9_-]+").ReplaceAllString(expanded, "`$0` in Value")
expanded = regexp.MustCompile("!(`[/\\:.A-Za-z0-9_-]+`)").ReplaceAllString(expanded, "$1 not")

For

> debug.stacks("console.go:419")
INFO [09-20|13:22:16.459] Expanded filter expression               filter=console.go:419 expanded="`console.go:419` in Value"
goroutine 140 [chan receive]:
github.com/ethereum/go-ethereum/console.(*Console).readLines(0xc000596310, 0xc0004566e8, 0xc000dc3ff0, 0xc0000bb7b0)
	github.com/ethereum/go-ethereum/console/console.go:419 +0x46
created by github.com/ethereum/go-ethereum/console.(*Console).Interactive
	github.com/ethereum/go-ethereum/console/console.go:363 +0x1ef

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just move the : to the front of the regexp. I think the - must be the last, otherwise it's interpreted as an interval i.e. from _ to :

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. THat's actually how I had it in my own code, but when I wrote the comment here I moved it. WCGW right? ;)

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