cli: use custom logger to filter out runtime.Log messages

```
anna@kiwi:~/Documents/GitProjects/nspcc-dev/neo-go$ ./bin/neo-go vm -p

    _   ____________        __________      _    ____  ___
   / | / / ____/ __ \      / ____/ __ \    | |  / /  |/  /
  /  |/ / __/ / / / /_____/ / __/ / / /____| | / / /|_/ /
 / /|  / /___/ /_/ /_____/ /_/ / /_/ /_____/ |/ / /  / /
/_/ |_/_____/\____/      \____/\____/      |___/_/  /_/

NEO-GO-VM > loadgo ./1-print/1-print.go
READY: loaded 21 instructions
NEO-GO-VM 0 > run
2022-10-07T15:28:20.461+0300	INFO	runtime log	{"tx": "", "script": "db03ceb3f672ee8cd0d714989b4d103ff7eed2f3", "msg": "Hello, world!"}
[]
```
This commit is contained in:
Anna Shaleva 2022-10-07 15:27:24 +03:00
parent b2cd007d8d
commit 95cbddf19e
3 changed files with 51 additions and 3 deletions

View file

@ -0,0 +1,28 @@
package options
import "go.uber.org/zap/zapcore"
// FilteringCore is custom implementation of zapcore.Core that allows to filter
// log entries using custom filtering function.
type FilteringCore struct {
zapcore.Core
filter FilterFunc
}
// FilterFunc is the filter function that is called to check whether the given
// entry together with the associated fields is to be written to a core or not.
type FilterFunc func(zapcore.Entry) bool
// NewFilteringCore returns a core middleware that uses the given filter function
// to decide whether to log this message or not.
func NewFilteringCore(next zapcore.Core, filter FilterFunc) zapcore.Core {
return &FilteringCore{next, filter}
}
// Check implements zapcore.Core interface and performs log entries filtering.
func (c *FilteringCore) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.filter(e) {
return c.Core.Check(e, ce)
}
return ce
}

View file

@ -19,10 +19,12 @@ import (
"github.com/chzyer/readline" "github.com/chzyer/readline"
"github.com/kballard/go-shellquote" "github.com/kballard/go-shellquote"
"github.com/nspcc-dev/neo-go/cli/flags" "github.com/nspcc-dev/neo-go/cli/flags"
"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig" "github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
@ -37,6 +39,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/urfave/cli" "github.com/urfave/cli"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore"
) )
const ( const (
@ -392,13 +395,27 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg
store = storage.NewMemoryStore() store = storage.NewMemoryStore()
} }
log, logCloser, err := options.HandleLoggingParams(false, cfg.ApplicationConfiguration)
if err != nil {
return nil, cli.NewExitError(fmt.Errorf("failed to init logger: %w", err), 1)
}
filter := zap.WrapCore(func(z zapcore.Core) zapcore.Core {
return options.NewFilteringCore(z, func(entry zapcore.Entry) bool {
// Log only Runtime.Notify messages.
return entry.Level == zapcore.InfoLevel && entry.Message == runtime.SystemRuntimeLogMessage
})
})
fLog := log.WithOptions(filter)
exitF := func(i int) { exitF := func(i int) {
_ = store.Close() _ = store.Close()
if logCloser != nil {
_ = logCloser()
}
onExit(i) onExit(i)
} }
log := zap.NewNop() chain, err := core.NewBlockchain(store, cfg.ProtocolConfiguration, fLog)
chain, err := core.NewBlockchain(store, cfg.ProtocolConfiguration, log)
if err != nil { if err != nil {
return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %w", err), 1) return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %w", err), 1)
} }

View file

@ -19,6 +19,9 @@ const (
MaxEventNameLen = 32 MaxEventNameLen = 32
// MaxNotificationSize is the maximum length of a runtime log message. // MaxNotificationSize is the maximum length of a runtime log message.
MaxNotificationSize = 1024 MaxNotificationSize = 1024
// SystemRuntimeLogMessage represents log entry message used for output
// of the System.Runtime.Log syscall.
SystemRuntimeLogMessage = "runtime log"
) )
// GetExecutingScriptHash returns executing script hash. // GetExecutingScriptHash returns executing script hash.
@ -112,7 +115,7 @@ func Log(ic *interop.Context) error {
if ic.Tx != nil { if ic.Tx != nil {
txHash = ic.Tx.Hash().StringLE() txHash = ic.Tx.Hash().StringLE()
} }
ic.Log.Info("runtime log", ic.Log.Info(SystemRuntimeLogMessage,
zap.String("tx", txHash), zap.String("tx", txHash),
zap.String("script", ic.VM.GetCurrentScriptHash().StringLE()), zap.String("script", ic.VM.GetCurrentScriptHash().StringLE()),
zap.String("msg", state)) zap.String("msg", state))