From 7d886e0711a2afd1d4790834f626a7e4a3b58675 Mon Sep 17 00:00:00 2001 From: Matee Ullah Malik Date: Mon, 15 Dec 2025 15:24:46 +0500 Subject: [PATCH] status: report p2p sqlite db size --- p2p/kademlia/store/sqlite/sqlite.go | 42 ++++++++++++++++++---- p2p/p2p.go | 54 ++++++++++++++++++++--------- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/p2p/kademlia/store/sqlite/sqlite.go b/p2p/kademlia/store/sqlite/sqlite.go index d38661d1..fc665156 100644 --- a/p2p/kademlia/store/sqlite/sqlite.go +++ b/p2p/kademlia/store/sqlite/sqlite.go @@ -24,7 +24,6 @@ var ( checkpointInterval = 60 * time.Second // Checkpoint interval in seconds //dbLock sync.Mutex dbName = "data001.sqlite3" - dbFilePath = "" storeBatchRetryTimeout = 5 * time.Second ) @@ -54,6 +53,7 @@ type Store struct { cloud cloud.Storage migrationStore *MigrationMetaStore repWriter *RepWriter + dbFilePath string } // Record is a data record @@ -156,7 +156,7 @@ func NewStore(ctx context.Context, dataDir string, cloud cloud.Storage, mst *Mig } s.db = db - dbFilePath = dbFile + s.dbFilePath = dbFile go s.start(ctx) // Run WAL checkpoint worker every 60 seconds @@ -662,14 +662,44 @@ func (s *Store) Count(ctx context.Context) (int, error) { return count, nil } +func sqliteOnDiskSizeBytes(ctx context.Context, dbPath string) (bytes uint64, ok bool) { + if dbPath == "" { + return 0, false + } + + paths := []string{ + dbPath, + dbPath + "-wal", + dbPath + "-shm", + dbPath + "-journal", + } + + var total uint64 + var found bool + for _, p := range paths { + fi, err := os.Stat(p) + if err != nil { + if os.IsNotExist(err) { + continue + } + logtrace.Error(ctx, "failed to stat sqlite file", logtrace.Fields{logtrace.FieldError: err.Error(), "file_path": p}) + continue + } + found = true + total += uint64(fi.Size()) + } + + return total, found +} + // Stats returns stats of store func (s *Store) Stats(ctx context.Context) (map[string]interface{}, error) { stats := map[string]interface{}{} - fi, err := os.Stat(dbFilePath) - if err != nil { - logtrace.Error(ctx, "failed to get p2p db size", logtrace.Fields{logtrace.FieldError: err.Error()}) + + if bytes, ok := sqliteOnDiskSizeBytes(ctx, s.dbFilePath); !ok { + logtrace.Error(ctx, "failed to get p2p db size", logtrace.Fields{logtrace.FieldError: "p2p db file not found"}) } else { - stats["p2p_db_size"] = utils.BytesToMB(uint64(fi.Size())) + stats["p2p_db_size"] = utils.BytesToMB(bytes) } if count, err := s.Count(ctx); err == nil { diff --git a/p2p/p2p.go b/p2p/p2p.go index c613a32d..6a8a35ff 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -168,31 +168,53 @@ func (s *p2p) Delete(ctx context.Context, key string) error { // Stats return status of p2p func (s *p2p) Stats(ctx context.Context) (map[string]interface{}, error) { - retStats := map[string]interface{}{} - dhtStats, err := s.dht.Stats(ctx) - if err != nil { + if err := ctx.Err(); err != nil { return nil, err } + retStats := map[string]interface{}{} + dhtStats := map[string]any{} + + if s.dht != nil { + if stats, err := s.dht.Stats(ctx); err != nil { + logtrace.Error(ctx, "failed to get dht stats", logtrace.Fields{logtrace.FieldModule: "p2p", logtrace.FieldError: err.Error()}) + } else { + dhtStats = stats + } + + retStats["ban-list"] = s.dht.BanListSnapshot() + retStats["conn-pool"] = s.dht.ConnPoolSnapshot() + + // Expose DHT rolling metrics snapshot both under the top-level key (as expected by + // the status service) and also within the DHT map for backward compatibility. + snapshot := s.dht.MetricsSnapshot() + retStats["dht_metrics"] = snapshot + dhtStats["dht_metrics"] = snapshot + } else { + retStats["ban-list"] = []kademlia.BanSnapshot{} + retStats["conn-pool"] = map[string]int64{} + } + + if s.store != nil { + if dbStats, err := s.store.Stats(ctx); err != nil { + logtrace.Error(ctx, "failed to get store stats", logtrace.Fields{logtrace.FieldModule: "p2p", logtrace.FieldError: err.Error()}) + } else if dbStats != nil { + dhtStats["database"] = dbStats + } + } + retStats["dht"] = dhtStats retStats["config"] = s.config // get free space of current kademlia folder - diskUse, err := utils.DiskUsage(s.config.DataDir) - if err != nil { - return nil, errors.Errorf("get disk info failed: %w", err) + if s.config != nil { + if diskUse, err := utils.DiskUsage(s.config.DataDir); err != nil { + logtrace.Error(ctx, "get disk info failed", logtrace.Fields{logtrace.FieldModule: "p2p", logtrace.FieldError: err.Error()}) + } else { + retStats["disk-info"] = &diskUse + } } - retStats["disk-info"] = &diskUse - retStats["ban-list"] = s.dht.BanListSnapshot() - retStats["conn-pool"] = s.dht.ConnPoolSnapshot() - - // Expose DHT rolling metrics snapshot both under the top-level key (as expected by - // the status service) and also within the DHT map for backward compatibility. - snapshot := s.dht.MetricsSnapshot() - retStats["dht_metrics"] = snapshot - dhtStats["dht_metrics"] = snapshot - return retStats, nil }