From b6147733d2e7d2508d9ec82723ccb7a90d625262 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 19 Feb 2025 13:56:12 +0000 Subject: [PATCH 1/9] add monitoring routes Signed-off-by: Chengxuan Xing --- Makefile | 2 +- cmd/client_eventstreams_delete.go | 2 +- cmd/client_eventstreams_list.go | 2 +- cmd/client_listeners_delete.go | 2 +- cmd/client_listeners_list.go | 2 +- cmd/migrate.go | 2 +- internal/apiclient/eventstreams.go | 8 +-- internal/confirmations/confirmations.go | 1 + .../confirmations/confirmed_block_listener.go | 1 + internal/events/eventstream.go | 11 +++- internal/metrics/metrics.go | 7 +- .../leveldb/leveldb_persistence.go | 5 +- .../persistence/postgres/sqlpersistence.go | 1 + .../postgres/transaction_writer.go | 4 +- internal/persistence/postgres/transactions.go | 1 + internal/persistence/postgres/txhistory.go | 2 + internal/tmconfig/tmconfig.go | 26 ++++++-- internal/tmmsgs/en_config_descriptions.go | 18 ++--- pkg/apitypes/api_types.go | 65 ++++++++++--------- pkg/fftm/api.go | 21 ++++-- pkg/fftm/manager.go | 46 ++++++------- pkg/fftm/manager_test.go | 14 ++-- pkg/fftm/routes.go | 11 +++- 23 files changed, 154 insertions(+), 100 deletions(-) diff --git a/Makefile b/Makefile index 40bbc938..43292e1e 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ coverage.html: $(VGO) tool cover -html=coverage.txt coverage: test coverage.html lint: - $(VGO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 + $(VGO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5 GOGC=20 $(LINT) run -v --timeout 5m ${MOCKERY}: diff --git a/cmd/client_eventstreams_delete.go b/cmd/client_eventstreams_delete.go index 1def5d69..07fa9496 100644 --- a/cmd/client_eventstreams_delete.go +++ b/cmd/client_eventstreams_delete.go @@ -30,7 +30,7 @@ func clientEventStreamsDeleteCommand(clientFactory func() (apiclient.FFTMClient, Use: "delete", Short: "Delete event streams", Long: "", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { client, err := clientFactory() if err != nil { return err diff --git a/cmd/client_eventstreams_list.go b/cmd/client_eventstreams_list.go index 30909546..99d03f02 100644 --- a/cmd/client_eventstreams_list.go +++ b/cmd/client_eventstreams_list.go @@ -30,7 +30,7 @@ func clientEventStreamsListCommand(clientFactory func() (apiclient.FFTMClient, e Use: "list", Short: "List event streams", Long: "", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { client, err := clientFactory() if err != nil { return err diff --git a/cmd/client_listeners_delete.go b/cmd/client_listeners_delete.go index b2c97920..dc07d22c 100644 --- a/cmd/client_listeners_delete.go +++ b/cmd/client_listeners_delete.go @@ -30,7 +30,7 @@ func clientListenersDeleteCommand(clientFactory func() (apiclient.FFTMClient, er Use: "delete", Short: "Delete event streams", Long: "", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { client, err := clientFactory() if err != nil { return err diff --git a/cmd/client_listeners_list.go b/cmd/client_listeners_list.go index 5e8513b0..bfe62986 100644 --- a/cmd/client_listeners_list.go +++ b/cmd/client_listeners_list.go @@ -30,7 +30,7 @@ func clientListenersListCommand(clientFactory func() (apiclient.FFTMClient, erro Use: "list", Short: "List listeners", Long: "", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { client, err := clientFactory() if err != nil { return err diff --git a/cmd/migrate.go b/cmd/migrate.go index 8c60a089..c32a7909 100644 --- a/cmd/migrate.go +++ b/cmd/migrate.go @@ -41,7 +41,7 @@ func buildLeveldb2postgresCommand(initConfig func() error) *cobra.Command { leveldb2postgresEventStreamsCmd := &cobra.Command{ Use: "leveldb2postgres", Short: "Migrate from LevelDB to PostgreSQL persistence", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if err := initConfig(); err != nil { return err } diff --git a/internal/apiclient/eventstreams.go b/internal/apiclient/eventstreams.go index df4cd92e..90b5e8c9 100644 --- a/internal/apiclient/eventstreams.go +++ b/internal/apiclient/eventstreams.go @@ -31,7 +31,7 @@ func (c *fftmClient) GetEventStreams(ctx context.Context) ([]apitypes.EventStrea SetResult(&eventStreams). Get("eventstreams") if !resp.IsSuccess() { - return nil, fmt.Errorf(string(resp.Body())) + return nil, fmt.Errorf("%s", string(resp.Body())) } return eventStreams, err } @@ -43,7 +43,7 @@ func (c *fftmClient) GetListeners(ctx context.Context, eventStreamID string) ([] SetResult(&listeners). Get(fmt.Sprintf("eventstreams/%s/listeners", eventStreamID)) if !resp.IsSuccess() { - return nil, fmt.Errorf(string(resp.Body())) + return nil, fmt.Errorf("%s", string(resp.Body())) } return listeners, err } @@ -56,7 +56,7 @@ func (c *fftmClient) DeleteEventStream(ctx context.Context, eventStreamID string return err } if !resp.IsSuccess() { - return fmt.Errorf(string(resp.Body())) + return fmt.Errorf("%s", string(resp.Body())) } return nil } @@ -92,7 +92,7 @@ func (c *fftmClient) DeleteListener(ctx context.Context, eventStreamID, listener return err } if !resp.IsSuccess() { - return fmt.Errorf(string(resp.Body())) + return fmt.Errorf("%s", string(resp.Body())) } return nil } diff --git a/internal/confirmations/confirmations.go b/internal/confirmations/confirmations.go index 81235826..5e543fb9 100644 --- a/internal/confirmations/confirmations.go +++ b/internal/confirmations/confirmations.go @@ -311,6 +311,7 @@ func (bcm *blockConfirmationManager) getBlockByHash(blockHash string) (*apitypes func (bcm *blockConfirmationManager) getBlockByNumber(blockNumber uint64, allowCache bool, expectedParentHash string) (*apitypes.BlockInfo, error) { res, reason, err := bcm.connector.BlockInfoByNumber(bcm.ctx, &ffcapi.BlockInfoByNumberRequest{ + //nolint:gosec BlockNumber: fftypes.NewFFBigInt(int64(blockNumber)), AllowCache: allowCache, ExpectedParentHash: expectedParentHash, diff --git a/internal/confirmations/confirmed_block_listener.go b/internal/confirmations/confirmed_block_listener.go index bd004504..fa8cda41 100644 --- a/internal/confirmations/confirmed_block_listener.go +++ b/internal/confirmations/confirmed_block_listener.go @@ -357,6 +357,7 @@ func (cbl *confirmedBlockListener) dispatchAllConfirmed() { BlockEvent: &ffcapi.BlockEvent{ ListenerID: cbl.id, BlockInfo: ffcapi.BlockInfo{ + //nolint:gosec BlockNumber: fftypes.NewFFBigInt(int64(block.BlockNumber)), BlockHash: block.BlockHash, ParentHash: block.ParentHash, diff --git a/internal/events/eventstream.go b/internal/events/eventstream.go index 9de8b39e..646251d1 100644 --- a/internal/events/eventstream.go +++ b/internal/events/eventstream.go @@ -65,6 +65,7 @@ var esDefaults struct { } func InitDefaults() { + //nolint:gosec esDefaults.batchSize = config.GetInt64(tmconfig.EventStreamsDefaultsBatchSize) esDefaults.batchTimeout = fftypes.FFDuration(config.GetDuration(tmconfig.EventStreamsDefaultsBatchTimeout)) esDefaults.errorHandling = fftypes.FFEnum(config.GetString(tmconfig.EventStreamsDefaultsErrorHandling)) @@ -218,6 +219,7 @@ func mergeValidateEsConfig(ctx context.Context, base *apitypes.EventStream, upda // Batch timeout if updates.EthCompatBatchTimeoutMS != nil { + //nolint:gosec dv := fftypes.FFDuration(*updates.EthCompatBatchTimeoutMS) * fftypes.FFDuration(time.Millisecond) changed = apitypes.CheckUpdateDuration(changed, &merged.BatchTimeout, base.BatchTimeout, &dv, esDefaults.batchTimeout) } else { @@ -226,6 +228,7 @@ func mergeValidateEsConfig(ctx context.Context, base *apitypes.EventStream, upda // Retry timeout if updates.EthCompatRetryTimeoutSec != nil { + //nolint:gosec dv := fftypes.FFDuration(*updates.EthCompatRetryTimeoutSec) * fftypes.FFDuration(time.Second) changed = apitypes.CheckUpdateDuration(changed, &merged.RetryTimeout, base.RetryTimeout, &dv, esDefaults.retryTimeout) } else { @@ -234,6 +237,7 @@ func mergeValidateEsConfig(ctx context.Context, base *apitypes.EventStream, upda // Blocked retry delay if updates.EthCompatBlockedRetryDelaySec != nil { + //nolint:gosec dv := fftypes.FFDuration(*updates.EthCompatBlockedRetryDelaySec) * fftypes.FFDuration(time.Second) changed = apitypes.CheckUpdateDuration(changed, &merged.BlockedRetryDelay, base.BlockedRetryDelay, &dv, esDefaults.blockedRetryDelay) } else { @@ -509,7 +513,8 @@ func (es *eventStream) Start(ctx context.Context) error { startTime: fftypes.Now(), eventLoopDone: make(chan struct{}), batchLoopDone: make(chan struct{}), - updates: make(chan *ffcapi.ListenerEvent, int(*es.spec.BatchSize)), + //nolint:gosec + updates: make(chan *ffcapi.ListenerEvent, int(*es.spec.BatchSize)), } startedState.ctx, startedState.cancelCtx = context.WithCancel(es.bgCtx) es.currentState = startedState @@ -781,6 +786,8 @@ func (es *eventStream) checkConfirmedEventForBatch(e *ffcapi.ListenerEvent) (l * func (es *eventStream) batchLoop(startedState *startedStreamState) { defer close(startedState.batchLoopDone) ctx := startedState.ctx + + //nolint:gosec maxSize := int(*es.spec.BatchSize) batchNumber := int64(0) @@ -955,7 +962,7 @@ func (es *eventStream) writeCheckpoint(startedState *startedStreamState, batch * } // We only return if the context is cancelled, or the checkpoint succeeds - return es.retry.Do(startedState.ctx, "checkpoint", func(attempt int) (retry bool, err error) { + return es.retry.Do(startedState.ctx, "checkpoint", func(_ int) (retry bool, err error) { return true, es.persistence.WriteCheckpoint(startedState.ctx, cp) }) } diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index b0115d0b..7fc5fa54 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -58,7 +58,7 @@ func NewMetricsManager(ctx context.Context) Metrics { ) mm := &metricsManager{ ctx: ctx, - metricsEnabled: config.GetBool(tmconfig.MetricsEnabled), + metricsEnabled: config.GetBool(tmconfig.DeprecatedMetricsEnabled) || config.GetBool(tmconfig.MonitoringEnabled), timeMap: make(map[string]time.Time), metricsRegistry: metricsRegistry, eventsMetricsManager: eventsMetricsManager, @@ -74,7 +74,10 @@ func (mm *metricsManager) IsMetricsEnabled() bool { } func (mm *metricsManager) HTTPHandler() http.Handler { - httpHandler, _ := mm.metricsRegistry.HTTPHandler(mm.ctx, promhttp.HandlerOpts{}) + httpHandler, err := mm.metricsRegistry.HTTPHandler(mm.ctx, promhttp.HandlerOpts{}) + if err != nil { + panic(err) + } return httpHandler } diff --git a/internal/persistence/leveldb/leveldb_persistence.go b/internal/persistence/leveldb/leveldb_persistence.go index 402b3cbe..530b3b33 100644 --- a/internal/persistence/leveldb/leveldb_persistence.go +++ b/internal/persistence/leveldb/leveldb_persistence.go @@ -478,6 +478,7 @@ func (p *leveldbPersistence) InsertTransactionWithNextNonce(ctx context.Context, // From this point on, we will guide this transaction through to submission. // We return an "ack" at this point, and dispatch the work of getting the transaction submitted // to the background worker. + //nolint:gosec // Safe conversion as nonce is always positive tx.Nonce = fftypes.NewFFBigInt(int64(lockedNonce.nonce)) if err = p.writeTransaction(ctx, &apitypes.TXWithStatus{ @@ -586,7 +587,7 @@ func (p *leveldbPersistence) UpdateTransaction(ctx context.Context, txID string, return p.writeTransaction(ctx, tx, false) } -func (p *leveldbPersistence) writeTransaction(ctx context.Context, tx *apitypes.TXWithStatus, new bool) (err error) { +func (p *leveldbPersistence) writeTransaction(ctx context.Context, tx *apitypes.TXWithStatus, newTx bool) (err error) { // We take a write-lock here, because we are writing multiple values (the indexes), and anybody // attempting to read the critical nonce allocation index must know the difference between a partial write // (we crashed before we completed all the writes) and an incomplete write that's in process. @@ -608,7 +609,7 @@ func (p *leveldbPersistence) writeTransaction(ctx context.Context, tx *apitypes. return i18n.NewError(ctx, tmmsgs.MsgPersistenceTXIncomplete) } idKey := txDataKey(tx.ID) - if new { + if newTx { if tx.SequenceID != "" { // for new transactions sequence ID should always be generated by persistence layer // as the format of its value is persistence service specific diff --git a/internal/persistence/postgres/sqlpersistence.go b/internal/persistence/postgres/sqlpersistence.go index da0511ff..6af2a80f 100644 --- a/internal/persistence/postgres/sqlpersistence.go +++ b/internal/persistence/postgres/sqlpersistence.go @@ -103,6 +103,7 @@ func (p *sqlPersistence) RichQuery() persistence.RichQuery { } func (p *sqlPersistence) seqAfterFilter(ctx context.Context, qf *ffapi.QueryFields, after *int64, limit int, dir txhandler.SortDirection, conditions ...ffapi.Filter) (filter ffapi.Filter) { + //nolint:gosec // Safe conversion as limit is always positive fb := qf.NewFilterLimit(ctx, uint64(limit)) if after != nil { if dir == txhandler.SortDirectionDescending { diff --git a/internal/persistence/postgres/transaction_writer.go b/internal/persistence/postgres/transaction_writer.go index 0099671d..c4c91400 100644 --- a/internal/persistence/postgres/transaction_writer.go +++ b/internal/persistence/postgres/transaction_writer.go @@ -98,7 +98,8 @@ func newTransactionWriter(bgCtx context.Context, p *sqlPersistence, conf config. batchMaxSize := conf.GetInt(ConfigTXWriterBatchSize) cacheSlots := conf.GetInt(ConfigTXWriterCacheSlots) tw = &transactionWriter{ - p: p, + p: p, + //nolint:gosec // Safe conversion as workerCount is always positive workerCount: uint32(workerCount), batchTimeout: conf.GetDuration(ConfigTXWriterBatchTimeout), batchMaxSize: batchMaxSize, @@ -354,6 +355,7 @@ func (tw *transactionWriter) assignNonces(ctx context.Context, txInsertsByFrom m } } log.L(ctx).Infof("Assigned nonce %s / %d to %s", signer, cacheEntry.nextNonce, op.txInsert.ID) + //nolint:gosec // Safe conversion as nextNonce is always positive op.txInsert.Nonce = fftypes.NewFFBigInt(int64(cacheEntry.nextNonce)) cacheEntry.nextNonce++ tw.nextNonceCache.Add(signer, cacheEntry) diff --git a/internal/persistence/postgres/transactions.go b/internal/persistence/postgres/transactions.go index a1aac9da..e797bfec 100644 --- a/internal/persistence/postgres/transactions.go +++ b/internal/persistence/postgres/transactions.go @@ -141,6 +141,7 @@ func (p *sqlPersistence) ListTransactionsByCreateTime(ctx context.Context, after } func (p *sqlPersistence) ListTransactionsByNonce(ctx context.Context, signer string, after *fftypes.FFBigInt, limit int, dir txhandler.SortDirection) ([]*apitypes.ManagedTX, error) { + //nolint:gosec // Safe conversion as limit is always positive fb := persistence.TransactionFilters.NewFilterLimit(ctx, uint64(limit)) conditions := []ffapi.Filter{ fb.Eq("from", signer), diff --git a/internal/persistence/postgres/txhistory.go b/internal/persistence/postgres/txhistory.go index 73904466..a1ed3ddc 100644 --- a/internal/persistence/postgres/txhistory.go +++ b/internal/persistence/postgres/txhistory.go @@ -153,7 +153,9 @@ func (p *sqlPersistence) buildHistorySummary(ctx context.Context, txID string, b var lastRecordSameSubStatus *apitypes.TXHistoryRecord for { filter := persistence.TXHistoryFilters. + //nolint:gosec // Safe conversion as pageSize is always positive NewFilterLimit(ctx, uint64(pageSize)).Eq("transaction", txID). + //nolint:gosec // Safe conversion as skip is always positive Skip(uint64(skip)) page, _, err := p.txHistory.GetMany(ctx, filter) if err != nil { diff --git a/internal/tmconfig/tmconfig.go b/internal/tmconfig/tmconfig.go index cf877701..128a35f7 100644 --- a/internal/tmconfig/tmconfig.go +++ b/internal/tmconfig/tmconfig.go @@ -56,8 +56,10 @@ var ( APIMaxRequestTimeout = ffc("api.maxRequestTimeout") APIPassthroughHeaders = ffc("api.passthroughHeaders") APISimpleQuery = ffc("api.simpleQuery") - MetricsEnabled = ffc("metrics.enabled") - MetricsPath = ffc("metrics.path") + DeprecatedMetricsEnabled = ffc("metrics.enabled") + DeprecatedMetricsPath = ffc("metrics.path") + MonitoringEnabled = ffc("monitoring.enabled") + MonitoringMetricsPath = ffc("monitoring.metricsPath") TransactionsHandlerName = ffc("transactions.handler.name") TransactionsMaxHistoryCount = ffc("transactions.maxHistoryCount") TransactionsNonceStateTimeout = ffc("transactions.nonceStateTimeout") @@ -87,7 +89,7 @@ var TransactionHandlerBaseConfig config.Section var WebhookPrefix config.Section -var MetricsConfig config.Section +var MonitoringConfig config.Section func setDefaults() { viper.SetDefault(string(TransactionsMaxHistoryCount), 50) @@ -121,8 +123,11 @@ func setDefaults() { viper.SetDefault(string(EventStreamsRetryInitDelay), "250ms") viper.SetDefault(string(EventStreamsRetryMaxDelay), "30s") viper.SetDefault(string(EventStreamsRetryFactor), 2.0) - viper.SetDefault(string(MetricsEnabled), false) - viper.SetDefault(string(MetricsPath), "/metrics") + viper.SetDefault(string(DeprecatedMetricsEnabled), false) + viper.SetDefault(string(DeprecatedMetricsPath), "/metrics") + + viper.SetDefault(string(MonitoringEnabled), false) + viper.SetDefault(string(MonitoringMetricsPath), "/metrics") viper.SetDefault(string(APIPassthroughHeaders), []string{}) viper.SetDefault(string(DeprecatedPolicyEngineName), "simple") @@ -159,6 +164,13 @@ func Reset() { TransactionHandlerBaseConfig = config.RootSection("transactions.handler") // Transaction handler must be registered outside of this package - MetricsConfig = config.RootSection("metrics") - httpserver.InitHTTPConfig(MetricsConfig, 6000) + MonitoringConfig = config.RootSection("monitoring") + MetricsConfig := config.RootSection("metrics") + if MetricsConfig.GetBool("enabled") && !MonitoringConfig.GetBool("enabled") { + // only use the deprecated metrics config if the monitoring config is not enabled + httpserver.InitHTTPConfig(MetricsConfig, 6000) + } else { + httpserver.InitHTTPConfig(MonitoringConfig, 6000) + } + } diff --git a/internal/tmmsgs/en_config_descriptions.go b/internal/tmmsgs/en_config_descriptions.go index 14422fc8..1920c2a9 100644 --- a/internal/tmmsgs/en_config_descriptions.go +++ b/internal/tmmsgs/en_config_descriptions.go @@ -104,14 +104,16 @@ var ( ConfigWebhooksURL = ffc("config.webhooks.url", "Unused (overridden by the WebHook configuration of an individual event stream)", i18n.IgnoredType) ConfigWebhooksProxyURL = ffc("config.webhooks.proxy.url", "Optional HTTP proxy to use when invoking WebHooks", i18n.StringType) - ConfigMetricsAddress = ffc("config.metrics.address", "The IP address on which the metrics HTTP API should listen", i18n.IntType) - ConfigMetricsEnabled = ffc("config.metrics.enabled", "Enables the metrics API", i18n.BooleanType) - ConfigMetricsPath = ffc("config.metrics.path", "The path from which to serve the Prometheus metrics", i18n.StringType) - ConfigMetricsPort = ffc("config.metrics.port", "The port on which the metrics HTTP API should listen", i18n.IntType) - ConfigMetricsPublicURL = ffc("config.metrics.publicURL", "The fully qualified public URL for the metrics API. This is used for building URLs in HTTP responses and in OpenAPI Spec generation", "URL "+i18n.StringType) - ConfigMetricsReadTimeout = ffc("config.metrics.readTimeout", "The maximum time to wait when reading from an HTTP connection", i18n.TimeDurationType) - ConfigMetricsWriteTimeout = ffc("config.metrics.writeTimeout", "The maximum time to wait when writing to an HTTP connection", i18n.TimeDurationType) - ConfigMetricsShutdownTimeout = ffc("config.metrics.shutdownTimeout", "The maximum amount of time to wait for any open HTTP requests to finish before shutting down the HTTP server", i18n.TimeDurationType) + ConfigMetricsAddress = ffc("config.metrics.address", "The IP address on which the metrics HTTP API should listen", i18n.IntType) + DeprecatedConfigMetricsEnabled = ffc("config.metrics.enabled", "Deprecated: Please use 'monitoring.enabled' instead", i18n.BooleanType) + DeprecatedConfigMetricsPath = ffc("config.monitoring.enabled", "Deprecated: Please use 'monitoring.metricsPath' instead", i18n.StringType) + ConfigMonitoringEnabled = ffc("config.monitoring.metricsPath", "Enables the monitoring APIs", i18n.BooleanType) + ConfigMonitoringMetricsPath = ffc("config.metrics.path", "The path from which to serve the Prometheus metrics", i18n.StringType) + ConfigMetricsPort = ffc("config.metrics.port", "The port on which the metrics HTTP API should listen", i18n.IntType) + ConfigMetricsPublicURL = ffc("config.metrics.publicURL", "The fully qualified public URL for the metrics API. This is used for building URLs in HTTP responses and in OpenAPI Spec generation", "URL "+i18n.StringType) + ConfigMetricsReadTimeout = ffc("config.metrics.readTimeout", "The maximum time to wait when reading from an HTTP connection", i18n.TimeDurationType) + ConfigMetricsWriteTimeout = ffc("config.metrics.writeTimeout", "The maximum time to wait when writing to an HTTP connection", i18n.TimeDurationType) + ConfigMetricsShutdownTimeout = ffc("config.metrics.shutdownTimeout", "The maximum amount of time to wait for any open HTTP requests to finish before shutting down the HTTP server", i18n.TimeDurationType) ConfigDatabasePostgresMaxConnIdleTime = ffc("config.persistence.postgres.maxConnIdleTime", "The maximum amount of time a database connection can be idle", i18n.TimeDurationType) ConfigDatabasePostgresMaxConnLifetime = ffc("config.persistence.postgres.maxConnLifetime", "The maximum amount of time to keep a database connection open", i18n.TimeDurationType) diff --git a/pkg/apitypes/api_types.go b/pkg/apitypes/api_types.go index d2f4b44a..76257579 100644 --- a/pkg/apitypes/api_types.go +++ b/pkg/apitypes/api_types.go @@ -263,95 +263,96 @@ type LiveGasPrice struct { } // CheckUpdateString helper merges supplied configuration, with a base, and applies a default if unset -func CheckUpdateString(changed bool, merged **string, old *string, new *string, defValue string) bool { - if new != nil { - *merged = new +func CheckUpdateString(changed bool, merged **string, oldValue *string, newValue *string, defValue string) bool { + if newValue != nil { + *merged = newValue } else { - *merged = old + *merged = oldValue } if *merged == nil { v := defValue *merged = &v return true } - return changed || old == nil || *old != **merged + return changed || oldValue == nil || *oldValue != **merged } // CheckUpdateBool helper merges supplied configuration, with a base, and applies a default if unset -func CheckUpdateBool(changed bool, merged **bool, old *bool, new *bool, defValue bool) bool { - if new != nil { - *merged = new +func CheckUpdateBool(changed bool, merged **bool, oldValue *bool, newValue *bool, defValue bool) bool { + if newValue != nil { + *merged = newValue } else { - *merged = old + *merged = oldValue } if *merged == nil { v := defValue *merged = &v return true } - return changed || old == nil || *old != **merged + return changed || oldValue == nil || *oldValue != **merged } // CheckUpdateUint64 helper merges supplied configuration, with a base, and applies a default if unset -func CheckUpdateUint64(changed bool, merged **uint64, old *uint64, new *uint64, defValue int64) bool { - if new != nil { - *merged = new +func CheckUpdateUint64(changed bool, merged **uint64, oldValue *uint64, newValue *uint64, defValue int64) bool { + if newValue != nil { + *merged = newValue } else { - *merged = old + *merged = oldValue } if *merged == nil { + //nolint:gosec v := uint64(defValue) *merged = &v return true } - return changed || old == nil || *old != **merged + return changed || oldValue == nil || *oldValue != **merged } // CheckUpdateDuration helper merges supplied configuration, with a base, and applies a default if unset -func CheckUpdateDuration(changed bool, merged **fftypes.FFDuration, old *fftypes.FFDuration, new *fftypes.FFDuration, defValue fftypes.FFDuration) bool { - if new != nil { - *merged = new +func CheckUpdateDuration(changed bool, merged **fftypes.FFDuration, oldValue *fftypes.FFDuration, newValue *fftypes.FFDuration, defValue fftypes.FFDuration) bool { + if newValue != nil { + *merged = newValue } else { - *merged = old + *merged = oldValue } if *merged == nil { v := defValue *merged = &v return true } - return changed || old == nil || *old != **merged + return changed || oldValue == nil || *oldValue != **merged } // CheckUpdateEnum helper merges supplied configuration, with a base, and applies a default if unset -func CheckUpdateEnum(changed bool, merged **fftypes.FFEnum, old *fftypes.FFEnum, new *fftypes.FFEnum, defValue fftypes.FFEnum) bool { - if new != nil { - *merged = new +func CheckUpdateEnum(changed bool, merged **fftypes.FFEnum, oldValue *fftypes.FFEnum, newValue *fftypes.FFEnum, defValue fftypes.FFEnum) bool { + if newValue != nil { + *merged = newValue } else { - *merged = old + *merged = oldValue } if *merged == nil { v := defValue *merged = &v return true } - return changed || old == nil || *old != **merged + return changed || oldValue == nil || *oldValue != **merged } // CheckUpdateStringMap helper merges supplied configuration, with a base, and applies a default if unset -func CheckUpdateStringMap(changed bool, merged *map[string]string, old map[string]string, new map[string]string) bool { - if new != nil { - *merged = new - changed = changed || (old == nil) +func CheckUpdateStringMap(changed bool, merged *map[string]string, oldValue map[string]string, newValue map[string]string) bool { + if newValue != nil { + *merged = newValue + changed = changed || (oldValue == nil) } else { - *merged = old + *merged = oldValue return false // new was nil, we cannot have changed } if changed { return true } // We need to compare otherwise - jsonOld, _ := json.Marshal(old) - jsonNew, _ := json.Marshal(new) + jsonOld, _ := json.Marshal(oldValue) + jsonNew, _ := json.Marshal(newValue) return !bytes.Equal(jsonOld, jsonNew) } diff --git a/pkg/fftm/api.go b/pkg/fftm/api.go index c686d459..33e6ba32 100644 --- a/pkg/fftm/api.go +++ b/pkg/fftm/api.go @@ -59,17 +59,30 @@ func (m *manager) router(metricsEnabled bool) *mux.Router { mux.HandleFunc("/ws", m.wsServer.Handler) - mux.NotFoundHandler = hf.APIWrapper(func(res http.ResponseWriter, req *http.Request) (status int, err error) { + mux.NotFoundHandler = hf.APIWrapper(func(_ http.ResponseWriter, req *http.Request) (status int, err error) { return 404, i18n.NewError(req.Context(), i18n.Msg404NotFound) }) return mux } -func (m *manager) createMetricsMuxRouter() *mux.Router { +func (m *manager) createMonitoringMuxRouter() *mux.Router { r := mux.NewRouter() - r.Path(config.GetString(tmconfig.MetricsPath)).Handler(m.metricsManager.HTTPHandler()) - + if config.GetBool(tmconfig.DeprecatedMetricsEnabled) { + r.Path(config.GetString(tmconfig.DeprecatedMetricsPath)).Handler(m.metricsManager.HTTPHandler()) + } else { + r.Path(config.GetString(tmconfig.MonitoringMetricsPath)).Handler(m.metricsManager.HTTPHandler()) + } + hf := ffapi.HandlerFactory{ + DefaultRequestTimeout: config.GetDuration(tmconfig.APIDefaultRequestTimeout), + MaxTimeout: config.GetDuration(tmconfig.APIMaxRequestTimeout), + } + for _, route := range m.monitoringRoutes() { + r.Path(route.Path).Methods(route.Method).Handler(hf.RouteHandler(route)) + } + r.NotFoundHandler = hf.APIWrapper(func(_ http.ResponseWriter, req *http.Request) (status int, err error) { + return 404, i18n.NewError(req.Context(), i18n.Msg404NotFound) + }) return r } diff --git a/pkg/fftm/manager.go b/pkg/fftm/manager.go index 1ea07ce6..8a7ecbfc 100644 --- a/pkg/fftm/manager.go +++ b/pkg/fftm/manager.go @@ -59,16 +59,16 @@ type manager struct { connector ffcapi.API toolkit *txhandler.Toolkit - mux sync.Mutex - eventStreams map[fftypes.UUID]events.Stream - streamsByName map[string]*fftypes.UUID - blockListenerDone chan struct{} - txHandlerDone <-chan struct{} - started bool - apiServerDone chan error - metricsServerDone chan error - metricsEnabled bool - metricsManager metrics.Metrics + mux sync.Mutex + eventStreams map[fftypes.UUID]events.Stream + streamsByName map[string]*fftypes.UUID + blockListenerDone chan struct{} + txHandlerDone <-chan struct{} + started bool + apiServerDone chan error + monitoringServerDone chan error + monitoringEnabled bool + metricsManager metrics.Metrics } func InitConfig() { @@ -90,13 +90,13 @@ func NewManager(ctx context.Context, connector ffcapi.API) (Manager, error) { func newManager(ctx context.Context, connector ffcapi.API) *manager { m := &manager{ - connector: connector, - apiServerDone: make(chan error), - metricsServerDone: make(chan error), - metricsEnabled: config.GetBool(tmconfig.MetricsEnabled), - eventStreams: make(map[fftypes.UUID]events.Stream), - streamsByName: make(map[string]*fftypes.UUID), - metricsManager: metrics.NewMetricsManager(ctx), + connector: connector, + apiServerDone: make(chan error), + monitoringServerDone: make(chan error), + monitoringEnabled: config.GetBool(tmconfig.DeprecatedMetricsEnabled) || config.GetBool(tmconfig.MonitoringEnabled), + eventStreams: make(map[fftypes.UUID]events.Stream), + streamsByName: make(map[string]*fftypes.UUID), + metricsManager: metrics.NewMetricsManager(ctx), } m.toolkit = &txhandler.Toolkit{ Connector: m.connector, @@ -109,7 +109,7 @@ func newManager(ctx context.Context, connector ffcapi.API) *manager { func (m *manager) initServices(ctx context.Context) (err error) { m.confirmations = confirmations.NewBlockConfirmationManager(ctx, m.connector, "receipts", m.metricsManager) m.wsServer = ws.NewWebSocketServer(ctx) - m.apiServer, err = httpserver.NewHTTPServer(ctx, "api", m.router(m.metricsEnabled), m.apiServerDone, tmconfig.APIConfig, tmconfig.CorsConfig) + m.apiServer, err = httpserver.NewHTTPServer(ctx, "api", m.router(m.monitoringEnabled), m.apiServerDone, tmconfig.APIConfig, tmconfig.CorsConfig) if err != nil { return err } @@ -132,8 +132,8 @@ func (m *manager) initServices(ctx context.Context) (err error) { // metrics service must be initialized after transaction handler // in case the transaction handler has logic in the Init function // to add more metrics - if m.metricsEnabled { - m.metricsServer, err = httpserver.NewHTTPServer(ctx, "metrics", m.createMetricsMuxRouter(), m.metricsServerDone, tmconfig.MetricsConfig, tmconfig.CorsConfig) + if m.monitoringEnabled { + m.metricsServer, err = httpserver.NewHTTPServer(ctx, "metrics", m.createMonitoringMuxRouter(), m.monitoringServerDone, tmconfig.MonitoringConfig, tmconfig.CorsConfig) if err != nil { return err } @@ -180,7 +180,7 @@ func (m *manager) Start() error { } go m.runAPIServer() - if m.metricsEnabled { + if m.monitoringEnabled { go m.runMetricsServer() } go m.confirmations.Start() @@ -198,8 +198,8 @@ func (m *manager) Close() { if m.started { m.started = false <-m.apiServerDone - if m.metricsEnabled { - <-m.metricsServerDone + if m.monitoringEnabled { + <-m.monitoringServerDone } <-m.txHandlerDone <-m.blockListenerDone diff --git a/pkg/fftm/manager_test.go b/pkg/fftm/manager_test.go index bddffbc0..d349abcf 100644 --- a/pkg/fftm/manager_test.go +++ b/pkg/fftm/manager_test.go @@ -55,7 +55,7 @@ func testManagerCommonInit(t *testing.T, withMetrics bool) string { tmconfig.TransactionHandlerBaseConfig.SubSection("simple").SubSection(simple.GasOracleConfig).Set(simple.GasOracleMode, simple.GasOracleModeDisabled) if withMetrics { - tmconfig.MetricsConfig.Set("enabled", true) + tmconfig.MonitoringConfig.Set("enabled", true) } ln, err := net.Listen("tcp", "127.0.0.1:0") @@ -66,8 +66,8 @@ func testManagerCommonInit(t *testing.T, withMetrics bool) string { tmconfig.APIConfig.Set(httpserver.HTTPConfAddress, "127.0.0.1") if withMetrics { - tmconfig.MetricsConfig.Set(httpserver.HTTPConfPort, 6010) - tmconfig.MetricsConfig.Set(httpserver.HTTPConfAddress, "127.0.0.1") + tmconfig.MonitoringConfig.Set(httpserver.HTTPConfPort, 6010) + tmconfig.MonitoringConfig.Set(httpserver.HTTPConfAddress, "127.0.0.1") } // config.Set(tmconfig.PolicyLoopInterval, "1ns") //TODO: fix this @@ -308,7 +308,7 @@ func TestNewManagerMetricsOffByDefault(t *testing.T) { tmconfig.Reset() m := newManager(context.Background(), nil) - assert.False(t, m.metricsEnabled) + assert.False(t, m.monitoringEnabled) } func TestNewManagerWithMetrics(t *testing.T) { @@ -317,7 +317,7 @@ func TestNewManagerWithMetrics(t *testing.T) { defer close() _ = m.Start() - assert.True(t, m.metricsEnabled) + assert.True(t, m.monitoringEnabled) } func TestNewManagerWithMetricsBadConfig(t *testing.T) { @@ -325,8 +325,8 @@ func TestNewManagerWithMetricsBadConfig(t *testing.T) { tmconfig.Reset() viper.SetDefault(string(tmconfig.TransactionsHandlerName), "simple") - tmconfig.MetricsConfig.Set("enabled", true) - tmconfig.MetricsConfig.Set(httpserver.HTTPConfAddress, "::::") + tmconfig.MonitoringConfig.Set("enabled", true) + tmconfig.MonitoringConfig.Set(httpserver.HTTPConfAddress, "::::") dir := t.TempDir() config.Set(tmconfig.PersistenceLevelDBPath, dir) diff --git a/pkg/fftm/routes.go b/pkg/fftm/routes.go index d6472040..fd842297 100644 --- a/pkg/fftm/routes.go +++ b/pkg/fftm/routes.go @@ -28,11 +28,11 @@ func (m *manager) routes() []*ffapi.Route { getEventStreamListener(m), getEventStreamListeners(m), getEventStreams(m), - getLiveStatus(m), getStatus(m), getSubscription(m), getSubscriptions(m), - getReadyStatus(m), + getLiveStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes + getReadyStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes getTransaction(m), getTransactionConfirmations(m), getTransactionHistory(m), @@ -55,3 +55,10 @@ func (m *manager) routes() []*ffapi.Route { postTransactionResume(m), } } + +func (m *manager) monitoringRoutes() []*ffapi.Route { + return []*ffapi.Route{ + getLiveStatus(m), + getReadyStatus(m), + } +} From 841ed80db43420eae6d028a282de4de43db94add Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 19 Feb 2025 13:59:22 +0000 Subject: [PATCH 2/9] bump to 1.23 Signed-off-by: Chengxuan Xing --- .github/workflows/go.yml | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index b466cdf2..0dbc7dc7 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,7 +10,7 @@ on: jobs: build: runs-on: ubuntu-latest - container: golang:1.22-bullseye + container: golang:1.23-bullseye defaults: run: shell: bash # needed for codecov diff --git a/go.mod b/go.mod index e7b19c12..3289c1e6 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/hyperledger/firefly-transaction-manager -go 1.22 +go 1.23 require ( github.com/DATA-DOG/go-sqlmock v1.5.2 From 186d052355938340c47bdede36f8248e1ee80935 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 19 Feb 2025 14:08:44 +0000 Subject: [PATCH 3/9] update doc Signed-off-by: Chengxuan Xing --- config.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/config.md b/config.md index a2391391..f0c8cfe1 100644 --- a/config.md +++ b/config.md @@ -174,28 +174,35 @@ |Key|Description|Type|Default Value| |---|-----------|----|-------------| -|address|The IP address on which the metrics HTTP API should listen|`int`|`127.0.0.1` -|enabled|Enables the metrics API|`boolean`|`false` +|enabled|Deprecated: Please use 'monitoring.enabled' instead|`boolean`|`false` |path|The path from which to serve the Prometheus metrics|`string`|`/metrics` -|port|The port on which the metrics HTTP API should listen|`int`|`6000` -|publicURL|The fully qualified public URL for the metrics API. This is used for building URLs in HTTP responses and in OpenAPI Spec generation|URL `string`|`` -|readTimeout|The maximum time to wait when reading from an HTTP connection|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` -|shutdownTimeout|The maximum amount of time to wait for any open HTTP requests to finish before shutting down the HTTP server|[`time.Duration`](https://pkg.go.dev/time#Duration)|`10s` -|writeTimeout|The maximum time to wait when writing to an HTTP connection|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` -## metrics.auth +## monitoring + +|Key|Description|Type|Default Value| +|---|-----------|----|-------------| +|address|Listener address|`int`|`127.0.0.1` +|enabled|Deprecated: Please use 'monitoring.metricsPath' instead|`string`|`false` +|metricsPath|Enables the monitoring APIs|`boolean`|`/metrics` +|port|Listener port|`int`|`6000` +|publicURL|Externally available URL for the HTTP endpoint|`string`|`` +|readTimeout|HTTP server read timeout|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` +|shutdownTimeout|HTTP server shutdown timeout|[`time.Duration`](https://pkg.go.dev/time#Duration)|`10s` +|writeTimeout|HTTP server write timeout|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` + +## monitoring.auth |Key|Description|Type|Default Value| |---|-----------|----|-------------| |type|The auth plugin to use for server side authentication of requests|`string`|`` -## metrics.auth.basic +## monitoring.auth.basic |Key|Description|Type|Default Value| |---|-----------|----|-------------| |passwordfile|The path to a .htpasswd file to use for authenticating requests. Passwords should be hashed with bcrypt.|`string`|`` -## metrics.tls +## monitoring.tls |Key|Description|Type|Default Value| |---|-----------|----|-------------| From 91933303d54ddb2d889b95f6ad35fad1482fec4b Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 19 Feb 2025 14:15:53 +0000 Subject: [PATCH 4/9] fixing config Signed-off-by: Chengxuan Xing --- config.md | 33 +++++++++++++++++++++ internal/tmconfig/tmconfig.go | 13 ++++----- pkg/fftm/api.go | 4 +-- pkg/fftm/manager.go | 54 ++++++++++++++++++++--------------- 4 files changed, 71 insertions(+), 33 deletions(-) diff --git a/config.md b/config.md index f0c8cfe1..3e22dcaa 100644 --- a/config.md +++ b/config.md @@ -174,8 +174,41 @@ |Key|Description|Type|Default Value| |---|-----------|----|-------------| +|address|The IP address on which the metrics HTTP API should listen|`int`|`127.0.0.1` |enabled|Deprecated: Please use 'monitoring.enabled' instead|`boolean`|`false` |path|The path from which to serve the Prometheus metrics|`string`|`/metrics` +|port|The port on which the metrics HTTP API should listen|`int`|`6000` +|publicURL|The fully qualified public URL for the metrics API. This is used for building URLs in HTTP responses and in OpenAPI Spec generation|URL `string`|`` +|readTimeout|The maximum time to wait when reading from an HTTP connection|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` +|shutdownTimeout|The maximum amount of time to wait for any open HTTP requests to finish before shutting down the HTTP server|[`time.Duration`](https://pkg.go.dev/time#Duration)|`10s` +|writeTimeout|The maximum time to wait when writing to an HTTP connection|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` + +## metrics.auth + +|Key|Description|Type|Default Value| +|---|-----------|----|-------------| +|type|The auth plugin to use for server side authentication of requests|`string`|`` + +## metrics.auth.basic + +|Key|Description|Type|Default Value| +|---|-----------|----|-------------| +|passwordfile|The path to a .htpasswd file to use for authenticating requests. Passwords should be hashed with bcrypt.|`string`|`` + +## metrics.tls + +|Key|Description|Type|Default Value| +|---|-----------|----|-------------| +|ca|The TLS certificate authority in PEM format (this option is ignored if caFile is also set)|`string`|`` +|caFile|The path to the CA file for TLS on this API|`string`|`` +|cert|The TLS certificate in PEM format (this option is ignored if certFile is also set)|`string`|`` +|certFile|The path to the certificate file for TLS on this API|`string`|`` +|clientAuth|Enables or disables client auth for TLS on this API|`string`|`` +|enabled|Enables or disables TLS on this API|`boolean`|`false` +|insecureSkipHostVerify|When to true in unit test development environments to disable TLS verification. Use with extreme caution|`boolean`|`` +|key|The TLS certificate key in PEM format (this option is ignored if keyFile is also set)|`string`|`` +|keyFile|The path to the private key file for TLS on this API|`string`|`` +|requiredDNAttributes|A set of required subject DN attributes. Each entry is a regular expression, and the subject certificate must have a matching attribute of the specified type (CN, C, O, OU, ST, L, STREET, POSTALCODE, SERIALNUMBER are valid attributes)|`map[string]string`|`` ## monitoring diff --git a/internal/tmconfig/tmconfig.go b/internal/tmconfig/tmconfig.go index 128a35f7..0fceb254 100644 --- a/internal/tmconfig/tmconfig.go +++ b/internal/tmconfig/tmconfig.go @@ -91,6 +91,8 @@ var WebhookPrefix config.Section var MonitoringConfig config.Section +var DeprecatedMetricsConfig config.Section + func setDefaults() { viper.SetDefault(string(TransactionsMaxHistoryCount), 50) viper.SetDefault(string(ConfirmationsRequired), 20) @@ -165,12 +167,7 @@ func Reset() { TransactionHandlerBaseConfig = config.RootSection("transactions.handler") // Transaction handler must be registered outside of this package MonitoringConfig = config.RootSection("monitoring") - MetricsConfig := config.RootSection("metrics") - if MetricsConfig.GetBool("enabled") && !MonitoringConfig.GetBool("enabled") { - // only use the deprecated metrics config if the monitoring config is not enabled - httpserver.InitHTTPConfig(MetricsConfig, 6000) - } else { - httpserver.InitHTTPConfig(MonitoringConfig, 6000) - } - + DeprecatedMetricsConfig = config.RootSection("metrics") + httpserver.InitHTTPConfig(DeprecatedMetricsConfig, 6000) + httpserver.InitHTTPConfig(MonitoringConfig, 6000) } diff --git a/pkg/fftm/api.go b/pkg/fftm/api.go index 33e6ba32..22a46106 100644 --- a/pkg/fftm/api.go +++ b/pkg/fftm/api.go @@ -90,6 +90,6 @@ func (m *manager) runAPIServer() { m.apiServer.ServeHTTP(m.ctx) } -func (m *manager) runMetricsServer() { - m.metricsServer.ServeHTTP(m.ctx) +func (m *manager) runMonitoringServer() { + m.monitoringServer.ServeHTTP(m.ctx) } diff --git a/pkg/fftm/manager.go b/pkg/fftm/manager.go index 8a7ecbfc..2f12df32 100644 --- a/pkg/fftm/manager.go +++ b/pkg/fftm/manager.go @@ -51,7 +51,7 @@ type manager struct { confirmations confirmations.Manager txHandler txhandler.TransactionHandler apiServer httpserver.HTTPServer - metricsServer httpserver.HTTPServer + monitoringServer httpserver.HTTPServer wsServer ws.WebSocketServer persistence persistence.Persistence richQueryEnabled bool @@ -59,16 +59,17 @@ type manager struct { connector ffcapi.API toolkit *txhandler.Toolkit - mux sync.Mutex - eventStreams map[fftypes.UUID]events.Stream - streamsByName map[string]*fftypes.UUID - blockListenerDone chan struct{} - txHandlerDone <-chan struct{} - started bool - apiServerDone chan error - monitoringServerDone chan error - monitoringEnabled bool - metricsManager metrics.Metrics + mux sync.Mutex + eventStreams map[fftypes.UUID]events.Stream + streamsByName map[string]*fftypes.UUID + blockListenerDone chan struct{} + txHandlerDone <-chan struct{} + started bool + apiServerDone chan error + monitoringServerDone chan error + monitoringEnabled bool + deprecatedMetricsEnabled bool + metricsManager metrics.Metrics } func InitConfig() { @@ -90,13 +91,14 @@ func NewManager(ctx context.Context, connector ffcapi.API) (Manager, error) { func newManager(ctx context.Context, connector ffcapi.API) *manager { m := &manager{ - connector: connector, - apiServerDone: make(chan error), - monitoringServerDone: make(chan error), - monitoringEnabled: config.GetBool(tmconfig.DeprecatedMetricsEnabled) || config.GetBool(tmconfig.MonitoringEnabled), - eventStreams: make(map[fftypes.UUID]events.Stream), - streamsByName: make(map[string]*fftypes.UUID), - metricsManager: metrics.NewMetricsManager(ctx), + connector: connector, + apiServerDone: make(chan error), + monitoringServerDone: make(chan error), + deprecatedMetricsEnabled: config.GetBool(tmconfig.DeprecatedMetricsEnabled), + monitoringEnabled: config.GetBool(tmconfig.MonitoringEnabled), + eventStreams: make(map[fftypes.UUID]events.Stream), + streamsByName: make(map[string]*fftypes.UUID), + metricsManager: metrics.NewMetricsManager(ctx), } m.toolkit = &txhandler.Toolkit{ Connector: m.connector, @@ -109,7 +111,7 @@ func newManager(ctx context.Context, connector ffcapi.API) *manager { func (m *manager) initServices(ctx context.Context) (err error) { m.confirmations = confirmations.NewBlockConfirmationManager(ctx, m.connector, "receipts", m.metricsManager) m.wsServer = ws.NewWebSocketServer(ctx) - m.apiServer, err = httpserver.NewHTTPServer(ctx, "api", m.router(m.monitoringEnabled), m.apiServerDone, tmconfig.APIConfig, tmconfig.CorsConfig) + m.apiServer, err = httpserver.NewHTTPServer(ctx, "api", m.router(m.monitoringEnabled || m.deprecatedMetricsEnabled), m.apiServerDone, tmconfig.APIConfig, tmconfig.CorsConfig) if err != nil { return err } @@ -133,10 +135,16 @@ func (m *manager) initServices(ctx context.Context) (err error) { // in case the transaction handler has logic in the Init function // to add more metrics if m.monitoringEnabled { - m.metricsServer, err = httpserver.NewHTTPServer(ctx, "metrics", m.createMonitoringMuxRouter(), m.monitoringServerDone, tmconfig.MonitoringConfig, tmconfig.CorsConfig) + m.monitoringServer, err = httpserver.NewHTTPServer(ctx, "monitoring", m.createMonitoringMuxRouter(), m.monitoringServerDone, tmconfig.MonitoringConfig, tmconfig.CorsConfig) if err != nil { return err } + } else if m.deprecatedMetricsEnabled { + m.monitoringServer, err = httpserver.NewHTTPServer(ctx, "metrics", m.createMonitoringMuxRouter(), m.monitoringServerDone, tmconfig.DeprecatedMetricsConfig, tmconfig.CorsConfig) + if err != nil { + return err + } + } return nil } @@ -180,8 +188,8 @@ func (m *manager) Start() error { } go m.runAPIServer() - if m.monitoringEnabled { - go m.runMetricsServer() + if m.monitoringEnabled || m.deprecatedMetricsEnabled { + go m.runMonitoringServer() } go m.confirmations.Start() @@ -198,7 +206,7 @@ func (m *manager) Close() { if m.started { m.started = false <-m.apiServerDone - if m.monitoringEnabled { + if m.monitoringEnabled || m.deprecatedMetricsEnabled { <-m.monitoringServerDone } <-m.txHandlerDone From ce4d18e7cef315554c79f90b3e8987cc53d3ddf0 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 19 Feb 2025 14:17:39 +0000 Subject: [PATCH 5/9] fixing documentation Signed-off-by: Chengxuan Xing --- config.md | 6 +++--- internal/tmmsgs/en_config_descriptions.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config.md b/config.md index 3e22dcaa..e7b644a8 100644 --- a/config.md +++ b/config.md @@ -176,7 +176,7 @@ |---|-----------|----|-------------| |address|The IP address on which the metrics HTTP API should listen|`int`|`127.0.0.1` |enabled|Deprecated: Please use 'monitoring.enabled' instead|`boolean`|`false` -|path|The path from which to serve the Prometheus metrics|`string`|`/metrics` +|path|Deprecated: Please use 'monitoring.metricsPath' instead|`string`|`/metrics` |port|The port on which the metrics HTTP API should listen|`int`|`6000` |publicURL|The fully qualified public URL for the metrics API. This is used for building URLs in HTTP responses and in OpenAPI Spec generation|URL `string`|`` |readTimeout|The maximum time to wait when reading from an HTTP connection|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` @@ -215,8 +215,8 @@ |Key|Description|Type|Default Value| |---|-----------|----|-------------| |address|Listener address|`int`|`127.0.0.1` -|enabled|Deprecated: Please use 'monitoring.metricsPath' instead|`string`|`false` -|metricsPath|Enables the monitoring APIs|`boolean`|`/metrics` +|enabled|Enables the monitoring APIs|`boolean`|`false` +|metricsPath|The path from which to serve the Prometheus metrics|`string`|`/metrics` |port|Listener port|`int`|`6000` |publicURL|Externally available URL for the HTTP endpoint|`string`|`` |readTimeout|HTTP server read timeout|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s` diff --git a/internal/tmmsgs/en_config_descriptions.go b/internal/tmmsgs/en_config_descriptions.go index 1920c2a9..d68d4e38 100644 --- a/internal/tmmsgs/en_config_descriptions.go +++ b/internal/tmmsgs/en_config_descriptions.go @@ -106,9 +106,9 @@ var ( ConfigMetricsAddress = ffc("config.metrics.address", "The IP address on which the metrics HTTP API should listen", i18n.IntType) DeprecatedConfigMetricsEnabled = ffc("config.metrics.enabled", "Deprecated: Please use 'monitoring.enabled' instead", i18n.BooleanType) - DeprecatedConfigMetricsPath = ffc("config.monitoring.enabled", "Deprecated: Please use 'monitoring.metricsPath' instead", i18n.StringType) - ConfigMonitoringEnabled = ffc("config.monitoring.metricsPath", "Enables the monitoring APIs", i18n.BooleanType) - ConfigMonitoringMetricsPath = ffc("config.metrics.path", "The path from which to serve the Prometheus metrics", i18n.StringType) + DeprecatedConfigMetricsPath = ffc("config.metrics.path", "Deprecated: Please use 'monitoring.metricsPath' instead", i18n.StringType) + ConfigMonitoringEnabled = ffc("config.monitoring.enabled", "Enables the monitoring APIs", i18n.BooleanType) + ConfigMonitoringMetricsPath = ffc("config.monitoring.metricsPath", "The path from which to serve the Prometheus metrics", i18n.StringType) ConfigMetricsPort = ffc("config.metrics.port", "The port on which the metrics HTTP API should listen", i18n.IntType) ConfigMetricsPublicURL = ffc("config.metrics.publicURL", "The fully qualified public URL for the metrics API. This is used for building URLs in HTTP responses and in OpenAPI Spec generation", "URL "+i18n.StringType) ConfigMetricsReadTimeout = ffc("config.metrics.readTimeout", "The maximum time to wait when reading from an HTTP connection", i18n.TimeDurationType) From ef44d517b899f98a89b88a96e4f5c69b62879ddc Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 19 Feb 2025 14:21:29 +0000 Subject: [PATCH 6/9] copyright Signed-off-by: Chengxuan Xing --- cmd/client_eventstreams_delete.go | 2 +- cmd/client_eventstreams_list.go | 2 +- cmd/client_listeners_delete.go | 2 +- cmd/client_listeners_list.go | 2 +- cmd/migrate.go | 2 +- internal/apiclient/eventstreams.go | 2 +- internal/confirmations/confirmations.go | 2 +- internal/confirmations/confirmed_block_listener.go | 2 +- internal/events/eventstream.go | 2 +- internal/metrics/metrics.go | 2 +- internal/persistence/leveldb/leveldb_persistence.go | 2 +- internal/persistence/postgres/sqlpersistence.go | 2 +- internal/persistence/postgres/transaction_writer.go | 2 +- internal/persistence/postgres/transactions.go | 2 +- internal/persistence/postgres/txhistory.go | 2 +- internal/tmconfig/tmconfig.go | 2 +- internal/tmmsgs/en_config_descriptions.go | 2 +- pkg/apitypes/api_types.go | 2 +- pkg/fftm/api.go | 2 +- pkg/fftm/manager.go | 2 +- pkg/fftm/manager_test.go | 2 +- pkg/fftm/routes.go | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/cmd/client_eventstreams_delete.go b/cmd/client_eventstreams_delete.go index 07fa9496..bd2cdda0 100644 --- a/cmd/client_eventstreams_delete.go +++ b/cmd/client_eventstreams_delete.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/cmd/client_eventstreams_list.go b/cmd/client_eventstreams_list.go index 99d03f02..1cc8134b 100644 --- a/cmd/client_eventstreams_list.go +++ b/cmd/client_eventstreams_list.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/cmd/client_listeners_delete.go b/cmd/client_listeners_delete.go index dc07d22c..c28c25f2 100644 --- a/cmd/client_listeners_delete.go +++ b/cmd/client_listeners_delete.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/cmd/client_listeners_list.go b/cmd/client_listeners_list.go index bfe62986..9d057e34 100644 --- a/cmd/client_listeners_list.go +++ b/cmd/client_listeners_list.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/cmd/migrate.go b/cmd/migrate.go index c32a7909..ebc547e4 100644 --- a/cmd/migrate.go +++ b/cmd/migrate.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/apiclient/eventstreams.go b/internal/apiclient/eventstreams.go index 90b5e8c9..4b253ad4 100644 --- a/internal/apiclient/eventstreams.go +++ b/internal/apiclient/eventstreams.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/confirmations/confirmations.go b/internal/confirmations/confirmations.go index 5e543fb9..f2ff520e 100644 --- a/internal/confirmations/confirmations.go +++ b/internal/confirmations/confirmations.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/confirmations/confirmed_block_listener.go b/internal/confirmations/confirmed_block_listener.go index fa8cda41..4d54408c 100644 --- a/internal/confirmations/confirmed_block_listener.go +++ b/internal/confirmations/confirmed_block_listener.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/events/eventstream.go b/internal/events/eventstream.go index 646251d1..a46d4323 100644 --- a/internal/events/eventstream.go +++ b/internal/events/eventstream.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 7fc5fa54..8199de45 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/persistence/leveldb/leveldb_persistence.go b/internal/persistence/leveldb/leveldb_persistence.go index 530b3b33..c6eb5373 100644 --- a/internal/persistence/leveldb/leveldb_persistence.go +++ b/internal/persistence/leveldb/leveldb_persistence.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/persistence/postgres/sqlpersistence.go b/internal/persistence/postgres/sqlpersistence.go index 6af2a80f..b75cc961 100644 --- a/internal/persistence/postgres/sqlpersistence.go +++ b/internal/persistence/postgres/sqlpersistence.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/persistence/postgres/transaction_writer.go b/internal/persistence/postgres/transaction_writer.go index c4c91400..f4018b89 100644 --- a/internal/persistence/postgres/transaction_writer.go +++ b/internal/persistence/postgres/transaction_writer.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/persistence/postgres/transactions.go b/internal/persistence/postgres/transactions.go index e797bfec..b985909d 100644 --- a/internal/persistence/postgres/transactions.go +++ b/internal/persistence/postgres/transactions.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/persistence/postgres/txhistory.go b/internal/persistence/postgres/txhistory.go index a1ed3ddc..eb7b6b2a 100644 --- a/internal/persistence/postgres/txhistory.go +++ b/internal/persistence/postgres/txhistory.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/tmconfig/tmconfig.go b/internal/tmconfig/tmconfig.go index 0fceb254..42f7b673 100644 --- a/internal/tmconfig/tmconfig.go +++ b/internal/tmconfig/tmconfig.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/tmmsgs/en_config_descriptions.go b/internal/tmmsgs/en_config_descriptions.go index d68d4e38..0e3ffc73 100644 --- a/internal/tmmsgs/en_config_descriptions.go +++ b/internal/tmmsgs/en_config_descriptions.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/pkg/apitypes/api_types.go b/pkg/apitypes/api_types.go index 76257579..28c37686 100644 --- a/pkg/apitypes/api_types.go +++ b/pkg/apitypes/api_types.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/pkg/fftm/api.go b/pkg/fftm/api.go index 22a46106..9c2023d2 100644 --- a/pkg/fftm/api.go +++ b/pkg/fftm/api.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/pkg/fftm/manager.go b/pkg/fftm/manager.go index 2f12df32..3f6c87fc 100644 --- a/pkg/fftm/manager.go +++ b/pkg/fftm/manager.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/pkg/fftm/manager_test.go b/pkg/fftm/manager_test.go index d349abcf..32d19dd9 100644 --- a/pkg/fftm/manager_test.go +++ b/pkg/fftm/manager_test.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/pkg/fftm/routes.go b/pkg/fftm/routes.go index fd842297..3e09373c 100644 --- a/pkg/fftm/routes.go +++ b/pkg/fftm/routes.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Kaleido, Inc. +// Copyright © 2025 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // From 839806bbec0ba49ece8e5c35f293ddd66da7d53f Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 20 Feb 2025 12:05:56 +0000 Subject: [PATCH 7/9] Apply suggestions from code review Signed-off-by: Chengxuan Xing --- .github/workflows/go.yml | 2 +- Makefile | 2 +- go.mod | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 0dbc7dc7..b466cdf2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,7 +10,7 @@ on: jobs: build: runs-on: ubuntu-latest - container: golang:1.23-bullseye + container: golang:1.22-bullseye defaults: run: shell: bash # needed for codecov diff --git a/Makefile b/Makefile index 43292e1e..40bbc938 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ coverage.html: $(VGO) tool cover -html=coverage.txt coverage: test coverage.html lint: - $(VGO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5 + $(VGO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 GOGC=20 $(LINT) run -v --timeout 5m ${MOCKERY}: diff --git a/go.mod b/go.mod index 3289c1e6..e7b19c12 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/hyperledger/firefly-transaction-manager -go 1.23 +go 1.22 require ( github.com/DATA-DOG/go-sqlmock v1.5.2 From a5d2902cd59f686e414914e5012df1a3e1120f53 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 21 Feb 2025 06:27:59 +0000 Subject: [PATCH 8/9] use new path name Signed-off-by: Chengxuan Xing --- internal/tmmsgs/en_api_descriptions.go | 7 +++++-- pkg/fftm/route_get_status_live.go | 25 +++++++++++++++++++++---- pkg/fftm/route_get_status_ready.go | 19 ++++++++++++++++++- pkg/fftm/routes.go | 10 +++++----- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/internal/tmmsgs/en_api_descriptions.go b/internal/tmmsgs/en_api_descriptions.go index f11767f2..0aeea43b 100644 --- a/internal/tmmsgs/en_api_descriptions.go +++ b/internal/tmmsgs/en_api_descriptions.go @@ -37,8 +37,11 @@ var ( APIEndpointGetEventStreamListeners = ffm("api.endpoints.get.eventstream.listeners", "List event stream listeners") APIEndpointGetEventStreams = ffm("api.endpoints.get.eventstreams", "List event streams") APIEndpointGetGasPrice = ffm("api.endpoints.get.gasprice", "Get the current gas price of the connector's chain") - APIEndpointGetStatusLive = ffm("api.endpoints.get.status.live", "Get the liveness status of the connector") - APIEndpointGetStatusReady = ffm("api.endpoints.get.status.ready", "Get the readiness status of the connector") + APIEndpointGetStatus = ffm("api.endpoints.get.status", "Deprecated - Get the liveness and readiness status of the connector") + APIEndpointGetStatusLive = ffm("api.endpoints.get.status.live", "Deprecated - Get the liveness status of the connector") + APIEndpointGetStatusReady = ffm("api.endpoints.get.status.ready", "Deprecated - Get the readiness status of the connector") + APIEndpointGetLiveness = ffm("api.endpoints.get.livez", "Get the liveness status of the connector") + APIEndpointGetReadiness = ffm("api.endpoints.get.readyz", "Get the readiness status of the connector") APIEndpointGetSubscription = ffm("api.endpoints.get.subscription", "Get listener - route deprecated in favor of /eventstreams/{streamId}/listeners/{listenerId}") APIEndpointGetSubscriptions = ffm("api.endpoints.get.subscriptions", "Get listeners - route deprecated in favor of /eventstreams/{streamId}/listeners") APIEndpointGetTransaction = ffm("api.endpoints.get.transaction", "Get individual transaction with a status summary") diff --git a/pkg/fftm/route_get_status_live.go b/pkg/fftm/route_get_status_live.go index 046c778c..526cd030 100644 --- a/pkg/fftm/route_get_status_live.go +++ b/pkg/fftm/route_get_status_live.go @@ -25,15 +25,15 @@ import ( "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes" ) -// getStatus deprecated, is present for backwards compatibility with the previous generation of connectors i.e. Ethconnect -var getStatus = func(m *manager) *ffapi.Route { +// deprecatedGetStatus deprecated, is present for backwards compatibility with the previous generation of connectors i.e. Ethconnect +var deprecatedGetStatus = func(m *manager) *ffapi.Route { return &ffapi.Route{ Name: "getStatus", Path: "/status", Method: http.MethodGet, PathParams: nil, QueryParams: nil, - Description: tmmsgs.APIEndpointGetStatusLive, + Description: tmmsgs.APIEndpointGetStatus, JSONInputValue: nil, JSONOutputValue: func() interface{} { return &apitypes.LiveStatus{} }, JSONOutputCodes: []int{http.StatusOK}, @@ -43,7 +43,7 @@ var getStatus = func(m *manager) *ffapi.Route { } } -var getLiveStatus = func(m *manager) *ffapi.Route { +var deprecatedGetLiveStatus = func(m *manager) *ffapi.Route { return &ffapi.Route{ Name: "getLiveStatus", Path: "/status/live", @@ -59,3 +59,20 @@ var getLiveStatus = func(m *manager) *ffapi.Route { }, } } + +var getLiveness = func(m *manager) *ffapi.Route { + return &ffapi.Route{ + Name: "getLiveness", + Path: "/livez", + Method: http.MethodGet, + PathParams: nil, + QueryParams: nil, + Description: tmmsgs.APIEndpointGetLiveness, + JSONInputValue: nil, + JSONOutputValue: func() interface{} { return &apitypes.LiveStatus{} }, + JSONOutputCodes: []int{http.StatusOK}, + JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) { + return m.getLiveStatus(r.Req.Context()) + }, + } +} diff --git a/pkg/fftm/route_get_status_ready.go b/pkg/fftm/route_get_status_ready.go index dc397801..82256c68 100644 --- a/pkg/fftm/route_get_status_ready.go +++ b/pkg/fftm/route_get_status_ready.go @@ -25,7 +25,7 @@ import ( "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes" ) -var getReadyStatus = func(m *manager) *ffapi.Route { +var deprecatedGetReadyStatus = func(m *manager) *ffapi.Route { return &ffapi.Route{ Name: "getReadyStatus", Path: "/status/ready", @@ -41,3 +41,20 @@ var getReadyStatus = func(m *manager) *ffapi.Route { }, } } + +var getReadiness = func(m *manager) *ffapi.Route { + return &ffapi.Route{ + Name: "getReadiness", + Path: "/readyz", + Method: http.MethodGet, + PathParams: nil, + QueryParams: nil, + Description: tmmsgs.APIEndpointGetReadiness, + JSONInputValue: nil, + JSONOutputValue: func() interface{} { return &apitypes.ReadyStatus{} }, + JSONOutputCodes: []int{http.StatusOK}, + JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) { + return m.getReadyStatus(r.Req.Context()) + }, + } +} diff --git a/pkg/fftm/routes.go b/pkg/fftm/routes.go index 3e09373c..2447c9b7 100644 --- a/pkg/fftm/routes.go +++ b/pkg/fftm/routes.go @@ -28,11 +28,11 @@ func (m *manager) routes() []*ffapi.Route { getEventStreamListener(m), getEventStreamListeners(m), getEventStreams(m), - getStatus(m), + deprecatedGetStatus(m), getSubscription(m), getSubscriptions(m), - getLiveStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes - getReadyStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes + deprecatedGetLiveStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes + deprecatedGetReadyStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes getTransaction(m), getTransactionConfirmations(m), getTransactionHistory(m), @@ -58,7 +58,7 @@ func (m *manager) routes() []*ffapi.Route { func (m *manager) monitoringRoutes() []*ffapi.Route { return []*ffapi.Route{ - getLiveStatus(m), - getReadyStatus(m), + getReadiness(m), + getLiveness(m), } } From a99198d10ac72346c8d8fdcdc924956ce21db9a2 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 21 Feb 2025 17:11:46 +0000 Subject: [PATCH 9/9] address review comments Signed-off-by: Chengxuan Xing --- internal/apiclient/eventstreams.go | 9 +++++---- internal/persistence/postgres/transaction_writer.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/apiclient/eventstreams.go b/internal/apiclient/eventstreams.go index 4b253ad4..cffb2036 100644 --- a/internal/apiclient/eventstreams.go +++ b/internal/apiclient/eventstreams.go @@ -18,6 +18,7 @@ package apiclient import ( "context" + "errors" "fmt" "regexp" @@ -31,7 +32,7 @@ func (c *fftmClient) GetEventStreams(ctx context.Context) ([]apitypes.EventStrea SetResult(&eventStreams). Get("eventstreams") if !resp.IsSuccess() { - return nil, fmt.Errorf("%s", string(resp.Body())) + return nil, errors.New(string(resp.Body())) } return eventStreams, err } @@ -43,7 +44,7 @@ func (c *fftmClient) GetListeners(ctx context.Context, eventStreamID string) ([] SetResult(&listeners). Get(fmt.Sprintf("eventstreams/%s/listeners", eventStreamID)) if !resp.IsSuccess() { - return nil, fmt.Errorf("%s", string(resp.Body())) + return nil, errors.New(string(resp.Body())) } return listeners, err } @@ -56,7 +57,7 @@ func (c *fftmClient) DeleteEventStream(ctx context.Context, eventStreamID string return err } if !resp.IsSuccess() { - return fmt.Errorf("%s", string(resp.Body())) + return errors.New(string(resp.Body())) } return nil } @@ -92,7 +93,7 @@ func (c *fftmClient) DeleteListener(ctx context.Context, eventStreamID, listener return err } if !resp.IsSuccess() { - return fmt.Errorf("%s", string(resp.Body())) + return errors.New(string(resp.Body())) } return nil } diff --git a/internal/persistence/postgres/transaction_writer.go b/internal/persistence/postgres/transaction_writer.go index f4018b89..2256cde9 100644 --- a/internal/persistence/postgres/transaction_writer.go +++ b/internal/persistence/postgres/transaction_writer.go @@ -355,7 +355,7 @@ func (tw *transactionWriter) assignNonces(ctx context.Context, txInsertsByFrom m } } log.L(ctx).Infof("Assigned nonce %s / %d to %s", signer, cacheEntry.nextNonce, op.txInsert.ID) - //nolint:gosec // Safe conversion as nextNonce is always positive + //nolint:gosec op.txInsert.Nonce = fftypes.NewFFBigInt(int64(cacheEntry.nextNonce)) cacheEntry.nextNonce++ tw.nextNonceCache.Add(signer, cacheEntry)