cli: add flag to enforce timestamps logging

The solution described in #3358 is not acceptable for debugging.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
Anna Shaleva 2025-03-21 14:46:48 +03:00
parent 3e54c46281
commit 3b2be8384c
7 changed files with 38 additions and 24 deletions

View file

@ -157,6 +157,14 @@ var Debug = &cli.BoolFlag{
Usage: "Enable debug logging (LOTS of output, overrides configuration)", Usage: "Enable debug logging (LOTS of output, overrides configuration)",
} }
// ForceTimestampLogs is a flag for commands that run the node. This flag
// enables timestamp logging for every log record even if program is running
// not in terminal.
var ForceTimestampLogs = &cli.BoolFlag{
Name: "force-timestamp-logs",
Usage: "Enable timestamps for log entries",
}
var errInvalidHistoric = errors.New("invalid 'historic' parameter, neither a block number, nor a block/state hash") var errInvalidHistoric = errors.New("invalid 'historic' parameter, neither a block number, nor a block/state hash")
var errNoWallet = errors.New("no wallet parameter found, specify it with the '--wallet' or '-w' flag or specify wallet config file with the '--wallet-config' flag") var errNoWallet = errors.New("no wallet parameter found, specify it with the '--wallet' or '-w' flag or specify wallet config file with the '--wallet-config' flag")
var errConflictingWalletFlags = errors.New("--wallet flag conflicts with --wallet-config flag, please, provide one of them to specify wallet location") var errConflictingWalletFlags = errors.New("--wallet flag conflicts with --wallet-config flag, please, provide one of them to specify wallet location")
@ -285,7 +293,7 @@ var (
// If logPath is configured on Windows -- function returns closer to be // If logPath is configured on Windows -- function returns closer to be
// able to close sink for the opened log output file. // able to close sink for the opened log output file.
// If the program is run in TTY then logger adds timestamp to its entries. // If the program is run in TTY then logger adds timestamp to its entries.
func HandleLoggingParams(debug bool, cfg config.ApplicationConfiguration) (*zap.Logger, *zap.AtomicLevel, func() error, error) { func HandleLoggingParams(ctx *cli.Context, cfg config.ApplicationConfiguration) (*zap.Logger, *zap.AtomicLevel, func() error, error) {
var ( var (
level = zapcore.InfoLevel level = zapcore.InfoLevel
err error err error
@ -296,7 +304,7 @@ func HandleLoggingParams(debug bool, cfg config.ApplicationConfiguration) (*zap.
return nil, nil, nil, fmt.Errorf("log setting: %w", err) return nil, nil, nil, fmt.Errorf("log setting: %w", err)
} }
} }
if debug { if ctx != nil && ctx.Bool("debug") {
level = zapcore.DebugLevel level = zapcore.DebugLevel
} }
@ -305,7 +313,7 @@ func HandleLoggingParams(debug bool, cfg config.ApplicationConfiguration) (*zap.
cc.DisableStacktrace = true cc.DisableStacktrace = true
cc.EncoderConfig.EncodeDuration = zapcore.StringDurationEncoder cc.EncoderConfig.EncodeDuration = zapcore.StringDurationEncoder
cc.EncoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder cc.EncoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
if term.IsTerminal(int(os.Stdout.Fd())) { if term.IsTerminal(int(os.Stdout.Fd())) || (ctx != nil && ctx.Bool("force-timestamp-logs")) {
cc.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder cc.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
} else { } else {
cc.EncoderConfig.EncodeTime = func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {} cc.EncoderConfig.EncodeTime = func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {}

View file

@ -20,7 +20,7 @@ func dumpBin(ctx *cli.Context) error {
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }
log, _, logCloser, err := options.HandleLoggingParams(ctx.Bool("debug"), cfg.ApplicationConfiguration) log, _, logCloser, err := options.HandleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }

View file

@ -39,7 +39,7 @@ func NewCommands() []*cli.Command {
cfgFlags = append(cfgFlags, options.Network...) cfgFlags = append(cfgFlags, options.Network...)
var cfgWithCountFlags = slices.Clone(cfgFlags) var cfgWithCountFlags = slices.Clone(cfgFlags)
cfgFlags = append(cfgFlags, options.Debug) cfgFlags = append(cfgFlags, options.Debug, options.ForceTimestampLogs)
cfgWithCountFlags = append(cfgWithCountFlags, cfgWithCountFlags = append(cfgWithCountFlags,
&cli.UintFlag{ &cli.UintFlag{
Name: "count", Name: "count",
@ -87,7 +87,7 @@ func NewCommands() []*cli.Command {
{ {
Name: "node", Name: "node",
Usage: "Start a NeoGo node", Usage: "Start a NeoGo node",
UsageText: "neo-go node [--config-path path] [-d] [-p/-m/-t] [--config-file file]", UsageText: "neo-go node [--config-path path] [-d] [-p/-m/-t] [--config-file file] [--force-timestamp-logs]",
Action: startServer, Action: startServer,
Flags: cfgFlags, Flags: cfgFlags,
}, },
@ -98,28 +98,28 @@ func NewCommands() []*cli.Command {
{ {
Name: "dump", Name: "dump",
Usage: "Dump blocks (starting with the genesis or specified block) to the file", Usage: "Dump blocks (starting with the genesis or specified block) to the file",
UsageText: "neo-go db dump [-o file] [-s start] [-c count] [--config-path path] [-p/-m/-t] [--config-file file]", UsageText: "neo-go db dump [-o file] [-s start] [-c count] [--config-path path] [-p/-m/-t] [--config-file file] [--force-timestamp-logs]",
Action: dumpDB, Action: dumpDB,
Flags: cfgCountOutFlags, Flags: cfgCountOutFlags,
}, },
{ {
Name: "dump-bin", Name: "dump-bin",
Usage: "Dump blocks (starting with the genesis or specified block) to the directory in binary format", Usage: "Dump blocks (starting with the genesis or specified block) to the directory in binary format",
UsageText: "neo-go db dump-bin -o directory [-s start] [-c count] [--config-path path] [-p/-m/-t] [--config-file file]", UsageText: "neo-go db dump-bin -o directory [-s start] [-c count] [--config-path path] [-p/-m/-t] [--config-file file] [--force-timestamp-logs]",
Action: dumpBin, Action: dumpBin,
Flags: cfgCountOutFlags, Flags: cfgCountOutFlags,
}, },
{ {
Name: "restore", Name: "restore",
Usage: "Restore blocks from the file", Usage: "Restore blocks from the file",
UsageText: "neo-go db restore [-i file] [--dump] [-n] [-c count] [--config-path path] [-p/-m/-t] [--config-file file]", UsageText: "neo-go db restore [-i file] [--dump] [-n] [-c count] [--config-path path] [-p/-m/-t] [--config-file file] [--force-timestamp-logs]",
Action: restoreDB, Action: restoreDB,
Flags: cfgCountInFlags, Flags: cfgCountInFlags,
}, },
{ {
Name: "reset", Name: "reset",
Usage: "Reset database to the previous state", Usage: "Reset database to the previous state",
UsageText: "neo-go db reset --height height [--config-path path] [-p/-m/-t] [--config-file file]", UsageText: "neo-go db reset --height height [--config-path path] [-p/-m/-t] [--config-file file] [--force-timestamp-logs]",
Action: resetDB, Action: resetDB,
Flags: cfgHeightFlags, Flags: cfgHeightFlags,
}, },
@ -170,7 +170,7 @@ func dumpDB(ctx *cli.Context) error {
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }
log, _, logCloser, err := options.HandleLoggingParams(ctx.Bool("debug"), cfg.ApplicationConfiguration) log, _, logCloser, err := options.HandleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }
@ -226,7 +226,7 @@ func restoreDB(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
log, _, logCloser, err := options.HandleLoggingParams(ctx.Bool("debug"), cfg.ApplicationConfiguration) log, _, logCloser, err := options.HandleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }
@ -345,7 +345,7 @@ func resetDB(ctx *cli.Context) error {
} }
h := uint32(ctx.Uint("height")) h := uint32(ctx.Uint("height"))
log, _, logCloser, err := options.HandleLoggingParams(ctx.Bool("debug"), cfg.ApplicationConfiguration) log, _, logCloser, err := options.HandleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }
@ -455,7 +455,7 @@ func startServer(ctx *cli.Context) error {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }
var logDebug = ctx.Bool("debug") var logDebug = ctx.Bool("debug")
log, logLevel, logCloser, err := options.HandleLoggingParams(logDebug, cfg.ApplicationConfiguration) log, logLevel, logCloser, err := options.HandleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }

View file

@ -88,6 +88,9 @@ func TestGetConfigFromContext(t *testing.T) {
func TestHandleLoggingParams(t *testing.T) { func TestHandleLoggingParams(t *testing.T) {
d := t.TempDir() d := t.TempDir()
testLog := filepath.Join(d, "file.log") testLog := filepath.Join(d, "file.log")
set := flag.NewFlagSet("flagSet", flag.ExitOnError)
debug := set.Bool("debug", false, "")
ctx := cli.NewContext(cli.NewApp(), set, nil)
t.Run("logdir is a file", func(t *testing.T) { t.Run("logdir is a file", func(t *testing.T) {
logfile := filepath.Join(d, "logdir") logfile := filepath.Join(d, "logdir")
@ -95,7 +98,7 @@ func TestHandleLoggingParams(t *testing.T) {
cfg := config.ApplicationConfiguration{ cfg := config.ApplicationConfiguration{
LogPath: filepath.Join(logfile, "file.log"), LogPath: filepath.Join(logfile, "file.log"),
} }
_, lvl, closer, err := options.HandleLoggingParams(false, cfg) _, lvl, closer, err := options.HandleLoggingParams(ctx, cfg)
require.Error(t, err) require.Error(t, err)
require.Nil(t, lvl) require.Nil(t, lvl)
require.Nil(t, closer) require.Nil(t, closer)
@ -106,7 +109,7 @@ func TestHandleLoggingParams(t *testing.T) {
LogPath: testLog, LogPath: testLog,
LogLevel: "qwerty", LogLevel: "qwerty",
} }
_, lvl, closer, err := options.HandleLoggingParams(false, cfg) _, lvl, closer, err := options.HandleLoggingParams(ctx, cfg)
require.Error(t, err) require.Error(t, err)
require.Nil(t, lvl) require.Nil(t, lvl)
require.Nil(t, closer) require.Nil(t, closer)
@ -116,7 +119,7 @@ func TestHandleLoggingParams(t *testing.T) {
cfg := config.ApplicationConfiguration{ cfg := config.ApplicationConfiguration{
LogPath: testLog, LogPath: testLog,
} }
logger, lvl, closer, err := options.HandleLoggingParams(false, cfg) logger, lvl, closer, err := options.HandleLoggingParams(ctx, cfg)
require.NotNil(t, lvl) require.NotNil(t, lvl)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
@ -134,7 +137,7 @@ func TestHandleLoggingParams(t *testing.T) {
LogPath: testLog, LogPath: testLog,
LogLevel: "warn", LogLevel: "warn",
} }
logger, lvl, closer, err := options.HandleLoggingParams(false, cfg) logger, lvl, closer, err := options.HandleLoggingParams(ctx, cfg)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
if closer != nil { if closer != nil {
@ -150,7 +153,9 @@ func TestHandleLoggingParams(t *testing.T) {
cfg := config.ApplicationConfiguration{ cfg := config.ApplicationConfiguration{
LogPath: testLog, LogPath: testLog,
} }
logger, lvl, closer, err := options.HandleLoggingParams(true, cfg) *debug = true
t.Cleanup(func() { *debug = false })
logger, lvl, closer, err := options.HandleLoggingParams(ctx, cfg)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
if closer != nil { if closer != nil {
@ -176,7 +181,7 @@ func TestInitBCWithMetrics(t *testing.T) {
ctx := cli.NewContext(cli.NewApp(), set, nil) ctx := cli.NewContext(cli.NewApp(), set, nil)
cfg, err := options.GetConfigFromContext(ctx) cfg, err := options.GetConfigFromContext(ctx)
require.NoError(t, err) require.NoError(t, err)
logger, _, closer, err := options.HandleLoggingParams(true, cfg.ApplicationConfiguration) logger, _, closer, err := options.HandleLoggingParams(ctx, cfg.ApplicationConfiguration)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
if closer != nil { if closer != nil {

View file

@ -87,6 +87,7 @@ func NewCommands() []*cli.Command {
Value: 20, Value: 20,
}, },
options.Debug, options.Debug,
options.ForceTimestampLogs,
}, options.RPC...) }, options.RPC...)
uploadBinFlags = append(uploadBinFlags, options.Wallet...) uploadBinFlags = append(uploadBinFlags, options.Wallet...)
uploadBinFlags = append(uploadBinFlags, neoFSFlags...) uploadBinFlags = append(uploadBinFlags, neoFSFlags...)
@ -98,7 +99,7 @@ func NewCommands() []*cli.Command {
Value: neofs.DefaultStateAttribute, Value: neofs.DefaultStateAttribute,
Action: cmdargs.EnsureNotEmpty("state-attribute"), Action: cmdargs.EnsureNotEmpty("state-attribute"),
}, },
options.Debug, options.Config, options.ConfigFile, options.RelativePath, options.Debug, options.ForceTimestampLogs, options.Config, options.ConfigFile, options.RelativePath,
}, options.Wallet...) }, options.Wallet...)
uploadStateFlags = append(uploadStateFlags, options.Network...) uploadStateFlags = append(uploadStateFlags, options.Network...)
uploadStateFlags = append(uploadStateFlags, neoFSFlags...) uploadStateFlags = append(uploadStateFlags, neoFSFlags...)
@ -189,7 +190,7 @@ func NewCommands() []*cli.Command {
{ {
Name: "upload-state", Name: "upload-state",
Usage: "Start the node, traverse MPT and upload MPT nodes to the NeoFS container at every StateSyncInterval number of blocks", Usage: "Start the node, traverse MPT and upload MPT nodes to the NeoFS container at every StateSyncInterval number of blocks",
UsageText: "neo-go util upload-state --fs-rpc-endpoint <address1>[,<address2>[...]] --container <cid> --state-attribute state --wallet <wallet> [--wallet-config <config>] [--address <address>] [--searchers <num>] [--retries <num>] [--debug] [--config-path path] [-p/-m/-t] [--config-file file]", UsageText: "neo-go util upload-state --fs-rpc-endpoint <address1>[,<address2>[...]] --container <cid> --state-attribute state --wallet <wallet> [--wallet-config <config>] [--address <address>] [--searchers <num>] [--retries <num>] [--debug] [--config-path path] [-p/-m/-t] [--config-file file] [--force-timestamp-logs]",
Action: uploadState, Action: uploadState,
Flags: uploadStateFlags, Flags: uploadStateFlags,
}, },

View file

@ -45,7 +45,7 @@ func uploadState(ctx *cli.Context) error {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }
defer p.Close() defer p.Close()
log, _, logCloser, err := options.HandleLoggingParams(debug, cfg.ApplicationConfiguration) log, _, logCloser, err := options.HandleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil { if err != nil {
return cli.Exit(err, 1) return cli.Exit(err, 1)
} }

View file

@ -480,7 +480,7 @@ 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) log, _, logCloser, err := options.HandleLoggingParams(nil, cfg.ApplicationConfiguration)
if err != nil { if err != nil {
return nil, cli.Exit(fmt.Errorf("failed to init logger: %w", err), 1) return nil, cli.Exit(fmt.Errorf("failed to init logger: %w", err), 1)
} }