From 66e6209e4b5de3e9c877ca6de23a702587fecaa5 Mon Sep 17 00:00:00 2001
From: Chris Marslender <chrismarslender@gmail.com>
Date: Tue, 21 Jun 2022 13:34:46 -0500
Subject: [PATCH] Add filesize metrics for full node

---
 go.mod                       |  2 +-
 go.sum                       |  4 +--
 internal/metrics/fullnode.go | 62 ++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index d141542..39f4eab 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/chia-network/chia-exporter
 go 1.17
 
 require (
-	github.com/chia-network/go-chia-libs v0.0.6
+	github.com/chia-network/go-chia-libs v0.0.7
 	github.com/oschwald/maxminddb-golang v1.8.0
 	github.com/prometheus/client_golang v1.12.0
 	github.com/sirupsen/logrus v1.8.1
diff --git a/go.sum b/go.sum
index b4fb4f2..390eaaa 100644
--- a/go.sum
+++ b/go.sum
@@ -73,8 +73,8 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
 github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chia-network/go-chia-libs v0.0.6 h1:8rtDjZb++jIYpm06ajsuMPkYp6Np4XSqb78/LLUhqUM=
-github.com/chia-network/go-chia-libs v0.0.6/go.mod h1:h1y8enwmbHVylzRDd5jA9C7RZMXX82pV8/rviB7L4V8=
+github.com/chia-network/go-chia-libs v0.0.7 h1:upXSFc7gjUyASY0pjHQgRoBcIdBvGEAin+pXuIixMbU=
+github.com/chia-network/go-chia-libs v0.0.7/go.mod h1:h1y8enwmbHVylzRDd5jA9C7RZMXX82pV8/rviB7L4V8=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
diff --git a/internal/metrics/fullnode.go b/internal/metrics/fullnode.go
index 91a4f68..47474b4 100644
--- a/internal/metrics/fullnode.go
+++ b/internal/metrics/fullnode.go
@@ -3,7 +3,10 @@ package metrics
 import (
 	"encoding/json"
 	"fmt"
+	"os"
+	"time"
 
+	"github.com/chia-network/go-chia-libs/pkg/config"
 	log "github.com/sirupsen/logrus"
 
 	"github.com/chia-network/go-chia-libs/pkg/rpc"
@@ -52,6 +55,14 @@ type FullNodeServiceMetrics struct {
 	totalSignagePoints   *wrappedPrometheus.LazyCounter
 	signagePointsSubSlot *wrappedPrometheus.LazyGauge
 	currentSignagePoint  *wrappedPrometheus.LazyGauge
+
+	// Filesize Metrics
+	database          *wrappedPrometheus.LazyGauge
+	databaseWal       *wrappedPrometheus.LazyGauge
+	databaseShm       *wrappedPrometheus.LazyGauge
+	peersDat          *wrappedPrometheus.LazyGauge
+	heightToHash      *wrappedPrometheus.LazyGauge
+	subEpochSummaries *wrappedPrometheus.LazyGauge
 }
 
 // InitMetrics sets all the metrics properties
@@ -83,9 +94,18 @@ func (s *FullNodeServiceMetrics) InitMetrics() {
 	s.preValidationTime = s.metrics.newGauge(chiaServiceFullNode, "pre_validation_time", "Last pre_validation_time from the block event")
 	s.validationTime = s.metrics.newGauge(chiaServiceFullNode, "validation_time", "Last validation time from the block event")
 
+	// Signage Point Metrics
 	s.totalSignagePoints = s.metrics.newCounter(chiaServiceFullNode, "total_signage_points", "Total number of signage points since the metrics exporter started. Only useful when combined with rate() or similar")
 	s.signagePointsSubSlot = s.metrics.newGauge(chiaServiceFullNode, "signage_points_sub_slot", "Number of signage points per sub slot")
 	s.currentSignagePoint = s.metrics.newGauge(chiaServiceFullNode, "current_signage_point", "Index of the last signage point received")
+
+	// File Size Metrics
+	s.database = s.metrics.newGauge(chiaServiceFullNode, "database_filesize", "Size of the database file")
+	s.databaseWal = s.metrics.newGauge(chiaServiceFullNode, "database_wal_filesize", "Size of the database wal file")
+	s.databaseShm = s.metrics.newGauge(chiaServiceFullNode, "database_shm_filesize", "Size of the database shm file")
+	s.peersDat = s.metrics.newGauge(chiaServiceFullNode, "peers_dat_filesize", "Size of peers.dat file")
+	s.heightToHash = s.metrics.newGauge(chiaServiceFullNode, "height_to_hash_filesize", "Size of height_to_hash file")
+	s.subEpochSummaries = s.metrics.newGauge(chiaServiceFullNode, "sub_epoch_summaries_filesize", "Size of sub_epoch_summaries file")
 }
 
 // InitialData is called on startup of the metrics server, to allow seeding metrics with
@@ -94,6 +114,14 @@ func (s *FullNodeServiceMetrics) InitialData() {
 	// Ask for some initial data so we dont have to wait as long
 	utils.LogErr(s.metrics.client.FullNodeService.GetBlockchainState()) // Also calls get_connections once we get the response
 	utils.LogErr(s.metrics.client.FullNodeService.GetBlockCountMetrics())
+
+	// Things that update in the background
+	go func() {
+		for {
+			s.RefreshFileSizes()
+			time.Sleep(30 * time.Second)
+		}
+	}()
 }
 
 // Disconnected clears/unregisters metrics when the connection drops
@@ -278,3 +306,37 @@ func (s *FullNodeServiceMetrics) SignagePoint(resp *types.WebsocketResponse) {
 	s.signagePointsSubSlot.Set(float64(64))
 	s.currentSignagePoint.Set(float64(signagePoint.BroadcastFarmer.SignagePointIndex))
 }
+
+// RefreshFileSizes periodically checks how large files related to the full node are
+func (s *FullNodeServiceMetrics) RefreshFileSizes() {
+	log.Info("cron: chia_full_node updating file sizes")
+	cfg, err := config.GetChiaConfig()
+	if err != nil {
+		log.Errorf("Error getting chia config: %s\n", err.Error())
+	}
+	database := cfg.GetFullPath(cfg.FullNode.DatabasePath)
+	databaseWal := fmt.Sprintf("%s-wal", database)
+	databaseShm := fmt.Sprintf("%s-shm", database)
+	heightToHash := cfg.GetFullPath("db/height-to-hash")
+	peersDat := cfg.GetFullPath("db/peers.dat")
+	subEpochSummaries := cfg.GetFullPath("db/sub-epoch-summaries")
+
+	utils.LogErr(nil, nil, setGaugeToFilesize(database, s.database))
+	utils.LogErr(nil, nil, setGaugeToFilesize(databaseWal, s.databaseWal))
+	utils.LogErr(nil, nil, setGaugeToFilesize(databaseShm, s.databaseShm))
+	utils.LogErr(nil, nil, setGaugeToFilesize(heightToHash, s.heightToHash))
+	utils.LogErr(nil, nil, setGaugeToFilesize(peersDat, s.peersDat))
+	utils.LogErr(nil, nil, setGaugeToFilesize(subEpochSummaries, s.subEpochSummaries))
+}
+
+func setGaugeToFilesize(file string, g *wrappedPrometheus.LazyGauge) error {
+	log.Debugf("Getting filesize of %s\n", file)
+	fi, err := os.Stat(file)
+	if err != nil {
+		return err
+	}
+
+	g.Set(float64(fi.Size()))
+
+	return nil
+}