From 95cbddf19e7ddd2872f22b5e5a2d302cdfefa215 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 7 Oct 2022 15:27:24 +0300 Subject: [PATCH] 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!"} [] ``` --- cli/options/filtering_core.go | 28 ++++++++++++++++++++++++++++ cli/vm/cli.go | 21 +++++++++++++++++++-- pkg/core/interop/runtime/engine.go | 5 ++++- 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 cli/options/filtering_core.go diff --git a/cli/options/filtering_core.go b/cli/options/filtering_core.go new file mode 100644 index 000000000..4dd0ad245 --- /dev/null +++ b/cli/options/filtering_core.go @@ -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 +} diff --git a/cli/vm/cli.go b/cli/vm/cli.go index 3f5eb5e2e..1a71dcfe3 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -19,10 +19,12 @@ import ( "github.com/chzyer/readline" "github.com/kballard/go-shellquote" "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/config" "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/runtime" "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/crypto/keys" @@ -37,6 +39,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/urfave/cli" "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) const ( @@ -392,13 +395,27 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg 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) { _ = store.Close() + if logCloser != nil { + _ = logCloser() + } onExit(i) } - log := zap.NewNop() - chain, err := core.NewBlockchain(store, cfg.ProtocolConfiguration, log) + chain, err := core.NewBlockchain(store, cfg.ProtocolConfiguration, fLog) if err != nil { return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %w", err), 1) } diff --git a/pkg/core/interop/runtime/engine.go b/pkg/core/interop/runtime/engine.go index daadcda5a..42855c10a 100644 --- a/pkg/core/interop/runtime/engine.go +++ b/pkg/core/interop/runtime/engine.go @@ -19,6 +19,9 @@ const ( MaxEventNameLen = 32 // MaxNotificationSize is the maximum length of a runtime log message. MaxNotificationSize = 1024 + // SystemRuntimeLogMessage represents log entry message used for output + // of the System.Runtime.Log syscall. + SystemRuntimeLogMessage = "runtime log" ) // GetExecutingScriptHash returns executing script hash. @@ -112,7 +115,7 @@ func Log(ic *interop.Context) error { if ic.Tx != nil { txHash = ic.Tx.Hash().StringLE() } - ic.Log.Info("runtime log", + ic.Log.Info(SystemRuntimeLogMessage, zap.String("tx", txHash), zap.String("script", ic.VM.GetCurrentScriptHash().StringLE()), zap.String("msg", state))