Files
zapdb/metrics_test.go
zeekayandHanzo Dev fe8d85d663 rename package badger -> zapdb
The module has been github.com/luxfi/zapdb for a while, but the package inside
it still declared itself badger, so every consumer had to write

	zapdb "github.com/luxfi/zapdb" // package badger

and the alias existed only to paper over the mismatch. 56 root files and the
134 qualified references inside the repo now say zapdb.

Backward compatible in both directions: an existing consumer with the alias
keeps compiling (the alias is now merely redundant), and one without it starts
compiling instead of failing on an undefined zapdb.

Directory badger/ and its cmd package are untouched — that is the CLI, and its
binary is named badger.

Build and vet clean; suite green except TestZRestore, which wants a /tmp/zb/src
benchmark fixture and fails identically without this change.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 14:24:18 -07:00

193 lines
5.6 KiB
Go

/*
* SPDX-FileCopyrightText: © 2017-2025 Istari Digital, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
package zapdb
import (
"expvar"
"math/rand"
"testing"
"github.com/stretchr/testify/require"
)
func clearAllMetrics() {
expvar.Do(func(kv expvar.KeyValue) {
// Reset the value of each expvar variable based on its type
switch v := kv.Value.(type) {
case *expvar.Int:
v.Set(0)
case *expvar.Float:
v.Set(0)
case *expvar.Map:
v.Init()
case *expvar.String:
v.Set("")
}
})
}
func TestWriteMetrics(t *testing.T) {
opt := getTestOptions("")
opt.managedTxns = true
opt.CompactL0OnClose = true
runBadgerTest(t, &opt, func(t *testing.T, db *DB) {
clearAllMetrics()
num := 10
val := make([]byte, 1<<12)
key := make([]byte, 40)
for i := 0; i < num; i++ {
_, err := rand.Read(key)
require.NoError(t, err)
_, err = rand.Read(val)
require.NoError(t, err)
writer := db.NewManagedWriteBatch()
require.NoError(t, writer.SetEntryAt(NewEntry(key, val), 1))
writer.Flush()
}
expectedSize := int64(len(val)) + 48 + 2 // 48 := size of key (40 + 8(ts)), 2 := meta
write_metric := expvar.Get("badger_write_bytes_user")
require.Equal(t, expectedSize*int64(num), write_metric.(*expvar.Int).Value())
put_metric := expvar.Get("badger_put_num_user")
require.Equal(t, int64(num), put_metric.(*expvar.Int).Value())
lsm_metric := expvar.Get("badger_write_bytes_l0")
require.Equal(t, expectedSize*int64(num), lsm_metric.(*expvar.Int).Value())
compactionMetric := expvar.Get("badger_write_bytes_compaction").(*expvar.Map)
require.Equal(t, nil, compactionMetric.Get("l6"))
// Force compaction
db.Close()
_, err := OpenManaged(opt)
require.NoError(t, err)
compactionMetric = expvar.Get("badger_write_bytes_compaction").(*expvar.Map)
require.GreaterOrEqual(t, expectedSize*int64(num)+int64(num*200), compactionMetric.Get("l6").(*expvar.Int).Value())
// Because we have random values, compression is not able to do much, so we incur a cost on total size
})
}
func TestVlogMetrics(t *testing.T) {
opt := getTestOptions("")
opt.managedTxns = true
opt.CompactL0OnClose = true
runBadgerTest(t, &opt, func(t *testing.T, db *DB) {
clearAllMetrics()
num := 10
val := make([]byte, 1<<20) // Large Value
key := make([]byte, 40)
for i := 0; i < num; i++ {
_, err := rand.Read(key)
require.NoError(t, err)
_, err = rand.Read(val)
require.NoError(t, err)
writer := db.NewManagedWriteBatch()
require.NoError(t, writer.SetEntryAt(NewEntry(key, val), 1))
writer.Flush()
}
expectedSize := int64(len(val)) + 200 // vlog expected size
totalWrites := expvar.Get("badger_write_num_vlog")
require.Equal(t, int64(num), totalWrites.(*expvar.Int).Value())
bytesWritten := expvar.Get("badger_write_bytes_vlog")
require.GreaterOrEqual(t, expectedSize*int64(num), bytesWritten.(*expvar.Int).Value())
txn := db.NewTransactionAt(2, false)
item, err := txn.Get(key)
require.NoError(t, err)
require.Equal(t, uint64(1), item.Version())
err = item.Value(func(val []byte) error {
totalReads := expvar.Get("badger_read_num_vlog")
bytesRead := expvar.Get("badger_read_bytes_vlog")
require.Equal(t, int64(1), totalReads.(*expvar.Int).Value())
require.GreaterOrEqual(t, expectedSize, bytesRead.(*expvar.Int).Value())
return nil
})
require.NoError(t, err)
})
}
func TestReadMetrics(t *testing.T) {
opt := getTestOptions("")
opt.managedTxns = true
opt.CompactL0OnClose = true
runBadgerTest(t, &opt, func(t *testing.T, db *DB) {
clearAllMetrics()
num := 10
val := make([]byte, 1<<15)
keys := [][]byte{}
writer := db.NewManagedWriteBatch()
for i := 0; i < num; i++ {
keyB := key("byte", 1)
keys = append(keys, []byte(keyB))
_, err := rand.Read(val)
require.NoError(t, err)
require.NoError(t, writer.SetEntryAt(NewEntry([]byte(keyB), val), 1))
}
writer.Flush()
txn := db.NewTransactionAt(2, false)
item, err := txn.Get(keys[0])
require.NoError(t, err)
require.Equal(t, uint64(1), item.Version())
totalGets := expvar.Get("badger_get_num_user")
require.Equal(t, int64(1), totalGets.(*expvar.Int).Value())
totalMemtableReads := expvar.Get("badger_get_num_memtable")
require.Equal(t, int64(1), totalMemtableReads.(*expvar.Int).Value())
totalLSMGets := expvar.Get("badger_get_num_lsm")
require.Nil(t, totalLSMGets.(*expvar.Map).Get("l6"))
// Force compaction
db.Close()
db, err = OpenManaged(opt)
require.NoError(t, err)
txn = db.NewTransactionAt(2, false)
item, err = txn.Get(keys[0])
require.NoError(t, err)
require.Equal(t, uint64(1), item.Version())
_, err = txn.Get([]byte(key("abdbyte", 1000))) // val should be far enough that bloom filter doesn't hit
require.Error(t, err)
totalLSMGets = expvar.Get("badger_get_num_lsm")
require.Equal(t, int64(0x1), totalLSMGets.(*expvar.Map).Get("l6").(*expvar.Int).Value())
totalBloom := expvar.Get("badger_hit_num_lsm_bloom_filter")
require.Equal(t, int64(0x1), totalBloom.(*expvar.Map).Get("l6").(*expvar.Int).Value())
require.Equal(t, int64(0x1), totalBloom.(*expvar.Map).Get("DoesNotHave_HIT").(*expvar.Int).Value())
require.Equal(t, int64(0x2), totalBloom.(*expvar.Map).Get("DoesNotHave_ALL").(*expvar.Int).Value())
bytesLSM := expvar.Get("badger_read_bytes_lsm")
require.Equal(t, int64(len(val)), bytesLSM.(*expvar.Int).Value())
getWithResult := expvar.Get("badger_get_with_result_num_user")
require.Equal(t, int64(2), getWithResult.(*expvar.Int).Value())
iterOpts := DefaultIteratorOptions
iter := txn.NewKeyIterator(keys[0], iterOpts)
iter.Seek(keys[0])
rangeQueries := expvar.Get("badger_iterator_num_user")
require.Equal(t, int64(1), rangeQueries.(*expvar.Int).Value())
})
}