feat: make logger easily replaceable (#15358)
This commit is contained in:
parent
1ac260cb1c
commit
abd4ac0790
@ -62,6 +62,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Improvements
|
||||
|
||||
* (server) [#15358](https://github.com/cosmos/cosmos-sdk/pull/15358) Add `server.InterceptConfigsAndCreateContext` as alternative to `server.InterceptConfigsPreRunHandler` which does not set the server context and the default SDK logger.
|
||||
* [#15011](https://github.com/cosmos/cosmos-sdk/pull/15011) Introduce `cosmossdk.io/log` package to provide a consistent logging interface through the SDK. CometBFT logger is now replaced by `cosmossdk.io/log.Logger`.
|
||||
* (x/auth) [#14758](https://github.com/cosmos/cosmos-sdk/pull/14758) Allow transaction event queries to directly passed to Tendermint, which will allow for full query operator support, e.g. `>`.
|
||||
* (server) [#15041](https://github.com/cosmos/cosmos-sdk/pull/15041) Remove unnecessary sleeps from gRPC and API server initiation. The servers will start and accept requests as soon as they're ready.
|
||||
@ -95,6 +96,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
* (server) [#15358](https://github.com/cosmos/cosmos-sdk/pull/15358) Remove `server.ErrorCode` that was not used anywhere.
|
||||
* [#15211](https://github.com/cosmos/cosmos-sdk/pull/15211) Remove usage of `github.com/cometbft/cometbft/libs/bytes.HexBytes` in favor of `[]byte` thorough the SDK.
|
||||
* [#15011](https://github.com/cosmos/cosmos-sdk/pull/15011) All functions that were taking a CometBFT logger, now take `cosmossdk.io/log.Logger` instead.
|
||||
* (x/auth) [#14758](https://github.com/cosmos/cosmos-sdk/pull/14758) Refactor transaction searching:
|
||||
|
||||
@ -168,4 +168,28 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/simapp/simd/cmd/root.go#L6
|
||||
|
||||
The `SetCmdClientContextHandler` call reads persistent flags via `ReadPersistentCommandFlags` which creates a `client.Context` and sets that on the root command's `Context`.
|
||||
|
||||
The `InterceptConfigsPreRunHandler` call creates a viper literal, default `server.Context`, and a logger and sets that on the root command's `Context`. The `server.Context` will be modified and saved to disk via the internal `interceptConfigs` call, which either reads or creates a Tendermint configuration based on the home path provided. In addition, `interceptConfigs` also reads and loads the application configuration, `app.toml`, and binds that to the `server.Context` viper literal. This is vital so the application can get access to not only the CLI flags, but also to the application configuration values provided by this file.
|
||||
The `InterceptConfigsPreRunHandler` call creates a viper literal, default `server.Context`, and a logger and sets that on the root command's `Context`. The `server.Context` will be modified and saved to disk. The internal `interceptConfigs` call reads or creates a Tendermint configuration based on the home path provided. In addition, `interceptConfigs` also reads and loads the application configuration, `app.toml`, and binds that to the `server.Context` viper literal. This is vital so the application can get access to not only the CLI flags, but also to the application configuration values provided by this file.
|
||||
|
||||
:::tip
|
||||
When willing to configure which logger is used, do not to use `InterceptConfigsPreRunHandler`, which sets the default SDK logger, but instead use `InterceptConfigsAndCreateContext` and set the server context and the logger manually:
|
||||
|
||||
```diff
|
||||
-return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customCMTConfig)
|
||||
|
||||
+serverCtx, err := server.InterceptConfigsAndCreateContext(cmd, customAppTemplate, customAppConfig, customCMTConfig)
|
||||
+if err != nil {
|
||||
+ return err
|
||||
+}
|
||||
|
||||
+// overwrite default server logger
|
||||
+logger, err := server.CreateSDKLogger(serverCtx, cmd.OutOrStdout())
|
||||
+if err != nil {
|
||||
+ return err
|
||||
+}
|
||||
+serverCtx.Logger = logger.With(log.ModuleKey, "server")
|
||||
|
||||
+// set server context
|
||||
+return server.SetCmdServerContext(cmd, serverCtx)
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Requests for Comments
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"os/signal"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@ -51,20 +50,11 @@ type Context struct {
|
||||
Logger log.Logger
|
||||
}
|
||||
|
||||
// ErrorCode contains the exit code for server exit.
|
||||
type ErrorCode struct {
|
||||
Code int
|
||||
}
|
||||
|
||||
func (e ErrorCode) Error() string {
|
||||
return strconv.Itoa(e.Code)
|
||||
}
|
||||
|
||||
func NewDefaultContext() *Context {
|
||||
return NewContext(
|
||||
viper.New(),
|
||||
cmtcfg.DefaultConfig(),
|
||||
log.NewLogger(os.Stdout), // TODO(mr): update NewDefaultContext to accept log destination.
|
||||
log.NewLogger(os.Stdout),
|
||||
)
|
||||
}
|
||||
|
||||
@ -106,7 +96,26 @@ func bindFlags(basename string, cmd *cobra.Command, v *viper.Viper) (err error)
|
||||
return err
|
||||
}
|
||||
|
||||
// InterceptConfigsPreRunHandler performs a pre-run function for the root daemon
|
||||
// InterceptConfigsPreRunHandler is identical to InterceptConfigsAndCreateContext
|
||||
// except it also sets the server context on the command and the server logger.
|
||||
func InterceptConfigsPreRunHandler(cmd *cobra.Command, customAppConfigTemplate string, customAppConfig interface{}, cmtConfig *cmtcfg.Config) error {
|
||||
serverCtx, err := InterceptConfigsAndCreateContext(cmd, customAppConfigTemplate, customAppConfig, cmtConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// overwrite default server logger
|
||||
logger, err := CreateSDKLogger(serverCtx, cmd.OutOrStdout())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverCtx.Logger = logger.With(log.ModuleKey, "server")
|
||||
|
||||
// set server context
|
||||
return SetCmdServerContext(cmd, serverCtx)
|
||||
}
|
||||
|
||||
// InterceptConfigsAndCreateContext performs a pre-run function for the root daemon
|
||||
// application command. It will create a Viper literal and a default server
|
||||
// Context. The server CometBFT configuration will either be read and parsed
|
||||
// or created and saved to disk, where the server Context is updated to reflect
|
||||
@ -116,7 +125,7 @@ func bindFlags(basename string, cmd *cobra.Command, v *viper.Viper) (err error)
|
||||
// is used to read and parse the application configuration. Command handlers can
|
||||
// fetch the server Context to get the CometBFT configuration or to get access
|
||||
// to Viper.
|
||||
func InterceptConfigsPreRunHandler(cmd *cobra.Command, customAppConfigTemplate string, customAppConfig interface{}, cmtConfig *cmtcfg.Config) error {
|
||||
func InterceptConfigsAndCreateContext(cmd *cobra.Command, customAppConfigTemplate string, customAppConfig interface{}, cmtConfig *cmtcfg.Config) (*Context, error) {
|
||||
serverCtx := NewDefaultContext()
|
||||
|
||||
// Get the executable name and configure the viper instance so that environmental
|
||||
@ -124,17 +133,17 @@ func InterceptConfigsPreRunHandler(cmd *cobra.Command, customAppConfigTemplate s
|
||||
// as a separator.
|
||||
executableName, err := os.Executable()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
basename := path.Base(executableName)
|
||||
|
||||
// configure the viper instance
|
||||
if err := serverCtx.Viper.BindPFlags(cmd.Flags()); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if err := serverCtx.Viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverCtx.Viper.SetEnvPrefix(basename)
|
||||
@ -144,31 +153,37 @@ func InterceptConfigsPreRunHandler(cmd *cobra.Command, customAppConfigTemplate s
|
||||
// intercept configuration files, using both Viper instances separately
|
||||
config, err := interceptConfigs(serverCtx.Viper, customAppConfigTemplate, customAppConfig, cmtConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return value is a CometBFT configuration object
|
||||
serverCtx.Config = config
|
||||
if err = bindFlags(basename, cmd, serverCtx.Viper); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serverCtx, nil
|
||||
}
|
||||
|
||||
// CreateSDKLogger creates a the default SDK logger.
|
||||
// It reads the log level and format from the server context.
|
||||
func CreateSDKLogger(ctx *Context, out io.Writer) (log.Logger, error) {
|
||||
var logger log.Logger
|
||||
if serverCtx.Viper.GetString(flags.FlagLogFormat) == cmtcfg.LogFormatJSON {
|
||||
zl := zerolog.New(cmd.OutOrStdout()).With().Timestamp().Logger()
|
||||
if ctx.Viper.GetString(flags.FlagLogFormat) == cmtcfg.LogFormatJSON {
|
||||
zl := zerolog.New(out).With().Timestamp().Logger()
|
||||
logger = log.NewCustomLogger(zl)
|
||||
} else {
|
||||
logger = log.NewLogger(cmd.OutOrStdout())
|
||||
logger = log.NewLogger(out)
|
||||
}
|
||||
|
||||
// set filter level or keys for the logger if any
|
||||
logLvlStr := serverCtx.Viper.GetString(flags.FlagLogLevel)
|
||||
logLvlStr := ctx.Viper.GetString(flags.FlagLogLevel)
|
||||
logLvl, err := zerolog.ParseLevel(logLvlStr)
|
||||
if err != nil {
|
||||
// If the log level is not a valid zerolog level, then we try to parse it as a key filter.
|
||||
filterFunc, err := log.ParseLogLevel(logLvlStr, zerolog.InfoLevel.String())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse log level (%s): %w", logLvlStr, err)
|
||||
return nil, fmt.Errorf("failed to parse log level (%s): %w", logLvlStr, err)
|
||||
}
|
||||
|
||||
logger = log.FilterKeys(logger, filterFunc)
|
||||
@ -176,16 +191,14 @@ func InterceptConfigsPreRunHandler(cmd *cobra.Command, customAppConfigTemplate s
|
||||
zl := logger.Impl().(*zerolog.Logger)
|
||||
// Check if the CometBFT flag for trace logging is set if it is then setup a tracing logger in this app as well.
|
||||
// Note it overrides log level passed in `log_levels`.
|
||||
if serverCtx.Viper.GetBool(cmtcli.TraceFlag) {
|
||||
if ctx.Viper.GetBool(cmtcli.TraceFlag) {
|
||||
logger = log.NewCustomLogger(zl.Level(zerolog.TraceLevel))
|
||||
} else {
|
||||
logger = log.NewCustomLogger(zl.Level(logLvl))
|
||||
}
|
||||
}
|
||||
|
||||
serverCtx.Logger = logger.With("module", "server")
|
||||
|
||||
return SetCmdServerContext(cmd, serverCtx)
|
||||
return logger, nil
|
||||
}
|
||||
|
||||
// GetServerContextFromCmd returns a Context from a command or an empty Context
|
||||
|
||||
@ -30,8 +30,7 @@ var errCanceledInPreRun = errors.New("canceled in prerun")
|
||||
// Used in each test to run the function under test via Cobra
|
||||
// but to always halt the command
|
||||
func preRunETestImpl(cmd *cobra.Command, args []string) error {
|
||||
err := server.InterceptConfigsPreRunHandler(cmd, "", nil, cmtcfg.DefaultConfig())
|
||||
if err != nil {
|
||||
if err := server.InterceptConfigsPreRunHandler(cmd, "", nil, cmtcfg.DefaultConfig()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -435,7 +434,12 @@ func TestEmptyMinGasPrices(t *testing.T) {
|
||||
// Run StartCmd.
|
||||
cmd = server.StartCmd(nil, tempDir)
|
||||
cmd.PreRunE = func(cmd *cobra.Command, _ []string) error {
|
||||
return server.InterceptConfigsPreRunHandler(cmd, "", nil, cmtcfg.DefaultConfig())
|
||||
ctx, err := server.InterceptConfigsAndCreateContext(cmd, "", nil, cmtcfg.DefaultConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return server.SetCmdServerContext(cmd, ctx)
|
||||
}
|
||||
err = cmd.ExecuteContext(ctx)
|
||||
require.Errorf(t, err, sdkerrors.ErrAppConfig.Error())
|
||||
|
||||
@ -1,23 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
"cosmossdk.io/simapp/simd/cmd"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rootCmd := cmd.NewRootCmd()
|
||||
if err := svrcmd.Execute(rootCmd, "", simapp.DefaultNodeHome); err != nil {
|
||||
switch e := err.(type) {
|
||||
case server.ErrorCode:
|
||||
os.Exit(e.Code)
|
||||
|
||||
default:
|
||||
os.Exit(1)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user