diff --git a/block.go b/block.go index 7dc3af9d..281301d7 100644 --- a/block.go +++ b/block.go @@ -84,6 +84,9 @@ type IndexReader interface { // LabelIndices returns a list of string tuples for which a label value index exists. LabelIndices() ([][]string, error) + // GetSymbolTableSize returns the size occupied by the symbol table of Reader object. + GetSymbolTableSize() uint32 + // Close releases the underlying resources of the reader. Close() error } @@ -382,6 +385,11 @@ func (r blockIndexReader) LabelIndices() ([][]string, error) { return ss, errors.Wrapf(err, "block: %s", r.b.Meta().ULID) } +func (r blockIndexReader) GetSymbolTableSize() uint32 { + ss := r.ir.GetSymbolTableSize() + return ss +} + func (r blockIndexReader) Close() error { r.b.pendingReaders.Done() return nil @@ -474,7 +482,7 @@ func (pb *Block) CleanTombstones(dest string, c Compactor) (bool, error) { numStones := 0 pb.tombstones.Iter(func(id uint64, ivs Intervals) error { - for _ = range ivs { + for range ivs { numStones++ } diff --git a/db.go b/db.go index 1ac2d425..df9384a7 100644 --- a/db.go +++ b/db.go @@ -125,6 +125,7 @@ type dbMetrics struct { cutoffs prometheus.Counter cutoffsFailed prometheus.Counter tombCleanTimer prometheus.Histogram + symbolTableSize prometheus.GaugeFunc } func newDBMetrics(db *DB, r prometheus.Registerer) *dbMetrics { @@ -162,7 +163,23 @@ func newDBMetrics(db *DB, r prometheus.Registerer) *dbMetrics { Name: "prometheus_tsdb_tombstone_cleanup_seconds", Help: "The time taken to recompact blocks to remove tombstones.", }) - + m.symbolTableSize = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ + Name: "prometheus_tsdb_symbol_table_size", + Help: "Size occupied by symbol table", + }, func() float64 { + db.mtx.RLock() + defer db.mtx.RUnlock() + var size uint64 + for _, block := range db.blocks { + ind, err := block.Index() + if err != nil { + size = 0 + break + } + size += uint64(ind.GetSymbolTableSize()) + } + return float64(size) + }) if r != nil { r.MustRegister( m.loadedBlocks, @@ -172,6 +189,7 @@ func newDBMetrics(db *DB, r prometheus.Registerer) *dbMetrics { m.cutoffsFailed, m.compactionsTriggered, m.tombCleanTimer, + m.symbolTableSize, ) } return m diff --git a/index/index.go b/index/index.go index 146332d1..d52b6e70 100644 --- a/index/index.go +++ b/index/index.go @@ -749,6 +749,23 @@ func (r *Reader) decbufUvarintAt(off int) decbuf { return dec } +// getSectionSize returns the first 4 bytes in a section starting at offset off +// to get the content length bytes. +func (r *Reader) getSectionSize(off int) uint32 { + b := r.b.Range(off, off+4) + l := uint32(binary.BigEndian.Uint32(b)) + + if l <= 0 { + l = 0 + } + return l +} + +// getSymbolTableSize returns the bytes taken by the symbol table of Reader object. +func (r *Reader) GetSymbolTableSize() uint32 { + return r.getSectionSize(int(r.toc.symbols)) +} + // readSymbols reads the symbol table fully into memory and allocates proper strings for them. // Strings backed by the mmap'd memory would cause memory faults if applications keep using them // after the reader is closed.