From eff1a432860f6e25d717ee32086f7fdb60ae6fa2 Mon Sep 17 00:00:00 2001 From: Manoj Krishnan Date: Thu, 2 Jul 2026 20:51:10 +0530 Subject: [PATCH] fix(vscc): prevent nil metrics panic on sql state db - pass metricsProvider (not nil) to statesqldb.NewVersionedDBProvider in VSCC server init so registerMetricsOnce.Do actually runs - guard every db.metrics dereference in statesqldb.go with a nil check so ApplyUpdates/GetLatestSavePoint no longer panic when a db handle was built with a nil metrics provider (e.g. snapshot import path) Fixes #7 --- .../txmgmt/statedb/statesqldb/statesqldb.go | 36 ++++++++++++------- core/vscc/validate.go | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/core/ledger/kvledger/txmgmt/statedb/statesqldb/statesqldb.go b/core/ledger/kvledger/txmgmt/statedb/statesqldb/statesqldb.go index d7cdc25..2b6ca0a 100644 --- a/core/ledger/kvledger/txmgmt/statedb/statesqldb/statesqldb.go +++ b/core/ledger/kvledger/txmgmt/statedb/statesqldb/statesqldb.go @@ -292,12 +292,16 @@ func (db *versionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version. startTime := time.Now() err := db.sqlSchema.Set(updateData) if err != nil { - db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "fail").Add(1) - db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "fail").Observe(time.Since(startTime).Seconds()) + if db.metrics != nil { + db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "fail").Add(1) + db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "fail").Observe(time.Since(startTime).Seconds()) + } logger.Errorf("Error in batch sql write. err:%+v", err) } - db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "success").Add(1) - db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "success").Observe(time.Since(startTime).Seconds()) + if db.metrics != nil { + db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "success").Add(1) + db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Set", "status", "success").Observe(time.Since(startTime).Seconds()) + } errChan <- err wg.Done() }() @@ -309,12 +313,16 @@ func (db *versionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version. startTime := time.Now() err := db.sqlSchema.Delete(deleteData) if err != nil { - db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "fail").Add(1) - db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "fail").Observe(time.Since(startTime).Seconds()) + if db.metrics != nil { + db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "fail").Add(1) + db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "fail").Observe(time.Since(startTime).Seconds()) + } logger.Errorf("Error in batch sql delete. err:%+v", err) } - db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "success").Add(1) - db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "success").Observe(time.Since(startTime).Seconds()) + if db.metrics != nil { + db.metrics.DBCallSql.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "success").Add(1) + db.metrics.DBCallTimeSQL.With("method_name", "ApplyUpdates", "call_type", "Delete", "status", "success").Observe(time.Since(startTime).Seconds()) + } errChan <- err wg.Done() }() @@ -365,12 +373,16 @@ func (db *versionedDB) GetLatestSavePoint() (*version.Height, error) { startTime := time.Now() versionedValue, err := db.sqlSchema.Get(savePointKey) if err != nil { - db.metrics.DBCallSql.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "fail").Add(1) - db.metrics.DBCallTimeSQL.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "fail").Observe(time.Since(startTime).Seconds()) + if db.metrics != nil { + db.metrics.DBCallSql.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "fail").Add(1) + db.metrics.DBCallTimeSQL.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "fail").Observe(time.Since(startTime).Seconds()) + } return nil, err } - db.metrics.DBCallSql.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "success").Add(1) - db.metrics.DBCallTimeSQL.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "success").Observe(time.Since(startTime).Seconds()) + if db.metrics != nil { + db.metrics.DBCallSql.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "success").Add(1) + db.metrics.DBCallTimeSQL.With("method_name", "GetLatestSavePoint", "call_type", "GetLifecycleKeys", "status", "success").Observe(time.Since(startTime).Seconds()) + } if versionedValue == nil { return nil, nil } diff --git a/core/vscc/validate.go b/core/vscc/validate.go index 7077026..781dffa 100644 --- a/core/vscc/validate.go +++ b/core/vscc/validate.go @@ -83,7 +83,7 @@ func NewVsccValidateServer(ledgerConfig *ledger.Config, validationPluginsByName return nil, err } } else if ledgerConfig.StateDBConfig.StateDatabase == ledger.SqlDB { - vdbProvider, err = statesqldb.NewVersionedDBProvider(ledgerConfig.StateDBConfig.SqlDB, nil, nil) + vdbProvider, err = statesqldb.NewVersionedDBProvider(ledgerConfig.StateDBConfig.SqlDB, metricsProvider, nil) if err != nil { return nil, err }