diff --git a/blockbook.go b/blockbook.go index d92a4ddc..f4bbf5c2 100644 --- a/blockbook.go +++ b/blockbook.go @@ -156,7 +156,7 @@ func main() { glog.Fatal("rpc: ", err) } - index, err = db.NewRocksDB(*dbPath, chain.GetChainParser()) + index, err = db.NewRocksDB(*dbPath, chain.GetChainParser(), metrics) if err != nil { glog.Fatal("rocksDB: ", err) } diff --git a/common/internalstate.go b/common/internalstate.go index 24c0b989..b29ac414 100644 --- a/common/internalstate.go +++ b/common/internalstate.go @@ -15,11 +15,11 @@ const ( // InternalStateColumn contains the data of a db column type InternalStateColumn struct { - Name string `json:"name"` - Version uint32 `json:"version"` - Rows int64 `json:"rows"` - KeysSum int64 `json:"keysSum"` - ValuesSum int64 `json:"valuesSum"` + Name string `json:"name"` + Version uint32 `json:"version"` + Rows int64 `json:"rows"` + KeyBytes int64 `json:"keysSum"` + ValueBytes int64 `json:"valuesSum"` } // InternalState contains the data of the internal state @@ -97,20 +97,29 @@ func (is *InternalState) GetMempoolSyncState() (bool, time.Time) { return is.IsMempoolSynchronized, is.LastMempoolSync } -func (is *InternalState) AddDBColumnStats(c int, rowsDiff int64, keysSumDiff int64, valuesSumDiff int64) { +func (is *InternalState) AddDBColumnStats(c int, rowsDiff int64, keyBytesDiff int64, valueBytesDiff int64) { is.mux.Lock() defer is.mux.Unlock() is.DbColumns[c].Rows += rowsDiff - is.DbColumns[c].KeysSum += keysSumDiff - is.DbColumns[c].ValuesSum += valuesSumDiff + is.DbColumns[c].KeyBytes += keyBytesDiff + is.DbColumns[c].ValueBytes += valueBytesDiff } -func (is *InternalState) SetDBColumnStats(c int, rowsDiff int64, keysSumDiff int64, valuesSumDiff int64) { +func (is *InternalState) SetDBColumnStats(c int, rows int64, keyBytes int64, valueBytes int64) { is.mux.Lock() defer is.mux.Unlock() - is.DbColumns[c].Rows = rowsDiff - is.DbColumns[c].KeysSum = keysSumDiff - is.DbColumns[c].ValuesSum = valuesSumDiff + is.DbColumns[c].Rows = rows + is.DbColumns[c].KeyBytes = keyBytes + is.DbColumns[c].ValueBytes = valueBytes +} + +func (is *InternalState) GetDBColumnStats(c int) (int64, int64, int64) { + is.mux.Lock() + defer is.mux.Unlock() + if c < len(is.DbColumns) { + return is.DbColumns[c].Rows, is.DbColumns[c].KeyBytes, is.DbColumns[c].ValueBytes + } + return 0, 0, 0 } func (is *InternalState) DBSizeTotal() int64 { @@ -118,7 +127,7 @@ func (is *InternalState) DBSizeTotal() int64 { defer is.mux.Unlock() total := int64(0) for _, c := range is.DbColumns { - total += c.KeysSum + c.ValuesSum + total += c.KeyBytes + c.ValueBytes } return total } diff --git a/common/metrics.go b/common/metrics.go index 52376fef..e17cd489 100644 --- a/common/metrics.go +++ b/common/metrics.go @@ -19,6 +19,8 @@ type Metrics struct { IndexDBSize prometheus.Gauge ExplorerViews *prometheus.CounterVec MempoolSize prometheus.Gauge + DbColumnRows *prometheus.GaugeVec + DbColumnSize *prometheus.GaugeVec } type Labels = prometheus.Labels @@ -121,6 +123,22 @@ func GetMetrics(coin string) (*Metrics, error) { ConstLabels: Labels{"coin": coin}, }, ) + metrics.DbColumnRows = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "blockbook_dbcolumn_rows", + Help: "Number of rows in db column", + ConstLabels: Labels{"coin": coin}, + }, + []string{"column"}, + ) + metrics.DbColumnSize = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "blockbook_dbcolumn_size", + Help: "Size of db column (in bytes)", + ConstLabels: Labels{"coin": coin}, + }, + []string{"column"}, + ) v := reflect.ValueOf(metrics) for i := 0; i < v.NumField(); i++ { diff --git a/db/rocksdb.go b/db/rocksdb.go index 31d6e1cd..8d835e84 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -37,6 +37,7 @@ type RocksDB struct { cfh []*gorocksdb.ColumnFamilyHandle chainParser bchain.BlockChainParser is *common.InternalState + metrics *common.Metrics } const ( @@ -97,13 +98,13 @@ func openDB(path string) (*gorocksdb.DB, []*gorocksdb.ColumnFamilyHandle, error) // NewRocksDB opens an internal handle to RocksDB environment. Close // needs to be called to release it. -func NewRocksDB(path string, parser bchain.BlockChainParser) (d *RocksDB, err error) { +func NewRocksDB(path string, parser bchain.BlockChainParser, metrics *common.Metrics) (d *RocksDB, err error) { glog.Infof("rocksdb: open %s", path) db, cfh, err := openDB(path) wo := gorocksdb.NewDefaultWriteOptions() ro := gorocksdb.NewDefaultReadOptions() ro.SetFillCache(false) - return &RocksDB{path, db, wo, ro, cfh, parser, nil}, nil + return &RocksDB{path, db, wo, ro, cfh, parser, nil, metrics}, nil } func (d *RocksDB) closeDB() error { @@ -930,8 +931,8 @@ func (d *RocksDB) LoadInternalState(rpcCoin string) (*common.InternalState, erro if sc[j].Name == nc[i].Name { nc[i].Version = sc[j].Version nc[i].Rows = sc[j].Rows - nc[i].KeysSum = sc[j].KeysSum - nc[i].ValuesSum = sc[j].ValuesSum + nc[i].KeyBytes = sc[j].KeyBytes + nc[i].ValueBytes = sc[j].ValueBytes break } } @@ -947,6 +948,9 @@ func (d *RocksDB) SetInternalState(is *common.InternalState) { // StoreInternalState stores the internal state to db func (d *RocksDB) StoreInternalState(is *common.InternalState) error { + rows, keyBytes, valueBytes := d.is.GetDBColumnStats(cfTransactions) + d.metrics.DbColumnRows.With(common.Labels{"column": cfNames[cfTransactions]}).Set(float64(rows)) + d.metrics.DbColumnSize.With(common.Labels{"column": cfNames[cfTransactions]}).Set(float64(keyBytes + valueBytes)) buf, err := is.Pack() if err != nil { return err diff --git a/db/rocksdb_test.go b/db/rocksdb_test.go index 80e1b0a9..100a7b08 100644 --- a/db/rocksdb_test.go +++ b/db/rocksdb_test.go @@ -25,7 +25,7 @@ func setupRocksDB(t *testing.T, p bchain.BlockChainParser) *RocksDB { if err != nil { t.Fatal(err) } - d, err := NewRocksDB(tmp, p) + d, err := NewRocksDB(tmp, p, nil) if err != nil { t.Fatal(err) }