From 314c7022d2d2d6541a77f19130ab8695f43855d7 Mon Sep 17 00:00:00 2001 From: Renato Maia <1887792+renatomaia@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:28:01 -0300 Subject: [PATCH 1/4] fix(jsonrpc): handle SIGTERM to shutdown JSON-RPC service --- cmd/cartesi-rollups-jsonrpc-api/root/root.go | 2 +- internal/jsonrpc/service.go | 62 +++++++++++++++++++- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/cmd/cartesi-rollups-jsonrpc-api/root/root.go b/cmd/cartesi-rollups-jsonrpc-api/root/root.go index 5768eba9b..4eda3ccd6 100644 --- a/cmd/cartesi-rollups-jsonrpc-api/root/root.go +++ b/cmd/cartesi-rollups-jsonrpc-api/root/root.go @@ -74,7 +74,7 @@ func run(cmd *cobra.Command, args []string) { Name: config.ServiceJsonrpc, LogLevel: config.ResolveServiceLogLevel(config.ServiceJsonrpc, cfg.LogLevel), LogColor: cfg.LogColor, - EnableSignalHandling: false, + EnableSignalHandling: true, TelemetryCreate: true, TelemetryAddress: cfg.TelemetryAddress, }, diff --git a/internal/jsonrpc/service.go b/internal/jsonrpc/service.go index 3a4c523fe..7f08532e4 100644 --- a/internal/jsonrpc/service.go +++ b/internal/jsonrpc/service.go @@ -5,7 +5,9 @@ package jsonrpc import ( "context" + "errors" "fmt" + "net" "net/http" "time" @@ -30,6 +32,9 @@ type Service struct { server *http.Server inputABI *abi.ABI outputABI *abi.ABI + // listen opens the HTTP listener. It defaults to net.Listen and is + // overridden in tests so Serve() can be exercised without real sockets. + listen func(network, address string) (net.Listener, error) } type CreateInfo struct { @@ -78,6 +83,9 @@ func Create(ctx context.Context, c *CreateInfo) (*Service, error) { ReadTimeout: 30 * time.Second, //nolint: mnd ReadHeaderTimeout: 10 * time.Second, //nolint: mnd } + if s.listen == nil { + s.listen = net.Listen + } return s, nil } @@ -102,6 +110,7 @@ func (s *Service) Tick() []error { func (s *Service) Stop(_ bool) []error { s.SetStopping() var errs []error + s.Logger.Info("Shutting down JSON-RPC HTTP server", "addr", s.server.Addr) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) //nolint: mnd defer cancel() if err := s.server.Shutdown(ctx); err != nil { @@ -115,6 +124,55 @@ func (s *Service) String() string { } func (s *Service) Serve() error { - s.Logger.Info("Listening", "addr", s.server.Addr) - return s.server.ListenAndServe() + listener, err := s.listen("tcp", s.server.Addr) + if err != nil { + return err + } + + s.Logger.Info("Listening", "addr", listener.Addr().String()) + + serverDone := make(chan error, 1) + go func() { + // Run the HTTP accept loop in parallel with the framework's lifecycle + // loop below. The lifecycle loop is the component that consumes + // SIGINT/SIGTERM and calls Stop() for graceful shutdown. + err := s.server.Serve(listener) + s.Logger.Info("Stopped listening", "addr", listener.Addr().String(), "err", err) + if errors.Is(err, http.ErrServerClosed) { + serverDone <- nil + return + } + serverDone <- err + }() + + serviceDone := make(chan error, 1) + go func() { + // Run the shared service loop concurrently because it blocks waiting + // for signals/context cancellation while the HTTP server blocks + // waiting for connections. + serviceDone <- s.Service.Serve() + }() + + select { + case err := <-serverDone: + // The HTTP loop exited first. This is unexpected unless the listener + // failed or the server was already closed, so cancel the framework + // loop and wait for it to observe the cancellation before returning. + s.Cancel() + serviceErr := <-serviceDone + if err != nil { + return err + } + return serviceErr + case err := <-serviceDone: + // The framework loop exited first because it handled a shutdown signal + // or context cancellation and called Stop(), which should trigger + // s.server.Shutdown(). Wait for the HTTP loop to finish so Serve() + // returns only after the listener is fully closed. + serverErr := <-serverDone + if serverErr != nil { + return serverErr + } + return err + } } From 1e435755aaec0f01d3bc5653d9c9da442751c53e Mon Sep 17 00:00:00 2001 From: Renato Maia <1887792+renatomaia@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:06:50 -0300 Subject: [PATCH 2/4] fix(services): show correct default values for CLI flags --- cmd/cartesi-rollups-advancer/root/root.go | 56 +++-- cmd/cartesi-rollups-claimer/root/root.go | 52 ++--- cmd/cartesi-rollups-evm-reader/root/root.go | 55 ++--- cmd/cartesi-rollups-jsonrpc-api/root/root.go | 36 ++-- cmd/cartesi-rollups-node/root/root.go | 129 +++++------- cmd/cartesi-rollups-prt/root/root.go | 32 ++- cmd/cartesi-rollups-validator/root/root.go | 32 ++- internal/cli/cobra.go | 30 +++ internal/config/generate/Config.toml | 49 ++++- internal/config/generate/code.go | 2 - internal/config/generated.go | 208 +++++++++++++------ 11 files changed, 382 insertions(+), 299 deletions(-) create mode 100644 internal/cli/cobra.go diff --git a/cmd/cartesi-rollups-advancer/root/root.go b/cmd/cartesi-rollups-advancer/root/root.go index c9b46c8b4..418e23bd4 100644 --- a/cmd/cartesi-rollups-advancer/root/root.go +++ b/cmd/cartesi-rollups-advancer/root/root.go @@ -7,13 +7,13 @@ import ( "context" "github.com/cartesi/rollups-node/internal/advancer" + "github.com/cartesi/rollups-node/internal/cli" "github.com/cartesi/rollups-node/internal/config" "github.com/cartesi/rollups-node/internal/repository/factory" "github.com/cartesi/rollups-node/internal/version" "github.com/cartesi/rollups-node/pkg/service" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -39,38 +39,30 @@ var Cmd = &cobra.Command{ } func init() { - Cmd.Flags().StringVar(&inspectAddress, "inspect-address", ":10012", "Inspect service address and port") - cobra.CheckErr(viper.BindPFlag(config.INSPECT_ADDRESS, Cmd.Flags().Lookup("inspect-address"))) - - Cmd.Flags().StringVar(&telemetryAddress, "telemetry-address", ":10002", "Health check and metrics address and port") - cobra.CheckErr(viper.BindPFlag(config.TELEMETRY_ADDRESS, Cmd.Flags().Lookup("telemetry-address"))) - - Cmd.Flags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn or error") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL, Cmd.Flags().Lookup("log-level"))) - - Cmd.Flags().BoolVar(&logColor, "log-color", true, "Tint the logs (colored output)") - cobra.CheckErr(viper.BindPFlag(config.LOG_COLOR, Cmd.Flags().Lookup("log-color"))) - - Cmd.Flags().StringVar(&databaseConnection, "database-connection", "", - "Database connection string in the URL format\n(eg.: 'postgres://user:password@hostname:port/database') ") - cobra.CheckErr(viper.BindPFlag(config.DATABASE_CONNECTION, Cmd.Flags().Lookup("database-connection"))) - - Cmd.Flags().StringVar(&pollInterval, "poll-interval", "7", "Poll interval") - cobra.CheckErr(viper.BindPFlag(config.ADVANCER_POLLING_INTERVAL, Cmd.Flags().Lookup("poll-interval"))) - - Cmd.Flags().StringVar(&maxStartupTime, "max-startup-time", "15", "Maximum startup time in seconds") - cobra.CheckErr(viper.BindPFlag(config.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time"))) - - Cmd.Flags().BoolVar(&enableInspect, "inspect-enabled", true, "Enable or disable the inspect service") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_INSPECT_ENABLED, Cmd.Flags().Lookup("inspect-enabled"))) - - Cmd.Flags().BoolVar(&enableMachineHashCheck, "machine-hash-check", true, + flags := Cmd.Flags() + + config.SetDefaults() + + cli.AddFlagStrVar(flags, &inspectAddress, "inspect-address", config.INSPECT_ADDRESS, + "Inspect service address and port") + cli.AddFlagStrVar(flags, &telemetryAddress, "telemetry-address", config.ADVANCER_TELEMETRY_ADDRESS, + "Health check and metrics address and port") + cli.AddFlagStrVar(flags, &logLevel, "log-level", config.LOG_LEVEL, + "Log level: debug, info, warn or error") + cli.AddFlagBoolVar(flags, &logColor, "log-color", config.LOG_COLOR, + "Tint the logs (colored output)") + cli.AddFlagStrVar(flags, &databaseConnection, "database-connection", config.DATABASE_CONNECTION, + "Database connection string in the URL format") + cli.AddFlagStrVar(flags, &pollInterval, "poll-interval", config.ADVANCER_POLLING_INTERVAL, + "Poll interval") + cli.AddFlagStrVar(flags, &maxStartupTime, "max-startup-time", config.MAX_STARTUP_TIME, + "Maximum startup time in seconds") + cli.AddFlagBoolVar(flags, &enableInspect, "inspect-enabled", config.FEATURE_INSPECT_ENABLED, + "Enable or disable the inspect service") + cli.AddFlagBoolVar(flags, &enableMachineHashCheck, "machine-hash-check", config.FEATURE_MACHINE_HASH_CHECK_ENABLED, "Enable or disable machine hash check (DO NOT USE IN PRODUCTION)") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_MACHINE_HASH_CHECK_ENABLED, Cmd.Flags().Lookup("machine-hash-check"))) - - Cmd.Flags().StringVar(&machinelogLevel, "machine-log-level", "info", + cli.AddFlagStrVar(flags, &machinelogLevel, "machine-log-level", config.JSONRPC_MACHINE_LOG_LEVEL, "Remote Machine log level: trace, debug, info, warning, error, fatal") - cobra.CheckErr(viper.BindPFlag(config.JSONRPC_MACHINE_LOG_LEVEL, Cmd.Flags().Lookup("machine-log-level"))) // TODO: validate on preRunE Cmd.PreRunE = func(cmd *cobra.Command, args []string) error { @@ -94,7 +86,7 @@ func run(cmd *cobra.Command, args []string) { LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, - TelemetryAddress: cfg.TelemetryAddress, + TelemetryAddress: cfg.AdvancerTelemetryAddress, PollInterval: cfg.AdvancerPollingInterval, }, Config: *cfg, diff --git a/cmd/cartesi-rollups-claimer/root/root.go b/cmd/cartesi-rollups-claimer/root/root.go index 1e3cab2d1..0633a23b1 100644 --- a/cmd/cartesi-rollups-claimer/root/root.go +++ b/cmd/cartesi-rollups-claimer/root/root.go @@ -7,6 +7,7 @@ import ( "context" "github.com/cartesi/rollups-node/internal/claimer" + "github.com/cartesi/rollups-node/internal/cli" "github.com/cartesi/rollups-node/internal/config" "github.com/cartesi/rollups-node/internal/repository/factory" "github.com/cartesi/rollups-node/internal/version" @@ -14,7 +15,6 @@ import ( "github.com/cartesi/rollups-node/pkg/service" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -40,38 +40,30 @@ var Cmd = &cobra.Command{ } func init() { - Cmd.Flags().StringVarP(&defaultBlockString, "default-block", "d", "finalized", - "Default block to be used when fetching new blocks.\nOne of 'latest', 'safe', 'pending', 'finalized'") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_DEFAULT_BLOCK, Cmd.Flags().Lookup("default-block"))) - - Cmd.Flags().StringVar(&telemetryAddress, "telemetry-address", ":10004", "Health check and metrics address and port") - cobra.CheckErr(viper.BindPFlag(config.TELEMETRY_ADDRESS, Cmd.Flags().Lookup("telemetry-address"))) - - Cmd.Flags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn or error") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL, Cmd.Flags().Lookup("log-level"))) + flags := Cmd.Flags() - Cmd.Flags().BoolVar(&logColor, "log-color", true, "tint the logs (colored output)") - cobra.CheckErr(viper.BindPFlag(config.LOG_COLOR, Cmd.Flags().Lookup("log-color"))) + config.SetDefaults() - Cmd.Flags().StringVar(&databaseConnection, "database-connection", "", + cli.AddFlagStrVarP(flags, &defaultBlockString, "default-block", "d", config.BLOCKCHAIN_DEFAULT_BLOCK, + "Default block to be used when fetching new blocks.\nOne of 'latest', 'safe', 'pending', 'finalized'") + cli.AddFlagStrVar(flags, &telemetryAddress, "telemetry-address", config.CLAIMER_TELEMETRY_ADDRESS, + "Health check and metrics address and port") + cli.AddFlagStrVar(flags, &logLevel, "log-level", config.LOG_LEVEL, + "Log level: debug, info, warn or error") + cli.AddFlagBoolVar(flags, &logColor, "log-color", config.LOG_COLOR, + "tint the logs (colored output)") + cli.AddFlagStrVar(flags, &databaseConnection, "database-connection", config.DATABASE_CONNECTION, "Database connection string in the URL format\n(eg.: 'postgres://user:password@hostname:port/database') ") - cobra.CheckErr(viper.BindPFlag(config.DATABASE_CONNECTION, Cmd.Flags().Lookup("database-connection"))) - - Cmd.Flags().StringVar(&blockchainHttpEndpoint, "blockchain-http-endpoint", "", "Blockchain http endpoint") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_HTTP_ENDPOINT, Cmd.Flags().Lookup("blockchain-http-endpoint"))) - - Cmd.Flags().StringVar(&pollInterval, "poll-interval", "7", "Poll interval") - cobra.CheckErr(viper.BindPFlag(config.CLAIMER_POLLING_INTERVAL, Cmd.Flags().Lookup("poll-interval"))) - - Cmd.Flags().StringVar(&maxStartupTime, "max-startup-time", "15", "Maximum startup time in seconds") - cobra.CheckErr(viper.BindPFlag(config.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time"))) - - Cmd.Flags().BoolVar(&enableSubmission, "claim-submission", true, "Enable or disable claim submission (reader mode)") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_CLAIM_SUBMISSION_ENABLED, Cmd.Flags().Lookup("claim-submission"))) - - Cmd.Flags().Uint64Var(&maxBlockRange, "max-block-range", 0, + cli.AddFlagStrVar(flags, &blockchainHttpEndpoint, "blockchain-http-endpoint", config.BLOCKCHAIN_HTTP_ENDPOINT, + "Blockchain http endpoint") + cli.AddFlagStrVar(flags, &pollInterval, "poll-interval", config.CLAIMER_POLLING_INTERVAL, + "Poll interval") + cli.AddFlagStrVar(flags, &maxStartupTime, "max-startup-time", config.MAX_STARTUP_TIME, + "Maximum startup time in seconds") + cli.AddFlagBoolVar(flags, &enableSubmission, "claim-submission", config.FEATURE_CLAIM_SUBMISSION_ENABLED, + "Enable or disable claim submission (reader mode)") + cli.AddFlagUint64Var(flags, &maxBlockRange, "max-block-range", config.BLOCKCHAIN_MAX_BLOCK_RANGE, "Maximum number of blocks in a single query. large queries will be split automatically. Zero for unlimited.") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_MAX_BLOCK_RANGE, Cmd.Flags().Lookup("max-block-range"))) // TODO: validate on preRunE Cmd.PreRunE = func(cmd *cobra.Command, args []string) error { @@ -96,7 +88,7 @@ func run(cmd *cobra.Command, args []string) { LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, - TelemetryAddress: cfg.TelemetryAddress, + TelemetryAddress: cfg.ClaimerTelemetryAddress, PollInterval: cfg.ClaimerPollingInterval, }, Config: *cfg, diff --git a/cmd/cartesi-rollups-evm-reader/root/root.go b/cmd/cartesi-rollups-evm-reader/root/root.go index f6f286b9f..ef07fd340 100644 --- a/cmd/cartesi-rollups-evm-reader/root/root.go +++ b/cmd/cartesi-rollups-evm-reader/root/root.go @@ -6,6 +6,7 @@ package root import ( "context" + "github.com/cartesi/rollups-node/internal/cli" "github.com/cartesi/rollups-node/internal/config" "github.com/cartesi/rollups-node/internal/evmreader" "github.com/cartesi/rollups-node/internal/repository/factory" @@ -15,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -41,38 +41,30 @@ var Cmd = &cobra.Command{ } func init() { - Cmd.Flags().StringVarP(&defaultBlockString, "default-block", "d", "finalized", - "Default block to be used when fetching new blocks.\nOne of 'latest', 'safe', 'pending', 'finalized'") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_DEFAULT_BLOCK, Cmd.Flags().Lookup("default-block"))) - - Cmd.Flags().StringVar(&telemetryAddress, "telemetry-address", ":10001", "Health check and metrics address and port") - cobra.CheckErr(viper.BindPFlag(config.TELEMETRY_ADDRESS, Cmd.Flags().Lookup("telemetry-address"))) - - Cmd.Flags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn or error") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL, Cmd.Flags().Lookup("log-level"))) + flags := Cmd.Flags() - Cmd.Flags().BoolVar(&logColor, "log-color", true, "Tint the logs (colored output)") - cobra.CheckErr(viper.BindPFlag(config.LOG_COLOR, Cmd.Flags().Lookup("log-color"))) + config.SetDefaults() - Cmd.Flags().StringVar(&databaseConnection, "database-connection", "", + cli.AddFlagStrVarP(flags, &defaultBlockString, "default-block", "d", config.BLOCKCHAIN_DEFAULT_BLOCK, + "Default block to be used when fetching new blocks.\nOne of 'latest', 'safe', 'pending', 'finalized'") + cli.AddFlagStrVar(flags, &telemetryAddress, "telemetry-address", config.EVM_READER_TELEMETRY_ADDRESS, + "Health check and metrics address and port") + cli.AddFlagStrVar(flags, &logLevel, "log-level", config.LOG_LEVEL, + "Log level: debug, info, warn or error") + cli.AddFlagBoolVar(flags, &logColor, "log-color", config.LOG_COLOR, + "Tint the logs (colored output)") + cli.AddFlagStrVar(flags, &databaseConnection, "database-connection", config.DATABASE_CONNECTION, "Database connection string in the URL format\n(eg.: 'postgres://user:password@hostname:port/database') ") - cobra.CheckErr(viper.BindPFlag(config.DATABASE_CONNECTION, Cmd.Flags().Lookup("database-connection"))) - - Cmd.Flags().StringVar(&blockchainHttpEndpoint, "blockchain-http-endpoint", "", "Blockchain http endpoint") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_HTTP_ENDPOINT, Cmd.Flags().Lookup("blockchain-http-endpoint"))) - - Cmd.Flags().StringVar(&blockchainWsEndpoint, "blockchain-ws-endpoint", "", "Blockchain WS Endpoint") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_WS_ENDPOINT, Cmd.Flags().Lookup("blockchain-ws-endpoint"))) - - Cmd.Flags().StringVar(&maxStartupTime, "max-startup-time", "15", "Maximum startup time in seconds") - cobra.CheckErr(viper.BindPFlag(config.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time"))) - - Cmd.Flags().BoolVar(&enableInputReader, "input-reader", true, "Enable or disable the input reader (for external input readers)") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_INPUT_READER_ENABLED, Cmd.Flags().Lookup("input-reader"))) - - Cmd.Flags().Uint64Var(&maxBlockRange, "max-block-range", 0, + cli.AddFlagStrVar(flags, &blockchainHttpEndpoint, "blockchain-http-endpoint", config.BLOCKCHAIN_HTTP_ENDPOINT, + "Blockchain http endpoint") + cli.AddFlagStrVar(flags, &blockchainWsEndpoint, "blockchain-ws-endpoint", config.BLOCKCHAIN_WS_ENDPOINT, + "Blockchain WS Endpoint") + cli.AddFlagStrVar(flags, &maxStartupTime, "max-startup-time", config.MAX_STARTUP_TIME, + "Maximum startup time in seconds") + cli.AddFlagBoolVar(flags, &enableInputReader, "input-reader", config.FEATURE_INPUT_READER_ENABLED, + "Enable or disable the input reader (for external input readers)") + cli.AddFlagUint64Var(flags, &maxBlockRange, "max-block-range", config.BLOCKCHAIN_MAX_BLOCK_RANGE, "Maximum number of blocks in a single query. large queries will be split automatically. Zero for unlimited.") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_MAX_BLOCK_RANGE, Cmd.Flags().Lookup("max-block-range"))) // TODO: validate on preRunE Cmd.PreRunE = func(cmd *cobra.Command, args []string) error { @@ -85,8 +77,7 @@ func init() { } } -func run(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime) +func run(cmd *cobra.Command, args []string) { ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime) defer cancel() logLevel := config.ResolveServiceLogLevel(config.ServiceEvmReader, cfg.LogLevel) @@ -97,7 +88,7 @@ func run(cmd *cobra.Command, args []string) { LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, - TelemetryAddress: cfg.TelemetryAddress, + TelemetryAddress: cfg.EvmReaderTelemetryAddress, }, Config: *cfg, } diff --git a/cmd/cartesi-rollups-jsonrpc-api/root/root.go b/cmd/cartesi-rollups-jsonrpc-api/root/root.go index 4eda3ccd6..b80a2ec3e 100644 --- a/cmd/cartesi-rollups-jsonrpc-api/root/root.go +++ b/cmd/cartesi-rollups-jsonrpc-api/root/root.go @@ -6,6 +6,7 @@ package root import ( "context" + "github.com/cartesi/rollups-node/internal/cli" "github.com/cartesi/rollups-node/internal/config" "github.com/cartesi/rollups-node/internal/jsonrpc" "github.com/cartesi/rollups-node/internal/repository/factory" @@ -13,7 +14,6 @@ import ( "github.com/cartesi/rollups-node/pkg/service" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -35,24 +35,22 @@ var Cmd = &cobra.Command{ } func init() { - Cmd.Flags().StringVar(&jsonrpcApiAddress, "jsonrpc-address", ":10011", "Jsonrpc API service address and port") - cobra.CheckErr(viper.BindPFlag(config.JSONRPC_API_ADDRESS, Cmd.Flags().Lookup("jsonrpc-address"))) - - Cmd.Flags().StringVar(&telemetryAddress, "telemetry-address", ":10005", "Health check and metrics address and port") - cobra.CheckErr(viper.BindPFlag(config.TELEMETRY_ADDRESS, Cmd.Flags().Lookup("telemetry-address"))) - - Cmd.Flags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn or error") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL, Cmd.Flags().Lookup("log-level"))) - - Cmd.Flags().BoolVar(&logColor, "log-color", true, "Tint the logs (colored output)") - cobra.CheckErr(viper.BindPFlag(config.LOG_COLOR, Cmd.Flags().Lookup("log-color"))) - - Cmd.Flags().StringVar(&databaseConnection, "database-connection", "", + flags := Cmd.Flags() + + config.SetDefaults() + + cli.AddFlagStrVar(flags, &jsonrpcApiAddress, "jsonrpc-address", config.JSONRPC_API_ADDRESS, + "Jsonrpc API service address and port") + cli.AddFlagStrVar(flags, &telemetryAddress, "telemetry-address", config.JSONRPC_TELEMETRY_ADDRESS, + "Health check and metrics address and port") + cli.AddFlagStrVar(flags, &logLevel, "log-level", config.LOG_LEVEL, + "Log level: debug, info, warn or error") + cli.AddFlagBoolVar(flags, &logColor, "log-color", config.LOG_COLOR, + "Tint the logs (colored output)") + cli.AddFlagStrVar(flags, &databaseConnection, "database-connection", config.DATABASE_CONNECTION, "Database connection string in the URL format\n(eg.: 'postgres://user:password@hostname:port/database') ") - cobra.CheckErr(viper.BindPFlag(config.DATABASE_CONNECTION, Cmd.Flags().Lookup("database-connection"))) - - Cmd.Flags().StringVar(&maxStartupTime, "max-startup-time", "15", "Maximum startup time in seconds") - cobra.CheckErr(viper.BindPFlag(config.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time"))) + cli.AddFlagStrVar(flags, &maxStartupTime, "max-startup-time", config.MAX_STARTUP_TIME, + "Maximum startup time in seconds") // TODO: validate on preRunE Cmd.PreRunE = func(cmd *cobra.Command, args []string) error { @@ -76,7 +74,7 @@ func run(cmd *cobra.Command, args []string) { LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, - TelemetryAddress: cfg.TelemetryAddress, + TelemetryAddress: cfg.JsonrpcTelemetryAddress, }, Config: *cfg, } diff --git a/cmd/cartesi-rollups-node/root/root.go b/cmd/cartesi-rollups-node/root/root.go index 2fcc42066..bb5cd4f9d 100644 --- a/cmd/cartesi-rollups-node/root/root.go +++ b/cmd/cartesi-rollups-node/root/root.go @@ -6,6 +6,7 @@ package root import ( "context" + "github.com/cartesi/rollups-node/internal/cli" "github.com/cartesi/rollups-node/internal/config" "github.com/cartesi/rollups-node/internal/node" "github.com/cartesi/rollups-node/internal/repository/factory" @@ -15,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -58,97 +58,64 @@ var Cmd = &cobra.Command{ } func init() { - Cmd.Flags().StringVarP(&defaultBlockString, "default-block", "d", "finalized", - "Default block to be used when fetching new blocks.\nOne of 'latest', 'safe', 'pending', 'finalized'") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_DEFAULT_BLOCK, Cmd.Flags().Lookup("default-block"))) - - Cmd.Flags().StringVar(&jsonrpcApiAddress, "jsonrpc-address", ":10011", "Jsonrpc API service address and port") - cobra.CheckErr(viper.BindPFlag(config.JSONRPC_API_ADDRESS, Cmd.Flags().Lookup("jsonrpc-address"))) - - Cmd.Flags().StringVar(&inspectAddress, "inspect-address", ":10012", "Inspect service address and port") - cobra.CheckErr(viper.BindPFlag(config.INSPECT_ADDRESS, Cmd.Flags().Lookup("inspect-address"))) - - Cmd.Flags().StringVar(&telemetryAddress, "telemetry-address", ":10000", "Health check and metrics address and port") - cobra.CheckErr(viper.BindPFlag(config.TELEMETRY_ADDRESS, Cmd.Flags().Lookup("telemetry-address"))) + flags := Cmd.Flags() - Cmd.Flags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn or error") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL, Cmd.Flags().Lookup("log-level"))) + config.SetDefaults() - Cmd.Flags().BoolVar(&logColor, "log-color", true, "Tint the logs (colored output)") - cobra.CheckErr(viper.BindPFlag(config.LOG_COLOR, Cmd.Flags().Lookup("log-color"))) - - Cmd.Flags().StringVar(&logLevelAdvancer, "log-level-advancer", "", + cli.AddFlagStrVarP(flags, &defaultBlockString, "default-block", "d", config.BLOCKCHAIN_DEFAULT_BLOCK, + "Default block to be used when fetching new blocks.\nOne of 'latest', 'safe', 'pending', 'finalized'") + cli.AddFlagStrVar(flags, &jsonrpcApiAddress, "jsonrpc-address", config.JSONRPC_API_ADDRESS, + "Jsonrpc API service address and port") + cli.AddFlagStrVar(flags, &inspectAddress, "inspect-address", config.INSPECT_ADDRESS, + "Inspect service address and port") + cli.AddFlagStrVar(flags, &telemetryAddress, "telemetry-address", config.NODE_TELEMETRY_ADDRESS, + "Health check and metrics address and port") + cli.AddFlagStrVar(flags, &logLevel, "log-level", config.LOG_LEVEL, + "Log level: debug, info, warn or error") + cli.AddFlagBoolVar(flags, &logColor, "log-color", config.LOG_COLOR, + "Tint the logs (colored output)") + cli.AddFlagStrVar(flags, &logLevelAdvancer, "log-level-advancer", config.LOG_LEVEL_ADVANCER, "Override log level for the advancer service (default: inherit --log-level)") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL_ADVANCER, Cmd.Flags().Lookup("log-level-advancer"))) - - Cmd.Flags().StringVar(&logLevelClaimer, "log-level-claimer", "", + cli.AddFlagStrVar(flags, &logLevelClaimer, "log-level-claimer", config.LOG_LEVEL_CLAIMER, "Override log level for the claimer service (default: inherit --log-level)") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL_CLAIMER, Cmd.Flags().Lookup("log-level-claimer"))) - - Cmd.Flags().StringVar(&logLevelEvmReader, "log-level-evm-reader", "", + cli.AddFlagStrVar(flags, &logLevelEvmReader, "log-level-evm-reader", config.LOG_LEVEL_EVM_READER, "Override log level for the evm-reader service (default: inherit --log-level)") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL_EVM_READER, Cmd.Flags().Lookup("log-level-evm-reader"))) - - Cmd.Flags().StringVar(&logLevelJsonrpc, "log-level-jsonrpc-api", "", + cli.AddFlagStrVar(flags, &logLevelJsonrpc, "log-level-jsonrpc-api", config.LOG_LEVEL_JSONRPC_API, "Override log level for the jsonrpc-api service (default: inherit --log-level)") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL_JSONRPC_API, Cmd.Flags().Lookup("log-level-jsonrpc-api"))) - - Cmd.Flags().StringVar(&logLevelPrt, "log-level-prt", "", + cli.AddFlagStrVar(flags, &logLevelPrt, "log-level-prt", config.LOG_LEVEL_PRT, "Override log level for the prt service (default: inherit --log-level)") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL_PRT, Cmd.Flags().Lookup("log-level-prt"))) - - Cmd.Flags().StringVar(&logLevelValidator, "log-level-validator", "", + cli.AddFlagStrVar(flags, &logLevelValidator, "log-level-validator", config.LOG_LEVEL_VALIDATOR, "Override log level for the validator service (default: inherit --log-level)") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL_VALIDATOR, Cmd.Flags().Lookup("log-level-validator"))) - - Cmd.Flags().StringVar(&databaseConnection, "database-connection", "", + cli.AddFlagStrVar(flags, &databaseConnection, "database-connection", config.DATABASE_CONNECTION, "Database connection string in the URL format\n(eg.: 'postgres://user:password@hostname:port/database') ") - cobra.CheckErr(viper.BindPFlag(config.DATABASE_CONNECTION, Cmd.Flags().Lookup("database-connection"))) - - Cmd.Flags().StringVar(&blockchainHttpEndpoint, "blockchain-http-endpoint", "", "Blockchain HTTP endpoint") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_HTTP_ENDPOINT, Cmd.Flags().Lookup("blockchain-http-endpoint"))) - - Cmd.Flags().StringVar(&blockchainWsEndpoint, "blockchain-ws-endpoint", "", "Blockchain WS Endpoint") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_WS_ENDPOINT, Cmd.Flags().Lookup("blockchain-ws-endpoint"))) - - Cmd.Flags().StringVar(&advancerPollInterval, "advancer-poll-interval", "3", "Advancer poll interval") - cobra.CheckErr(viper.BindPFlag(config.ADVANCER_POLLING_INTERVAL, Cmd.Flags().Lookup("advancer-poll-interval"))) - - Cmd.Flags().StringVar(&validatorPollInterval, "validator-poll-interval", "3", "Validator poll interval") - cobra.CheckErr(viper.BindPFlag(config.VALIDATOR_POLLING_INTERVAL, Cmd.Flags().Lookup("validator-poll-interval"))) - - Cmd.Flags().StringVar(&claimerPollInterval, "claimer-poll-interval", "3", "Claimer poll interval") - cobra.CheckErr(viper.BindPFlag(config.CLAIMER_POLLING_INTERVAL, Cmd.Flags().Lookup("claimer-poll-interval"))) - - Cmd.Flags().StringVar(&prtPollInterval, "prt-poll-interval", "3", "Claimer poll interval") - cobra.CheckErr(viper.BindPFlag(config.PRT_POLLING_INTERVAL, Cmd.Flags().Lookup("prt-poll-interval"))) - - Cmd.Flags().StringVar(&maxStartupTime, "max-startup-time", "15", "Maximum startup time in seconds") - cobra.CheckErr(viper.BindPFlag(config.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time"))) - - Cmd.Flags().BoolVar(&enableInputReader, "input-reader", true, "Enable or disable the input reader (for external input readers)") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_INPUT_READER_ENABLED, Cmd.Flags().Lookup("input-reader"))) - - Cmd.Flags().BoolVar(&enableInspect, "inspect-enabled", true, "Enable or disable the inspect service") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_INSPECT_ENABLED, Cmd.Flags().Lookup("inspect-enabled"))) - - Cmd.Flags().BoolVar(&enableJsonrpc, "jsonrpc-enabled", true, "Enable or disable the jsonrpc api service") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_JSONRPC_API_ENABLED, Cmd.Flags().Lookup("jsonrpc-enabled"))) - - Cmd.Flags().BoolVar(&enableMachineHashCheck, "machine-hash-check", true, + cli.AddFlagStrVar(flags, &blockchainHttpEndpoint, "blockchain-http-endpoint", config.BLOCKCHAIN_HTTP_ENDPOINT, + "Blockchain HTTP endpoint") + cli.AddFlagStrVar(flags, &blockchainWsEndpoint, "blockchain-ws-endpoint", config.BLOCKCHAIN_WS_ENDPOINT, + "Blockchain WS Endpoint") + cli.AddFlagStrVar(flags, &advancerPollInterval, "advancer-poll-interval", config.ADVANCER_POLLING_INTERVAL, + "Advancer poll interval") + cli.AddFlagStrVar(flags, &validatorPollInterval, "validator-poll-interval", config.VALIDATOR_POLLING_INTERVAL, + "Validator poll interval") + cli.AddFlagStrVar(flags, &claimerPollInterval, "claimer-poll-interval", config.CLAIMER_POLLING_INTERVAL, + "Claimer poll interval") + cli.AddFlagStrVar(flags, &prtPollInterval, "prt-poll-interval", config.PRT_POLLING_INTERVAL, + "Claimer poll interval") + cli.AddFlagStrVar(flags, &maxStartupTime, "max-startup-time", config.MAX_STARTUP_TIME, + "Maximum startup time in seconds") + cli.AddFlagBoolVar(flags, &enableInputReader, "input-reader", config.FEATURE_INPUT_READER_ENABLED, + "Enable or disable the input reader (for external input readers)") + cli.AddFlagBoolVar(flags, &enableInspect, "inspect-enabled", config.FEATURE_INSPECT_ENABLED, + "Enable or disable the inspect service") + cli.AddFlagBoolVar(flags, &enableJsonrpc, "jsonrpc-enabled", config.FEATURE_JSONRPC_API_ENABLED, + "Enable or disable the jsonrpc api service") + cli.AddFlagBoolVar(flags, &enableMachineHashCheck, "machine-hash-check", config.FEATURE_MACHINE_HASH_CHECK_ENABLED, "Enable or disable machine hash check (DO NOT USE IN PRODUCTION)") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_MACHINE_HASH_CHECK_ENABLED, Cmd.Flags().Lookup("machine-hash-check"))) - - Cmd.Flags().BoolVar(&enableSubmission, "claim-submission", true, "Enable or disable claim submission (reader mode)") - cobra.CheckErr(viper.BindPFlag(config.FEATURE_CLAIM_SUBMISSION_ENABLED, Cmd.Flags().Lookup("claim-submission"))) - - Cmd.Flags().StringVar(&machinelogLevel, "machine-log-level", "info", + cli.AddFlagBoolVar(flags, &enableSubmission, "claim-submission", config.FEATURE_CLAIM_SUBMISSION_ENABLED, + "Enable or disable claim submission (reader mode)") + cli.AddFlagStrVar(flags, &machinelogLevel, "machine-log-level", config.JSONRPC_MACHINE_LOG_LEVEL, "Remote Machine log level: trace, debug, info, warning, error, fatal") - cobra.CheckErr(viper.BindPFlag(config.JSONRPC_MACHINE_LOG_LEVEL, Cmd.Flags().Lookup("machine-log-level"))) - - Cmd.Flags().Uint64Var(&maxBlockRange, "max-block-range", 0, + cli.AddFlagUint64Var(flags, &maxBlockRange, "max-block-range", config.BLOCKCHAIN_MAX_BLOCK_RANGE, "Maximum number of blocks in a single query. large queries will be split automatically. Zero for unlimited.") - cobra.CheckErr(viper.BindPFlag(config.BLOCKCHAIN_MAX_BLOCK_RANGE, Cmd.Flags().Lookup("max-block-range"))) // TODO: validate on preRunE Cmd.PreRunE = func(cmd *cobra.Command, args []string) error { @@ -189,7 +156,7 @@ func run(cmd *cobra.Command, args []string) { LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, - TelemetryAddress: cfg.TelemetryAddress, + TelemetryAddress: cfg.NodeTelemetryAddress, }, Config: *cfg, } diff --git a/cmd/cartesi-rollups-prt/root/root.go b/cmd/cartesi-rollups-prt/root/root.go index 0d2a3e248..b9dbf1f7e 100644 --- a/cmd/cartesi-rollups-prt/root/root.go +++ b/cmd/cartesi-rollups-prt/root/root.go @@ -6,6 +6,7 @@ package root import ( "context" + "github.com/cartesi/rollups-node/internal/cli" "github.com/cartesi/rollups-node/internal/config" "github.com/cartesi/rollups-node/internal/prt" "github.com/cartesi/rollups-node/internal/repository/factory" @@ -14,7 +15,6 @@ import ( "github.com/cartesi/rollups-node/pkg/service" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -36,24 +36,22 @@ var Cmd = &cobra.Command{ } func init() { - Cmd.Flags().StringVar(&telemetryAddress, "telemetry-address", ":10003", "Health check and metrics address and port") - cobra.CheckErr(viper.BindPFlag(config.TELEMETRY_ADDRESS, Cmd.Flags().Lookup("telemetry-address"))) + flags := Cmd.Flags() - Cmd.Flags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn or error") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL, Cmd.Flags().Lookup("log-level"))) + config.SetDefaults() - Cmd.Flags().BoolVar(&logColor, "log-color", true, "Tint the logs (colored output)") - cobra.CheckErr(viper.BindPFlag(config.LOG_COLOR, Cmd.Flags().Lookup("log-color"))) - - Cmd.Flags().StringVar(&databaseConnection, "database-connection", "", + cli.AddFlagStrVar(flags, &telemetryAddress, "telemetry-address", config.PRT_TELEMETRY_ADDRESS, + "Health check and metrics address and port") + cli.AddFlagStrVar(flags, &logLevel, "log-level", config.LOG_LEVEL, + "Log level: debug, info, warn or error") + cli.AddFlagBoolVar(flags, &logColor, "log-color", config.LOG_COLOR, + "Tint the logs (colored output)") + cli.AddFlagStrVar(flags, &databaseConnection, "database-connection", config.DATABASE_CONNECTION, "Database connection string in the URL format\n(eg.: 'postgres://user:password@hostname:port/database') ") - cobra.CheckErr(viper.BindPFlag(config.DATABASE_CONNECTION, Cmd.Flags().Lookup("database-connection"))) - - Cmd.Flags().StringVar(&pollInterval, "poll-interval", "3", "Poll interval") - cobra.CheckErr(viper.BindPFlag(config.PRT_POLLING_INTERVAL, Cmd.Flags().Lookup("poll-interval"))) - - Cmd.Flags().StringVar(&maxStartupTime, "max-startup-time", "15", "Maximum startup time in seconds") - cobra.CheckErr(viper.BindPFlag(config.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time"))) + cli.AddFlagStrVar(flags, &pollInterval, "poll-interval", config.PRT_POLLING_INTERVAL, + "Poll interval") + cli.AddFlagStrVar(flags, &maxStartupTime, "max-startup-time", config.MAX_STARTUP_TIME, + "Maximum startup time in seconds") // TODO: validate on preRunE Cmd.PreRunE = func(cmd *cobra.Command, args []string) error { @@ -78,7 +76,7 @@ func run(cmd *cobra.Command, args []string) { LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, - TelemetryAddress: cfg.TelemetryAddress, + TelemetryAddress: cfg.PrtTelemetryAddress, PollInterval: cfg.PrtPollingInterval, }, Config: *cfg, diff --git a/cmd/cartesi-rollups-validator/root/root.go b/cmd/cartesi-rollups-validator/root/root.go index 70d7b25c4..9283f7f9c 100644 --- a/cmd/cartesi-rollups-validator/root/root.go +++ b/cmd/cartesi-rollups-validator/root/root.go @@ -6,6 +6,7 @@ package root import ( "context" + "github.com/cartesi/rollups-node/internal/cli" "github.com/cartesi/rollups-node/internal/config" "github.com/cartesi/rollups-node/internal/repository/factory" "github.com/cartesi/rollups-node/internal/validator" @@ -13,7 +14,6 @@ import ( "github.com/cartesi/rollups-node/pkg/service" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var ( @@ -35,24 +35,22 @@ var Cmd = &cobra.Command{ } func init() { - Cmd.Flags().StringVar(&telemetryAddress, "telemetry-address", ":10003", "Health check and metrics address and port") - cobra.CheckErr(viper.BindPFlag(config.TELEMETRY_ADDRESS, Cmd.Flags().Lookup("telemetry-address"))) + flags := Cmd.Flags() - Cmd.Flags().StringVar(&logLevel, "log-level", "info", "Log level: debug, info, warn or error") - cobra.CheckErr(viper.BindPFlag(config.LOG_LEVEL, Cmd.Flags().Lookup("log-level"))) + config.SetDefaults() - Cmd.Flags().BoolVar(&logColor, "log-color", true, "Tint the logs (colored output)") - cobra.CheckErr(viper.BindPFlag(config.LOG_COLOR, Cmd.Flags().Lookup("log-color"))) - - Cmd.Flags().StringVar(&databaseConnection, "database-connection", "", + cli.AddFlagStrVar(flags, &telemetryAddress, "telemetry-address", config.VALIDATOR_TELEMETRY_ADDRESS, + "Health check and metrics address and port") + cli.AddFlagStrVar(flags, &logLevel, "log-level", config.LOG_LEVEL, + "Log level: debug, info, warn or error") + cli.AddFlagBoolVar(flags, &logColor, "log-color", config.LOG_COLOR, + "Tint the logs (colored output)") + cli.AddFlagStrVar(flags, &databaseConnection, "database-connection", config.DATABASE_CONNECTION, "Database connection string in the URL format\n(eg.: 'postgres://user:password@hostname:port/database') ") - cobra.CheckErr(viper.BindPFlag(config.DATABASE_CONNECTION, Cmd.Flags().Lookup("database-connection"))) - - Cmd.Flags().StringVar(&pollInterval, "poll-interval", "7", "Poll interval") - cobra.CheckErr(viper.BindPFlag(config.VALIDATOR_POLLING_INTERVAL, Cmd.Flags().Lookup("poll-interval"))) - - Cmd.Flags().StringVar(&maxStartupTime, "max-startup-time", "15", "Maximum startup time in seconds") - cobra.CheckErr(viper.BindPFlag(config.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time"))) + cli.AddFlagStrVar(flags, &pollInterval, "poll-interval", config.VALIDATOR_POLLING_INTERVAL, + "Poll interval") + cli.AddFlagStrVar(flags, &maxStartupTime, "max-startup-time", config.MAX_STARTUP_TIME, + "Maximum startup time in seconds") // TODO: validate on preRunE Cmd.PreRunE = func(cmd *cobra.Command, args []string) error { @@ -76,7 +74,7 @@ func run(cmd *cobra.Command, args []string) { LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, - TelemetryAddress: cfg.TelemetryAddress, + TelemetryAddress: cfg.ValidatorTelemetryAddress, PollInterval: cfg.ValidatorPollingInterval, }, Config: *cfg, diff --git a/internal/cli/cobra.go b/internal/cli/cobra.go new file mode 100644 index 000000000..bf5889ff9 --- /dev/null +++ b/internal/cli/cobra.go @@ -0,0 +1,30 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package cli + +import ( + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/spf13/viper" +) + +func AddFlagBoolVar(flags *pflag.FlagSet, varRef *bool, flagName string, cfgName string, flagDesc string) { + flags.BoolVar(varRef, flagName, viper.GetBool(cfgName), flagDesc) + cobra.CheckErr(viper.BindPFlag(cfgName, flags.Lookup(flagName))) +} + +func AddFlagUint64Var(flags *pflag.FlagSet, varRef *uint64, flagName string, cfgName string, flagDesc string) { + flags.Uint64Var(varRef, flagName, viper.GetUint64(cfgName), flagDesc) + cobra.CheckErr(viper.BindPFlag(cfgName, flags.Lookup(flagName))) +} + +func AddFlagStrVar(flags *pflag.FlagSet, varRef *string, flagName string, cfgName string, flagDesc string) { + flags.StringVar(varRef, flagName, viper.GetString(cfgName), flagDesc) + cobra.CheckErr(viper.BindPFlag(cfgName, flags.Lookup(flagName))) +} + +func AddFlagStrVarP(flags *pflag.FlagSet, varRef *string, flagName string, flagShort string, cfgName string, flagDesc string) { + flags.StringVarP(varRef, flagName, flagShort, viper.GetString(cfgName), flagDesc) + cobra.CheckErr(viper.BindPFlag(cfgName, flags.Lookup(flagName))) +} diff --git a/internal/config/generate/Config.toml b/internal/config/generate/Config.toml index d96604350..0fcc1fd8a 100644 --- a/internal/config/generate/Config.toml +++ b/internal/config/generate/Config.toml @@ -385,11 +385,54 @@ used-by = ["advancer", "claimer", "evmreader", "validator", "jsonrpc", "node", " # Telemetry http address # -[http.CARTESI_TELEMETRY_ADDRESS] +[http.CARTESI_ADVANCER_TELEMETRY_ADDRESS] +default = ":10002" go-type = "string" description = """ -HTTP address for telemetry service.""" -used-by = ["advancer", "claimer", "evmreader", "validator", "jsonrpc", "node", "cli", "prt"] +HTTP address for Advancer's telemetry service.""" +used-by = ["advancer"] + +[http.CARTESI_CLAIMER_TELEMETRY_ADDRESS] +default = ":10004" +go-type = "string" +description = """ +HTTP address for Claimer's telemetry service.""" +used-by = ["claimer"] + +[http.CARTESI_EVM_READER_TELEMETRY_ADDRESS] +default = ":10001" +go-type = "string" +description = """ +HTTP address for EVM Reader's telemetry service.""" +used-by = ["evmreader"] + +[http.CARTESI_VALIDATOR_TELEMETRY_ADDRESS] +default = ":10003" +go-type = "string" +description = """ +HTTP address for Validator's telemetry service.""" +used-by = ["validator"] + +[http.CARTESI_JSONRPC_TELEMETRY_ADDRESS] +default = ":10005" +go-type = "string" +description = """ +HTTP address for JSON-RPC's telemetry service.""" +used-by = ["jsonrpc"] + +[http.CARTESI_NODE_TELEMETRY_ADDRESS] +default = ":10000" +go-type = "string" +description = """ +HTTP address for Node's telemetry service.""" +used-by = ["node"] + +[http.CARTESI_PRT_TELEMETRY_ADDRESS] +default = ":10006" +go-type = "string" +description = """ +HTTP address for PRT's telemetry service.""" +used-by = ["prt"] # # HTTP diff --git a/internal/config/generate/code.go b/internal/config/generate/code.go index d6e8dd13b..f32591338 100644 --- a/internal/config/generate/code.go +++ b/internal/config/generate/code.go @@ -168,8 +168,6 @@ type {{ capitalize $service }}Config struct { // Load{{ capitalize $service }}Config reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func Load{{ capitalize $service }}Config() (*{{ capitalize $service }}Config, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) diff --git a/internal/config/generated.go b/internal/config/generated.go index bcc63f00f..8e06ecd05 100644 --- a/internal/config/generated.go +++ b/internal/config/generated.go @@ -45,11 +45,17 @@ const ( FEATURE_INSPECT_ENABLED = "CARTESI_FEATURE_INSPECT_ENABLED" FEATURE_JSONRPC_API_ENABLED = "CARTESI_FEATURE_JSONRPC_API_ENABLED" FEATURE_MACHINE_HASH_CHECK_ENABLED = "CARTESI_FEATURE_MACHINE_HASH_CHECK_ENABLED" + ADVANCER_TELEMETRY_ADDRESS = "CARTESI_ADVANCER_TELEMETRY_ADDRESS" + CLAIMER_TELEMETRY_ADDRESS = "CARTESI_CLAIMER_TELEMETRY_ADDRESS" + EVM_READER_TELEMETRY_ADDRESS = "CARTESI_EVM_READER_TELEMETRY_ADDRESS" INSPECT_ADDRESS = "CARTESI_INSPECT_ADDRESS" INSPECT_URL = "CARTESI_INSPECT_URL" JSONRPC_API_ADDRESS = "CARTESI_JSONRPC_API_ADDRESS" JSONRPC_API_URL = "CARTESI_JSONRPC_API_URL" - TELEMETRY_ADDRESS = "CARTESI_TELEMETRY_ADDRESS" + JSONRPC_TELEMETRY_ADDRESS = "CARTESI_JSONRPC_TELEMETRY_ADDRESS" + NODE_TELEMETRY_ADDRESS = "CARTESI_NODE_TELEMETRY_ADDRESS" + PRT_TELEMETRY_ADDRESS = "CARTESI_PRT_TELEMETRY_ADDRESS" + VALIDATOR_TELEMETRY_ADDRESS = "CARTESI_VALIDATOR_TELEMETRY_ADDRESS" LOG_COLOR = "CARTESI_LOG_COLOR" LOG_LEVEL = "CARTESI_LOG_LEVEL" LOG_LEVEL_ADVANCER = "CARTESI_LOG_LEVEL_ADVANCER" @@ -137,6 +143,12 @@ func SetDefaults() { viper.SetDefault(FEATURE_MACHINE_HASH_CHECK_ENABLED, "true") + viper.SetDefault(ADVANCER_TELEMETRY_ADDRESS, ":10002") + + viper.SetDefault(CLAIMER_TELEMETRY_ADDRESS, ":10004") + + viper.SetDefault(EVM_READER_TELEMETRY_ADDRESS, ":10001") + viper.SetDefault(INSPECT_ADDRESS, ":10012") viper.SetDefault(INSPECT_URL, "http://localhost:10012") @@ -145,7 +157,13 @@ func SetDefaults() { viper.SetDefault(JSONRPC_API_URL, "http://localhost:10011/rpc") - // no default for CARTESI_TELEMETRY_ADDRESS + viper.SetDefault(JSONRPC_TELEMETRY_ADDRESS, ":10005") + + viper.SetDefault(NODE_TELEMETRY_ADDRESS, ":10000") + + viper.SetDefault(PRT_TELEMETRY_ADDRESS, ":10006") + + viper.SetDefault(VALIDATOR_TELEMETRY_ADDRESS, ":10003") viper.SetDefault(LOG_COLOR, "true") @@ -215,12 +233,12 @@ type AdvancerConfig struct { // the snapshot matches the hash in the Application contract. FeatureMachineHashCheckEnabled bool `mapstructure:"CARTESI_FEATURE_MACHINE_HASH_CHECK_ENABLED"` + // HTTP address for Advancer's telemetry service. + AdvancerTelemetryAddress string `mapstructure:"CARTESI_ADVANCER_TELEMETRY_ADDRESS"` + // HTTP address for inspect. InspectAddress string `mapstructure:"CARTESI_INSPECT_ADDRESS"` - // HTTP address for telemetry service. - TelemetryAddress string `mapstructure:"CARTESI_TELEMETRY_ADDRESS"` - // If set to true, the node will add colors to its log output. LogColor bool `mapstructure:"CARTESI_LOG_COLOR"` @@ -248,8 +266,6 @@ type AdvancerConfig struct { // LoadAdvancerConfig reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func LoadAdvancerConfig() (*AdvancerConfig, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) @@ -282,18 +298,18 @@ func LoadAdvancerConfig() (*AdvancerConfig, error) { return nil, fmt.Errorf("CARTESI_FEATURE_MACHINE_HASH_CHECK_ENABLED is required for the advancer service: %w", err) } - cfg.InspectAddress, err = GetInspectAddress() + cfg.AdvancerTelemetryAddress, err = GetAdvancerTelemetryAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_INSPECT_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_ADVANCER_TELEMETRY_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_INSPECT_ADDRESS is required for the advancer service: %w", err) + return nil, fmt.Errorf("CARTESI_ADVANCER_TELEMETRY_ADDRESS is required for the advancer service: %w", err) } - cfg.TelemetryAddress, err = GetTelemetryAddress() + cfg.InspectAddress, err = GetInspectAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_TELEMETRY_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_INSPECT_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_TELEMETRY_ADDRESS is required for the advancer service: %w", err) + return nil, fmt.Errorf("CARTESI_INSPECT_ADDRESS is required for the advancer service: %w", err) } cfg.LogColor, err = GetLogColor() @@ -378,8 +394,8 @@ type ClaimerConfig struct { // If set to false, the node will not submit claims (reader mode). FeatureClaimSubmissionEnabled bool `mapstructure:"CARTESI_FEATURE_CLAIM_SUBMISSION_ENABLED"` - // HTTP address for telemetry service. - TelemetryAddress string `mapstructure:"CARTESI_TELEMETRY_ADDRESS"` + // HTTP address for Claimer's telemetry service. + ClaimerTelemetryAddress string `mapstructure:"CARTESI_CLAIMER_TELEMETRY_ADDRESS"` // If set to true, the node will add colors to its log output. LogColor bool `mapstructure:"CARTESI_LOG_COLOR"` @@ -409,8 +425,6 @@ type ClaimerConfig struct { // LoadClaimerConfig reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func LoadClaimerConfig() (*ClaimerConfig, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) @@ -464,11 +478,11 @@ func LoadClaimerConfig() (*ClaimerConfig, error) { return nil, fmt.Errorf("CARTESI_FEATURE_CLAIM_SUBMISSION_ENABLED is required for the claimer service: %w", err) } - cfg.TelemetryAddress, err = GetTelemetryAddress() + cfg.ClaimerTelemetryAddress, err = GetClaimerTelemetryAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_TELEMETRY_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_CLAIMER_TELEMETRY_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_TELEMETRY_ADDRESS is required for the claimer service: %w", err) + return nil, fmt.Errorf("CARTESI_CLAIMER_TELEMETRY_ADDRESS is required for the claimer service: %w", err) } cfg.LogColor, err = GetLogColor() @@ -559,8 +573,8 @@ type EvmreaderConfig struct { // If set to false, the node will not read inputs from the blockchain. FeatureInputReaderEnabled bool `mapstructure:"CARTESI_FEATURE_INPUT_READER_ENABLED"` - // HTTP address for telemetry service. - TelemetryAddress string `mapstructure:"CARTESI_TELEMETRY_ADDRESS"` + // HTTP address for EVM Reader's telemetry service. + EvmReaderTelemetryAddress string `mapstructure:"CARTESI_EVM_READER_TELEMETRY_ADDRESS"` // If set to true, the node will add colors to its log output. LogColor bool `mapstructure:"CARTESI_LOG_COLOR"` @@ -596,8 +610,6 @@ type EvmreaderConfig struct { // LoadEvmreaderConfig reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func LoadEvmreaderConfig() (*EvmreaderConfig, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) @@ -651,11 +663,11 @@ func LoadEvmreaderConfig() (*EvmreaderConfig, error) { return nil, fmt.Errorf("CARTESI_FEATURE_INPUT_READER_ENABLED is required for the evmreader service: %w", err) } - cfg.TelemetryAddress, err = GetTelemetryAddress() + cfg.EvmReaderTelemetryAddress, err = GetEvmReaderTelemetryAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_TELEMETRY_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_EVM_READER_TELEMETRY_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_TELEMETRY_ADDRESS is required for the evmreader service: %w", err) + return nil, fmt.Errorf("CARTESI_EVM_READER_TELEMETRY_ADDRESS is required for the evmreader service: %w", err) } cfg.LogColor, err = GetLogColor() @@ -747,8 +759,8 @@ type JsonrpcConfig struct { // HTTP address for the JSON-RPC API. JsonrpcApiAddress string `mapstructure:"CARTESI_JSONRPC_API_ADDRESS"` - // HTTP address for telemetry service. - TelemetryAddress string `mapstructure:"CARTESI_TELEMETRY_ADDRESS"` + // HTTP address for JSON-RPC's telemetry service. + JsonrpcTelemetryAddress string `mapstructure:"CARTESI_JSONRPC_TELEMETRY_ADDRESS"` // If set to true, the node will add colors to its log output. LogColor bool `mapstructure:"CARTESI_LOG_COLOR"` @@ -763,8 +775,6 @@ type JsonrpcConfig struct { // LoadJsonrpcConfig reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func LoadJsonrpcConfig() (*JsonrpcConfig, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) @@ -790,11 +800,11 @@ func LoadJsonrpcConfig() (*JsonrpcConfig, error) { return nil, fmt.Errorf("CARTESI_JSONRPC_API_ADDRESS is required for the jsonrpc service: %w", err) } - cfg.TelemetryAddress, err = GetTelemetryAddress() + cfg.JsonrpcTelemetryAddress, err = GetJsonrpcTelemetryAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_TELEMETRY_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_JSONRPC_TELEMETRY_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_TELEMETRY_ADDRESS is required for the jsonrpc service: %w", err) + return nil, fmt.Errorf("CARTESI_JSONRPC_TELEMETRY_ADDRESS is required for the jsonrpc service: %w", err) } cfg.LogColor, err = GetLogColor() @@ -873,8 +883,8 @@ type NodeConfig struct { // HTTP address for the JSON-RPC API. JsonrpcApiAddress string `mapstructure:"CARTESI_JSONRPC_API_ADDRESS"` - // HTTP address for telemetry service. - TelemetryAddress string `mapstructure:"CARTESI_TELEMETRY_ADDRESS"` + // HTTP address for Node's telemetry service. + NodeTelemetryAddress string `mapstructure:"CARTESI_NODE_TELEMETRY_ADDRESS"` // If set to true, the node will add colors to its log output. LogColor bool `mapstructure:"CARTESI_LOG_COLOR"` @@ -933,8 +943,6 @@ type NodeConfig struct { // LoadNodeConfig reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func LoadNodeConfig() (*NodeConfig, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) @@ -1037,11 +1045,11 @@ func LoadNodeConfig() (*NodeConfig, error) { return nil, fmt.Errorf("CARTESI_JSONRPC_API_ADDRESS is required for the node service: %w", err) } - cfg.TelemetryAddress, err = GetTelemetryAddress() + cfg.NodeTelemetryAddress, err = GetNodeTelemetryAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_TELEMETRY_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_NODE_TELEMETRY_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_TELEMETRY_ADDRESS is required for the node service: %w", err) + return nil, fmt.Errorf("CARTESI_NODE_TELEMETRY_ADDRESS is required for the node service: %w", err) } cfg.LogColor, err = GetLogColor() @@ -1196,8 +1204,8 @@ type PrtConfig struct { // If set to false, the node will not submit claims (reader mode). FeatureClaimSubmissionEnabled bool `mapstructure:"CARTESI_FEATURE_CLAIM_SUBMISSION_ENABLED"` - // HTTP address for telemetry service. - TelemetryAddress string `mapstructure:"CARTESI_TELEMETRY_ADDRESS"` + // HTTP address for PRT's telemetry service. + PrtTelemetryAddress string `mapstructure:"CARTESI_PRT_TELEMETRY_ADDRESS"` // If set to true, the node will add colors to its log output. LogColor bool `mapstructure:"CARTESI_LOG_COLOR"` @@ -1230,8 +1238,6 @@ type PrtConfig struct { // LoadPrtConfig reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func LoadPrtConfig() (*PrtConfig, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) @@ -1285,11 +1291,11 @@ func LoadPrtConfig() (*PrtConfig, error) { return nil, fmt.Errorf("CARTESI_FEATURE_CLAIM_SUBMISSION_ENABLED is required for the prt service: %w", err) } - cfg.TelemetryAddress, err = GetTelemetryAddress() + cfg.PrtTelemetryAddress, err = GetPrtTelemetryAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_TELEMETRY_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_PRT_TELEMETRY_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_TELEMETRY_ADDRESS is required for the prt service: %w", err) + return nil, fmt.Errorf("CARTESI_PRT_TELEMETRY_ADDRESS is required for the prt service: %w", err) } cfg.LogColor, err = GetLogColor() @@ -1371,8 +1377,8 @@ type ValidatorConfig struct { // for more information. DatabaseConnection URL `mapstructure:"CARTESI_DATABASE_CONNECTION"` - // HTTP address for telemetry service. - TelemetryAddress string `mapstructure:"CARTESI_TELEMETRY_ADDRESS"` + // HTTP address for Validator's telemetry service. + ValidatorTelemetryAddress string `mapstructure:"CARTESI_VALIDATOR_TELEMETRY_ADDRESS"` // If set to true, the node will add colors to its log output. LogColor bool `mapstructure:"CARTESI_LOG_COLOR"` @@ -1390,8 +1396,6 @@ type ValidatorConfig struct { // LoadValidatorConfig reads configuration from environment variables, a config file, and defaults. // Priority: command line flags > environment variables > config file > defaults. func LoadValidatorConfig() (*ValidatorConfig, error) { - SetDefaults() - // Load config file if specified via --config flag. if cfgFile := viper.GetString("config"); cfgFile != "" { viper.SetConfigFile(cfgFile) @@ -1410,11 +1414,11 @@ func LoadValidatorConfig() (*ValidatorConfig, error) { return nil, fmt.Errorf("CARTESI_DATABASE_CONNECTION is required for the validator service: %w", err) } - cfg.TelemetryAddress, err = GetTelemetryAddress() + cfg.ValidatorTelemetryAddress, err = GetValidatorTelemetryAddress() if err != nil && err != ErrNotDefined { - return nil, fmt.Errorf("failed to get CARTESI_TELEMETRY_ADDRESS: %w", err) + return nil, fmt.Errorf("failed to get CARTESI_VALIDATOR_TELEMETRY_ADDRESS: %w", err) } else if err == ErrNotDefined { - return nil, fmt.Errorf("CARTESI_TELEMETRY_ADDRESS is required for the validator service: %w", err) + return nil, fmt.Errorf("CARTESI_VALIDATOR_TELEMETRY_ADDRESS is required for the validator service: %w", err) } cfg.LogColor, err = GetLogColor() @@ -1455,7 +1459,6 @@ func (c *NodeConfig) ToAdvancerConfig() *AdvancerConfig { FeatureInspectEnabled: c.FeatureInspectEnabled, FeatureMachineHashCheckEnabled: c.FeatureMachineHashCheckEnabled, InspectAddress: c.InspectAddress, - TelemetryAddress: c.TelemetryAddress, LogColor: c.LogColor, LogLevel: c.LogLevel, JsonrpcMachineLogLevel: c.JsonrpcMachineLogLevel, @@ -1475,7 +1478,6 @@ func (c *NodeConfig) ToClaimerConfig() *ClaimerConfig { BlockchainLegacyEnabled: c.BlockchainLegacyEnabled, DatabaseConnection: c.DatabaseConnection, FeatureClaimSubmissionEnabled: c.FeatureClaimSubmissionEnabled, - TelemetryAddress: c.TelemetryAddress, LogColor: c.LogColor, LogLevel: c.LogLevel, BlockchainHttpMaxRetries: c.BlockchainHttpMaxRetries, @@ -1496,7 +1498,6 @@ func (c *NodeConfig) ToEvmreaderConfig() *EvmreaderConfig { BlockchainWsEndpoint: c.BlockchainWsEndpoint, DatabaseConnection: c.DatabaseConnection, FeatureInputReaderEnabled: c.FeatureInputReaderEnabled, - TelemetryAddress: c.TelemetryAddress, LogColor: c.LogColor, LogLevel: c.LogLevel, BlockchainHttpMaxRetries: c.BlockchainHttpMaxRetries, @@ -1515,7 +1516,6 @@ func (c *NodeConfig) ToJsonrpcConfig() *JsonrpcConfig { return &JsonrpcConfig{ DatabaseConnection: c.DatabaseConnection, JsonrpcApiAddress: c.JsonrpcApiAddress, - TelemetryAddress: c.TelemetryAddress, LogColor: c.LogColor, LogLevel: c.LogLevel, MaxStartupTime: c.MaxStartupTime, @@ -1531,7 +1531,6 @@ func (c *NodeConfig) ToPrtConfig() *PrtConfig { BlockchainLegacyEnabled: c.BlockchainLegacyEnabled, DatabaseConnection: c.DatabaseConnection, FeatureClaimSubmissionEnabled: c.FeatureClaimSubmissionEnabled, - TelemetryAddress: c.TelemetryAddress, LogColor: c.LogColor, LogLevel: c.LogLevel, BlockchainHttpMaxRetries: c.BlockchainHttpMaxRetries, @@ -1548,7 +1547,6 @@ func (c *NodeConfig) ToPrtConfig() *PrtConfig { func (c *NodeConfig) ToValidatorConfig() *ValidatorConfig { return &ValidatorConfig{ DatabaseConnection: c.DatabaseConnection, - TelemetryAddress: c.TelemetryAddress, LogColor: c.LogColor, LogLevel: c.LogLevel, MaxStartupTime: c.MaxStartupTime, @@ -1903,6 +1901,45 @@ func GetFeatureMachineHashCheckEnabled() (bool, error) { return notDefinedbool(), fmt.Errorf("%s: %w", FEATURE_MACHINE_HASH_CHECK_ENABLED, ErrNotDefined) } +// GetAdvancerTelemetryAddress returns the value for the environment variable CARTESI_ADVANCER_TELEMETRY_ADDRESS. +func GetAdvancerTelemetryAddress() (string, error) { + s := viper.GetString(ADVANCER_TELEMETRY_ADDRESS) + if s != "" { + v, err := toString(s) + if err != nil { + return v, fmt.Errorf("failed to parse %s: %w", ADVANCER_TELEMETRY_ADDRESS, err) + } + return v, nil + } + return notDefinedstring(), fmt.Errorf("%s: %w", ADVANCER_TELEMETRY_ADDRESS, ErrNotDefined) +} + +// GetClaimerTelemetryAddress returns the value for the environment variable CARTESI_CLAIMER_TELEMETRY_ADDRESS. +func GetClaimerTelemetryAddress() (string, error) { + s := viper.GetString(CLAIMER_TELEMETRY_ADDRESS) + if s != "" { + v, err := toString(s) + if err != nil { + return v, fmt.Errorf("failed to parse %s: %w", CLAIMER_TELEMETRY_ADDRESS, err) + } + return v, nil + } + return notDefinedstring(), fmt.Errorf("%s: %w", CLAIMER_TELEMETRY_ADDRESS, ErrNotDefined) +} + +// GetEvmReaderTelemetryAddress returns the value for the environment variable CARTESI_EVM_READER_TELEMETRY_ADDRESS. +func GetEvmReaderTelemetryAddress() (string, error) { + s := viper.GetString(EVM_READER_TELEMETRY_ADDRESS) + if s != "" { + v, err := toString(s) + if err != nil { + return v, fmt.Errorf("failed to parse %s: %w", EVM_READER_TELEMETRY_ADDRESS, err) + } + return v, nil + } + return notDefinedstring(), fmt.Errorf("%s: %w", EVM_READER_TELEMETRY_ADDRESS, ErrNotDefined) +} + // GetInspectAddress returns the value for the environment variable CARTESI_INSPECT_ADDRESS. func GetInspectAddress() (string, error) { s := viper.GetString(INSPECT_ADDRESS) @@ -1955,17 +1992,56 @@ func GetJsonrpcApiUrl() (string, error) { return notDefinedstring(), fmt.Errorf("%s: %w", JSONRPC_API_URL, ErrNotDefined) } -// GetTelemetryAddress returns the value for the environment variable CARTESI_TELEMETRY_ADDRESS. -func GetTelemetryAddress() (string, error) { - s := viper.GetString(TELEMETRY_ADDRESS) +// GetJsonrpcTelemetryAddress returns the value for the environment variable CARTESI_JSONRPC_TELEMETRY_ADDRESS. +func GetJsonrpcTelemetryAddress() (string, error) { + s := viper.GetString(JSONRPC_TELEMETRY_ADDRESS) + if s != "" { + v, err := toString(s) + if err != nil { + return v, fmt.Errorf("failed to parse %s: %w", JSONRPC_TELEMETRY_ADDRESS, err) + } + return v, nil + } + return notDefinedstring(), fmt.Errorf("%s: %w", JSONRPC_TELEMETRY_ADDRESS, ErrNotDefined) +} + +// GetNodeTelemetryAddress returns the value for the environment variable CARTESI_NODE_TELEMETRY_ADDRESS. +func GetNodeTelemetryAddress() (string, error) { + s := viper.GetString(NODE_TELEMETRY_ADDRESS) + if s != "" { + v, err := toString(s) + if err != nil { + return v, fmt.Errorf("failed to parse %s: %w", NODE_TELEMETRY_ADDRESS, err) + } + return v, nil + } + return notDefinedstring(), fmt.Errorf("%s: %w", NODE_TELEMETRY_ADDRESS, ErrNotDefined) +} + +// GetPrtTelemetryAddress returns the value for the environment variable CARTESI_PRT_TELEMETRY_ADDRESS. +func GetPrtTelemetryAddress() (string, error) { + s := viper.GetString(PRT_TELEMETRY_ADDRESS) + if s != "" { + v, err := toString(s) + if err != nil { + return v, fmt.Errorf("failed to parse %s: %w", PRT_TELEMETRY_ADDRESS, err) + } + return v, nil + } + return notDefinedstring(), fmt.Errorf("%s: %w", PRT_TELEMETRY_ADDRESS, ErrNotDefined) +} + +// GetValidatorTelemetryAddress returns the value for the environment variable CARTESI_VALIDATOR_TELEMETRY_ADDRESS. +func GetValidatorTelemetryAddress() (string, error) { + s := viper.GetString(VALIDATOR_TELEMETRY_ADDRESS) if s != "" { v, err := toString(s) if err != nil { - return v, fmt.Errorf("failed to parse %s: %w", TELEMETRY_ADDRESS, err) + return v, fmt.Errorf("failed to parse %s: %w", VALIDATOR_TELEMETRY_ADDRESS, err) } return v, nil } - return notDefinedstring(), fmt.Errorf("%s: %w", TELEMETRY_ADDRESS, ErrNotDefined) + return notDefinedstring(), fmt.Errorf("%s: %w", VALIDATOR_TELEMETRY_ADDRESS, ErrNotDefined) } // GetLogColor returns the value for the environment variable CARTESI_LOG_COLOR. From ae7e7bd78b028f2e2ebd21542ce25bf37e119f56 Mon Sep 17 00:00:00 2001 From: Renato Maia <1887792+renatomaia@users.noreply.github.com> Date: Mon, 13 Apr 2026 20:36:42 -0300 Subject: [PATCH 3/4] fix(services): show errors on service log --- cmd/cartesi-rollups-advancer/root/root.go | 9 ++++-- cmd/cartesi-rollups-claimer/root/root.go | 16 +++++------ cmd/cartesi-rollups-evm-reader/root/root.go | 21 +++++++------- cmd/cartesi-rollups-jsonrpc-api/root/root.go | 9 ++++-- cmd/cartesi-rollups-node/root/root.go | 16 ++++++----- cmd/cartesi-rollups-prt/root/root.go | 16 +++++------ cmd/cartesi-rollups-validator/root/root.go | 9 ++++-- internal/cli/cobra.go | 29 ++++++++++++++++++++ pkg/service/service.go | 8 +++++- 9 files changed, 90 insertions(+), 43 deletions(-) diff --git a/cmd/cartesi-rollups-advancer/root/root.go b/cmd/cartesi-rollups-advancer/root/root.go index 418e23bd4..d8680f501 100644 --- a/cmd/cartesi-rollups-advancer/root/root.go +++ b/cmd/cartesi-rollups-advancer/root/root.go @@ -91,14 +91,17 @@ func run(cmd *cobra.Command, args []string) { }, Config: *cfg, } + logger := service.NewServiceLogger(&createInfo.CreateInfo) + createInfo.CreateInfo.Logger = logger + var err error createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw()) - cobra.CheckErr(err) + cli.CheckErr(logger, err) defer createInfo.Repository.Close() advancerService, err := advancer.Create(ctx, &createInfo) - cobra.CheckErr(err) + cli.CheckErr(logger, err) advancerService.LogConfig(createInfo.Config) - cobra.CheckErr(advancerService.Serve()) + cli.CheckErr(logger, advancerService.Serve()) } diff --git a/cmd/cartesi-rollups-claimer/root/root.go b/cmd/cartesi-rollups-claimer/root/root.go index 0633a23b1..d0a98b39a 100644 --- a/cmd/cartesi-rollups-claimer/root/root.go +++ b/cmd/cartesi-rollups-claimer/root/root.go @@ -80,11 +80,10 @@ func run(cmd *cobra.Command, args []string) { ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime) defer cancel() - logLevel := config.ResolveServiceLogLevel(config.ServiceClaimer, cfg.LogLevel) createInfo := claimer.CreateInfo{ CreateInfo: service.CreateInfo{ Name: config.ServiceClaimer, - LogLevel: logLevel, + LogLevel: config.ResolveServiceLogLevel(config.ServiceClaimer, cfg.LogLevel), LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, @@ -93,10 +92,11 @@ func run(cmd *cobra.Command, args []string) { }, Config: *cfg, } + logger := service.NewServiceLogger(&createInfo.CreateInfo) + createInfo.CreateInfo.Logger = logger - logger := service.NewLogger(logLevel, cfg.LogColor).With("service", config.ServiceClaimer) authOpt, err := config.HTTPAuthorizationOption() - cobra.CheckErr(err) + cli.CheckErr(logger, err) createInfo.EthConn, err = ethutil.NewEthClient( ctx, cfg.BlockchainHttpEndpoint.Raw(), logger, ethutil.RetryConfig{ @@ -104,16 +104,16 @@ func run(cmd *cobra.Command, args []string) { RetryMinWait: cfg.BlockchainHttpRetryMinWait, RetryMaxWait: cfg.BlockchainHttpRetryMaxWait, }, authOpt) - cobra.CheckErr(err) + cli.CheckErr(logger, err) createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw()) - cobra.CheckErr(err) + cli.CheckErr(logger, err) defer createInfo.Repository.Close() claimerService, err := claimer.Create(ctx, &createInfo) - cobra.CheckErr(err) + cli.CheckErr(logger, err) claimerService.LogConfig(createInfo.Config) err = claimerService.Serve() - cobra.CheckErr(err) + cli.CheckErr(logger, err) } diff --git a/cmd/cartesi-rollups-evm-reader/root/root.go b/cmd/cartesi-rollups-evm-reader/root/root.go index ef07fd340..cae77132f 100644 --- a/cmd/cartesi-rollups-evm-reader/root/root.go +++ b/cmd/cartesi-rollups-evm-reader/root/root.go @@ -77,14 +77,14 @@ func init() { } } -func run(cmd *cobra.Command, args []string) { ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime) +func run(cmd *cobra.Command, args []string) { + ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime) defer cancel() - logLevel := config.ResolveServiceLogLevel(config.ServiceEvmReader, cfg.LogLevel) createInfo := evmreader.CreateInfo{ CreateInfo: service.CreateInfo{ Name: config.ServiceEvmReader, - LogLevel: logLevel, + LogLevel: config.ResolveServiceLogLevel(config.ServiceEvmReader, cfg.LogLevel), LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, @@ -92,11 +92,12 @@ func run(cmd *cobra.Command, args []string) { ctx, cancel := context.WithTimeout }, Config: *cfg, } + logger := service.NewServiceLogger(&createInfo.CreateInfo) + createInfo.CreateInfo.Logger = logger var err error - logger := service.NewLogger(logLevel, cfg.LogColor).With("service", config.ServiceEvmReader) authOpt, err := config.HTTPAuthorizationOption() - cobra.CheckErr(err) + cli.CheckErr(logger, err) createInfo.EthClient, err = ethutil.NewEthClient( ctx, cfg.BlockchainHttpEndpoint.Raw(), logger, ethutil.RetryConfig{ @@ -104,19 +105,19 @@ func run(cmd *cobra.Command, args []string) { ctx, cancel := context.WithTimeout RetryMinWait: cfg.BlockchainHttpRetryMinWait, RetryMaxWait: cfg.BlockchainHttpRetryMaxWait, }, authOpt) - cobra.CheckErr(err) + cli.CheckErr(logger, err) wsEndpoint := cfg.BlockchainWsEndpoint.Raw() createInfo.EthWsClient, err = ethclient.DialContext(ctx, wsEndpoint) - cobra.CheckErr(ethutil.RedactEndpointFromError(err, wsEndpoint)) + cli.CheckErr(logger, ethutil.RedactEndpointFromError(err, wsEndpoint)) createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw()) - cobra.CheckErr(err) + cli.CheckErr(logger, err) defer createInfo.Repository.Close() readerService, err := evmreader.Create(ctx, &createInfo) - cobra.CheckErr(err) + cli.CheckErr(logger, err) readerService.LogConfig(createInfo.Config) - cobra.CheckErr(readerService.Serve()) + cli.CheckErr(logger, readerService.Serve()) } diff --git a/cmd/cartesi-rollups-jsonrpc-api/root/root.go b/cmd/cartesi-rollups-jsonrpc-api/root/root.go index b80a2ec3e..1da348eff 100644 --- a/cmd/cartesi-rollups-jsonrpc-api/root/root.go +++ b/cmd/cartesi-rollups-jsonrpc-api/root/root.go @@ -78,14 +78,17 @@ func run(cmd *cobra.Command, args []string) { }, Config: *cfg, } + logger := service.NewServiceLogger(&createInfo.CreateInfo) + createInfo.CreateInfo.Logger = logger + var err error createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw()) - cobra.CheckErr(err) + cli.CheckErr(logger, err) defer createInfo.Repository.Close() jsonrpcService, err := jsonrpc.Create(ctx, &createInfo) - cobra.CheckErr(err) + cli.CheckErr(logger, err) jsonrpcService.LogConfig(createInfo.Config) - cobra.CheckErr(jsonrpcService.Serve()) + cli.CheckErr(logger, jsonrpcService.Serve()) } diff --git a/cmd/cartesi-rollups-node/root/root.go b/cmd/cartesi-rollups-node/root/root.go index bb5cd4f9d..f534f1d83 100644 --- a/cmd/cartesi-rollups-node/root/root.go +++ b/cmd/cartesi-rollups-node/root/root.go @@ -160,28 +160,30 @@ func run(cmd *cobra.Command, args []string) { }, Config: *cfg, } + logger := service.NewServiceLogger(&createInfo.CreateInfo) + createInfo.CreateInfo.Logger = logger var err error createInfo.ReaderClient, err = newEthClient(ctx, config.ServiceEvmReader) - cobra.CheckErr(err) + cli.CheckErr(logger, err) wsEndpoint := cfg.BlockchainWsEndpoint.Raw() createInfo.ReaderWSClient, err = ethclient.DialContext(ctx, wsEndpoint) - cobra.CheckErr(ethutil.RedactEndpointFromError(err, wsEndpoint)) + cli.CheckErr(logger, ethutil.RedactEndpointFromError(err, wsEndpoint)) createInfo.ClaimerClient, err = newEthClient(ctx, config.ServiceClaimer) - cobra.CheckErr(err) + cli.CheckErr(logger, err) createInfo.PrtClient, err = newEthClient(ctx, config.ServicePrt) - cobra.CheckErr(err) + cli.CheckErr(logger, err) createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw()) - cobra.CheckErr(err) + cli.CheckErr(logger, err) defer createInfo.Repository.Close() nodeService, err := node.Create(ctx, &createInfo) - cobra.CheckErr(err) + cli.CheckErr(logger, err) nodeService.LogConfig(createInfo.Config) - cobra.CheckErr(nodeService.Serve()) + cli.CheckErr(logger, nodeService.Serve()) } diff --git a/cmd/cartesi-rollups-prt/root/root.go b/cmd/cartesi-rollups-prt/root/root.go index b9dbf1f7e..e7f13673d 100644 --- a/cmd/cartesi-rollups-prt/root/root.go +++ b/cmd/cartesi-rollups-prt/root/root.go @@ -68,11 +68,10 @@ func run(cmd *cobra.Command, args []string) { ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime) defer cancel() - logLevel := config.ResolveServiceLogLevel(config.ServicePrt, cfg.LogLevel) createInfo := prt.CreateInfo{ CreateInfo: service.CreateInfo{ Name: config.ServicePrt, - LogLevel: logLevel, + LogLevel: config.ResolveServiceLogLevel(config.ServicePrt, cfg.LogLevel), LogColor: cfg.LogColor, EnableSignalHandling: true, TelemetryCreate: true, @@ -81,11 +80,12 @@ func run(cmd *cobra.Command, args []string) { }, Config: *cfg, } + logger := service.NewServiceLogger(&createInfo.CreateInfo) + createInfo.CreateInfo.Logger = logger var err error - logger := service.NewLogger(logLevel, cfg.LogColor).With("service", config.ServicePrt) authOpt, err := config.HTTPAuthorizationOption() - cobra.CheckErr(err) + cli.CheckErr(logger, err) createInfo.EthClient, err = ethutil.NewEthClient( ctx, cfg.BlockchainHttpEndpoint.Raw(), logger, ethutil.RetryConfig{ @@ -93,15 +93,15 @@ func run(cmd *cobra.Command, args []string) { RetryMinWait: cfg.BlockchainHttpRetryMinWait, RetryMaxWait: cfg.BlockchainHttpRetryMaxWait, }, authOpt) - cobra.CheckErr(err) + cli.CheckErr(logger, err) createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw()) - cobra.CheckErr(err) + cli.CheckErr(logger, err) defer createInfo.Repository.Close() prtService, err := prt.Create(ctx, &createInfo) - cobra.CheckErr(err) + cli.CheckErr(logger, err) prtService.LogConfig(createInfo.Config) - cobra.CheckErr(prtService.Serve()) + cli.CheckErr(logger, prtService.Serve()) } diff --git a/cmd/cartesi-rollups-validator/root/root.go b/cmd/cartesi-rollups-validator/root/root.go index 9283f7f9c..1fa08a336 100644 --- a/cmd/cartesi-rollups-validator/root/root.go +++ b/cmd/cartesi-rollups-validator/root/root.go @@ -79,14 +79,17 @@ func run(cmd *cobra.Command, args []string) { }, Config: *cfg, } + logger := service.NewServiceLogger(&createInfo.CreateInfo) + createInfo.CreateInfo.Logger = logger + var err error createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw()) - cobra.CheckErr(err) + cli.CheckErr(logger, err) defer createInfo.Repository.Close() validatorService, err := validator.Create(ctx, &createInfo) - cobra.CheckErr(err) + cli.CheckErr(logger, err) validatorService.LogConfig(createInfo.Config) - cobra.CheckErr(validatorService.Serve()) + cli.CheckErr(logger, validatorService.Serve()) } diff --git a/internal/cli/cobra.go b/internal/cli/cobra.go index bf5889ff9..8da67f4c9 100644 --- a/internal/cli/cobra.go +++ b/internal/cli/cobra.go @@ -4,6 +4,9 @@ package cli import ( + "fmt" + "log/slog" + "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" @@ -28,3 +31,29 @@ func AddFlagStrVarP(flags *pflag.FlagSet, varRef *string, flagName string, flagS flags.StringVarP(varRef, flagName, flagShort, viper.GetString(cfgName), flagDesc) cobra.CheckErr(viper.BindPFlag(cfgName, flags.Lookup(flagName))) } + +func CheckErr(logger *slog.Logger, err error, args ...any) { + if err == nil { + return + } + + msg := "Error" + if len(args) > 0 { + arg0 := args[0] + args = args[1:] + switch value := arg0.(type) { + case string: + msg = value + case []byte: + msg = string(value) + case fmt.Stringer: + msg = value.String() + default: + msg = fmt.Sprintf("%v", value) + } + } + + args = append([]any{"error", err}, args...) + logger.Error(msg, args...) + cobra.CheckErr(err) +} diff --git a/pkg/service/service.go b/pkg/service/service.go index 9e71903ea..6cd298d09 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -117,6 +117,7 @@ type CreateInfo struct { TelemetryAddress string PollInterval time.Duration Impl ServiceImpl + Logger *slog.Logger ServeMux *http.ServeMux Context context.Context Cancel context.CancelFunc @@ -176,10 +177,11 @@ func Create(ctx context.Context, c *CreateInfo, s *Service) error { s.Running.Store(false) s.Name = c.Name s.Impl = c.Impl + s.Logger = c.Logger // log if s.Logger == nil { - s.Logger = NewLogger(c.LogLevel, c.LogColor).With("service", s.Name) + s.Logger = NewServiceLogger(c) } // context and cancelation @@ -413,6 +415,10 @@ func NewLogger(level slog.Level, color bool) *slog.Logger { return slog.New(handler) } +func NewServiceLogger(c *CreateInfo) *slog.Logger { + return NewLogger(c.LogLevel, c.LogColor).With("service", c.Name) +} + // Telemetry func (s *Service) CreateDefaultTelemetry( addr string, From af7699ca28ca2b1ad99b4d18ee69f7e088fc08d3 Mon Sep 17 00:00:00 2001 From: Renato Maia <1887792+renatomaia@users.noreply.github.com> Date: Tue, 14 Apr 2026 08:41:19 -0300 Subject: [PATCH 4/4] style: format code using standard Go style --- internal/advancer/advancer_test.go | 8 ++++---- internal/evmreader/dave_consensus_test.go | 2 +- internal/repository/postgres/epoch.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/advancer/advancer_test.go b/internal/advancer/advancer_test.go index cfc0c1e9e..229825d29 100644 --- a/internal/advancer/advancer_test.go +++ b/internal/advancer/advancer_test.go @@ -1882,10 +1882,10 @@ type MockRepository struct { ApplicationStateUpdates int LastApplicationState ApplicationState LastApplicationStateReason *string - OutputsProofUpdated bool - RepeatOutputsProofCalled bool - SnapshotURIUpdated bool - EpochInputsProcessedCount int + OutputsProofUpdated bool + RepeatOutputsProofCalled bool + SnapshotURIUpdated bool + EpochInputsProcessedCount int mu sync.Mutex } diff --git a/internal/evmreader/dave_consensus_test.go b/internal/evmreader/dave_consensus_test.go index fa0e5cb72..3594126bd 100644 --- a/internal/evmreader/dave_consensus_test.go +++ b/internal/evmreader/dave_consensus_test.go @@ -352,7 +352,7 @@ func (s *SealedEpochsSuite) TestOpenEpochExistingEpochAccumulatesInputs() { // Existing epoch reused with accumulated inputs s.Require().Equal(uint64(1), storedEpoch.Index) s.Require().Equal(uint64(100), storedEpoch.FirstBlock) // Preserved - s.Require().Equal(mostRecentBlock, storedEpoch.LastBlock) // Updated + s.Require().Equal(mostRecentBlock, storedEpoch.LastBlock) // Updated s.Require().Equal(uint64(3), storedEpoch.InputIndexLowerBound) // Preserved s.Require().Equal(uint64(5), storedEpoch.InputIndexUpperBound) // 4 + 1 new s.Require().Equal(EpochStatus_Open, storedEpoch.Status) diff --git a/internal/repository/postgres/epoch.go b/internal/repository/postgres/epoch.go index 5d3aa0565..3b180c4ab 100644 --- a/internal/repository/postgres/epoch.go +++ b/internal/repository/postgres/epoch.go @@ -180,8 +180,8 @@ func (r *PostgresRepository) CreateEpochsAndInputs( ) sqlStr, args := inputInsertStmt.QUERY(inputSelectQuery). - ON_CONFLICT(table.Input.EpochApplicationID, table.Input.Index). - DO_NOTHING().Sql() + ON_CONFLICT(table.Input.EpochApplicationID, table.Input.Index). + DO_NOTHING().Sql() batch.Queue(sqlStr, args...) }