rocksdb/
statistics.rs

1use crate::ffi;
2
3#[derive(Debug, Clone)]
4pub struct NameParseError;
5impl core::fmt::Display for NameParseError {
6    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7        write!(f, "unrecognized name")
8    }
9}
10
11impl std::error::Error for NameParseError {}
12
13// Helper macro to generate iterable nums that translate into static strings mapped from the cpp
14// land.
15macro_rules! iterable_named_enum {
16    (
17    $(#[$m:meta])*
18    $type_vis:vis enum $typename:ident {
19        $(
20            $(#[$variant_meta:meta])*
21            $variant:ident($variant_str:literal) $(= $value:expr)?,
22        )+
23    }
24    ) => {
25        // Main Type
26        #[allow(clippy::all)]
27        $(#[$m])*
28        $type_vis enum $typename {
29            $(
30            $(#[$variant_meta])*
31            $variant$( = $value)?,
32            )+
33        }
34
35        #[automatically_derived]
36        impl $typename {
37            #[doc = "The corresponding rocksdb string identifier for this variant"]
38            pub const fn name(&self) -> &'static str {
39                match self {
40                    $(
41                        $typename::$variant => $variant_str,
42                    )+
43                }
44            }
45            pub fn iter() -> ::core::slice::Iter<'static, $typename> {
46                static VARIANTS: &'static [$typename] = &[
47                    $(
48                        $typename::$variant,
49                    )+
50                ];
51                VARIANTS.iter()
52            }
53        }
54
55
56        #[automatically_derived]
57        impl ::core::str::FromStr for $typename {
58            type Err = NameParseError;
59            fn from_str(s: &str) -> Result<Self, Self::Err> {
60                match s {
61                    $(
62                        $variant_str => Ok($typename::$variant),
63                    )+
64                    _ => Err(NameParseError),
65                }
66            }
67        }
68
69        #[automatically_derived]
70        impl ::core::fmt::Display for $typename {
71            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
72                self.name().fmt(f)
73            }
74        }
75    };
76}
77
78/// StatsLevel can be used to reduce statistics overhead by skipping certain
79/// types of stats in the stats collection process.
80#[derive(Debug, Copy, Clone, PartialEq, Eq)]
81#[repr(u8)]
82pub enum StatsLevel {
83    /// Disable all metrics
84    DisableAll = 0,
85    /// Disable timer stats, and skip histogram stats
86    ExceptHistogramOrTimers = 2,
87    /// Skip timer stats
88    ExceptTimers,
89    /// Collect all stats except time inside mutex lock AND time spent on
90    /// compression.
91    ExceptDetailedTimers,
92    /// Collect all stats except the counters requiring to get time inside the
93    /// mutex lock.
94    ExceptTimeForMutex,
95    /// Collect all stats, including measuring duration of mutex operations.
96    /// If getting time is expensive on the platform to run, it can
97    /// reduce scalability to more threads, especially for writes.
98    All,
99}
100
101// Keep in-sync with rocksdb/include/rocksdb/statistics.h
102iterable_named_enum! {
103    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
104    #[repr(u32)]
105    pub enum Ticker {
106        /// total block cache misses
107        /// REQUIRES: BlockCacheMiss == BlockCacheIndexMiss +
108        ///                               BlockCacheFilterMiss +
109        ///                               BlockCacheDataMiss;
110        BlockCacheMiss("rocksdb.block.cache.miss") = 0,
111        /// total block cache hit
112        /// REQUIRES: BlockCacheHit == BlockCacheIndexHit +
113        ///                              BlockCacheFilterHit +
114        ///                              BlockCacheDataHit;
115        BlockCacheHit("rocksdb.block.cache.hit"),
116        /// # of blocks added to block cache.
117        BlockCacheAdd("rocksdb.block.cache.add"),
118        /// # of failures when adding blocks to block cache.
119        BlockCacheAddFailures("rocksdb.block.cache.add.failures"),
120        /// # of times cache miss when accessing index block from block cache.
121        BlockCacheIndexMiss("rocksdb.block.cache.index.miss"),
122        /// # of times cache hit when accessing index block from block cache.
123        BlockCacheIndexHit("rocksdb.block.cache.index.hit"),
124        /// # of index blocks added to block cache.
125        BlockCacheIndexAdd("rocksdb.block.cache.index.add"),
126        /// # of bytes of index blocks inserted into cache
127        BlockCacheIndexBytesInsert("rocksdb.block.cache.index.bytes.insert"),
128        /// # of times cache miss when accessing filter block from block cache.
129        BlockCacheFilterMiss("rocksdb.block.cache.filter.miss"),
130        /// # of times cache hit when accessing filter block from block cache.
131        BlockCacheFilterHit("rocksdb.block.cache.filter.hit"),
132        /// # of filter blocks added to block cache.
133        BlockCacheFilterAdd("rocksdb.block.cache.filter.add"),
134        /// # of bytes of bloom filter blocks inserted into cache
135        BlockCacheFilterBytesInsert("rocksdb.block.cache.filter.bytes.insert"),
136        /// # of times cache miss when accessing data block from block cache.
137        BlockCacheDataMiss("rocksdb.block.cache.data.miss"),
138        /// # of times cache hit when accessing data block from block cache.
139        BlockCacheDataHit("rocksdb.block.cache.data.hit"),
140        /// # of data blocks added to block cache.
141        BlockCacheDataAdd("rocksdb.block.cache.data.add"),
142        /// # of bytes of data blocks inserted into cache
143        BlockCacheDataBytesInsert("rocksdb.block.cache.data.bytes.insert"),
144        /// # of bytes read from cache.
145        BlockCacheBytesRead("rocksdb.block.cache.bytes.read"),
146        /// # of bytes written into cache.
147        BlockCacheBytesWrite("rocksdb.block.cache.bytes.write"),
148
149        /// # of times bloom filter has avoided file reads, i.e., negatives.
150        BloomFilterUseful("rocksdb.bloom.filter.useful"),
151        /// # of times bloom FullFilter has not avoided the reads.
152        BloomFilterFullPositive("rocksdb.bloom.filter.full.positive"),
153        /// # of times bloom FullFilter has not avoided the reads and data actually
154        /// exist.
155        BloomFilterFullTruePositive("rocksdb.bloom.filter.full.true.positive"),
156
157        /// # persistent cache hit
158        PersistentCacheHit("rocksdb.persistent.cache.hit"),
159        /// # persistent cache miss
160        PersistentCacheMiss("rocksdb.persistent.cache.miss"),
161
162        /// # total simulation block cache hits
163        SimBlockCacheHit("rocksdb.sim.block.cache.hit"),
164        /// # total simulation block cache misses
165        SimBlockCacheMiss("rocksdb.sim.block.cache.miss"),
166
167        /// # of memtable hits.
168        MemtableHit("rocksdb.memtable.hit"),
169        /// # of memtable misses.
170        MemtableMiss("rocksdb.memtable.miss"),
171
172        /// # of Get() queries served by L0
173        GetHitL0("rocksdb.l0.hit"),
174        /// # of Get() queries served by L1
175        GetHitL1("rocksdb.l1.hit"),
176        /// # of Get() queries served by L2 and up
177        GetHitL2AndUp("rocksdb.l2andup.hit"),
178
179        /**
180         * Compaction_KeyDrop* count the reasons for key drop during compaction
181         * There are 4 reasons currently.
182         */
183        CompactionKeyDropNewerEntry("rocksdb.compaction.key.drop.new"),
184        /// key was written with a newer value.
185        /// Also includes keys dropped for range del.
186        CompactionKeyDropObsolete("rocksdb.compaction.key.drop.obsolete"),
187        /// The key is obsolete.
188        CompactionKeyDropRangeDel("rocksdb.compaction.key.drop.range_del"),
189        /// key was covered by a range tombstone.
190        CompactionKeyDropUser("rocksdb.compaction.key.drop.user"),
191        /// user compaction function has dropped the key.
192        CompactionRangeDelDropObsolete("rocksdb.compaction.range_del.drop.obsolete"),
193        /// all keys in range were deleted.
194        /// Deletions obsoleted before bottom level due to file gap optimization.
195        CompactionOptimizedDelDropObsolete("rocksdb.compaction.optimized.del.drop.obsolete"),
196        /// If a compaction was canceled in sfm to prevent ENOSPC
197        CompactionCancelled("rocksdb.compaction.cancelled"),
198
199        /// Number of keys written to the database via the Put and Write call's
200        NumberKeysWritten("rocksdb.number.keys.written"),
201        /// Number of Keys read,
202        NumberKeysRead("rocksdb.number.keys.read"),
203        /// Number keys updated, if inplace update is enabled
204        NumberKeysUpdated("rocksdb.number.keys.updated"),
205        /// The number of uncompressed bytes issued by DB::Put(), DB::Delete(),
206        /// DB::Merge(), and DB::Write().
207        BytesWritten("rocksdb.bytes.written"),
208        /// The number of uncompressed bytes read from DB::Get().  It could be
209        /// either from memtables, cache, or table files.
210        /// For the number of logical bytes read from DB::MultiGet(),
211        /// please use NumberMultigetBytesRead.
212        BytesRead("rocksdb.bytes.read"),
213        /// The number of calls to seek/next/prev
214        NumberDbSeek("rocksdb.number.db.seek"),
215        NumberDbNext("rocksdb.number.db.next"),
216        NumberDbPrev("rocksdb.number.db.prev"),
217        /// The number of calls to seek/next/prev that returned data
218        NumberDbSeekFound("rocksdb.number.db.seek.found"),
219        NumberDbNextFound("rocksdb.number.db.next.found"),
220        NumberDbPrevFound("rocksdb.number.db.prev.found"),
221        /// The number of uncompressed bytes read from an iterator.
222        /// Includes size of key and value.
223        IterBytesRead("rocksdb.db.iter.bytes.read"),
224        NoFileOpens("rocksdb.no.file.opens"),
225        NoFileErrors("rocksdb.no.file.errors"),
226        /// Writer has to wait for compaction or flush to finish.
227        StallMicros("rocksdb.stall.micros"),
228        /// The wait time for db mutex.
229        /// Disabled by default. To enable it set stats level to kAll
230        DbMutexWaitMicros("rocksdb.db.mutex.wait.micros"),
231
232        /// Number of MultiGet calls, keys read, and bytes read
233        NumberMultigetCalls("rocksdb.number.multiget.get"),
234        NumberMultigetKeysRead("rocksdb.number.multiget.keys.read"),
235        NumberMultigetBytesRead("rocksdb.number.multiget.bytes.read"),
236
237        NumberMergeFailures("rocksdb.number.merge.failures"),
238
239        /// Prefix filter stats when used for point lookups (Get / MultiGet).
240        /// (For prefix filter stats on iterators, see *_LEVEL_Seek_*.)
241        /// Checked: filter was queried
242        BloomFilterPrefixChecked("rocksdb.bloom.filter.prefix.checked"),
243        /// Useful: filter returned false so prevented accessing data+index blocks
244        BloomFilterPrefixUseful("rocksdb.bloom.filter.prefix.useful"),
245        /// True positive: found a key matching the point query. When another key
246        /// with the same prefix matches, it is considered a false positive by
247        /// these statistics even though the filter returned a true positive.
248        BloomFilterPrefixTruePositive("rocksdb.bloom.filter.prefix.true.positive"),
249
250        /// Number of times we had to reseek inside an iteration to skip
251        /// over large number of keys with same userkey.
252        NumberOfReseeksInIteration("rocksdb.number.reseeks.iteration"),
253
254        /// Record the number of calls to GetUpdatesSince. Useful to keep track of
255        /// transaction log iterator refreshes
256        GetUpdatesSinceCalls("rocksdb.getupdatessince.calls"),
257        /// Number of times WAL sync is done
258        WalFileSynced("rocksdb.wal.synced"),
259        /// Number of bytes written to WAL
260        WalFileBytes("rocksdb.wal.bytes"),
261
262        /// Writes can be processed by requesting thread or by the thread at the
263        /// head of the writers queue.
264        WriteDoneBySelf("rocksdb.write.self"),
265        WriteDoneByOther("rocksdb.write.other"),
266        /// Equivalent to writes done for others
267        WriteWithWal("rocksdb.write.wal"),
268        /// Number of Write calls that request WAL
269        CompactReadBytes("rocksdb.compact.read.bytes"),
270        /// Bytes read during compaction
271        CompactWriteBytes("rocksdb.compact.write.bytes"),
272        /// Bytes written during compaction
273        FlushWriteBytes("rocksdb.flush.write.bytes"),
274        /// Bytes written during flush
275
276        /// Compaction read and write statistics broken down by CompactionReason
277        CompactReadBytesMarked("rocksdb.compact.read.marked.bytes"),
278        CompactReadBytesPeriodic("rocksdb.compact.read.periodic.bytes"),
279        CompactReadBytesTtl("rocksdb.compact.read.ttl.bytes"),
280        CompactWriteBytesMarked("rocksdb.compact.write.marked.bytes"),
281        CompactWriteBytesPeriodic("rocksdb.compact.write.periodic.bytes"),
282        CompactWriteBytesTtl("rocksdb.compact.write.ttl.bytes"),
283
284        /// Number of table's properties loaded directly from file, without creating
285        /// table reader object.
286        NumberDirectLoadTableProperties("rocksdb.number.direct.load.table.properties"),
287        NumberSuperversionAcquires("rocksdb.number.superversion_acquires"),
288        NumberSuperversionReleases("rocksdb.number.superversion_releases"),
289        NumberSuperversionCleanups("rocksdb.number.superversion_cleanups"),
290
291        /// # of compressions/decompressions executed
292        NumberBlockCompressed("rocksdb.number.block.compressed"),
293        NumberBlockDecompressed("rocksdb.number.block.decompressed"),
294
295        /// DEPRECATED / unused (see NumberBlockCompression_*)
296        NumberBlockNotCompressed("rocksdb.number.block.not_compressed"),
297
298        /// Tickers that record cumulative time.
299        MergeOperationTotalTime("rocksdb.merge.operation.time.nanos"),
300        FilterOperationTotalTime("rocksdb.filter.operation.time.nanos"),
301        CompactionCpuTotalTime("rocksdb.compaction.total.time.cpu_micros"),
302
303        /// Row cache.
304        RowCacheHit("rocksdb.row.cache.hit"),
305        RowCacheMiss("rocksdb.row.cache.miss"),
306
307        /// Read amplification statistics.
308        /// Read amplification can be calculated using this formula
309        /// (ReadAMP_ToTAL_ReadBytes / Read_AMP_Estimate_UsefulBytes)
310        //
311        /// REQUIRES: ReadOptions::read_amp_bytes_per_bit to be enabled
312        ReadAmpEstimateUsefulBytes("rocksdb.read.amp.estimate.useful.bytes"),
313        /// Estimate of total bytes actually used.
314        ReadAmpTotalReadBytes("rocksdb.read.amp.total.read.bytes"),
315        /// Total size of loaded data blocks.
316
317        /// Number of refill intervals where rate limiter's bytes are fully consumed.
318        NumberRateLimiterDrains("rocksdb.number.rate_limiter.drains"),
319
320        /// Number of internal keys skipped by Iterator
321        NumberIterSkip("rocksdb.number.iter.skip"),
322
323        /// BlobDB specific stats
324        /// # of Put/PutTtl/PutUntil to BlobDB. Only applicable to legacy BlobDB.
325        BlobDbNumPut("rocksdb.blobdb.num.put"),
326        /// # of Write to BlobDB. Only applicable to legacy BlobDB.
327        BlobDbNumWrite("rocksdb.blobdb.num.write"),
328        /// # of Get to BlobDB. Only applicable to legacy BlobDB.
329        BlobDbNumGet("rocksdb.blobdb.num.get"),
330        /// # of MultiGet to BlobDB. Only applicable to legacy BlobDB.
331        BlobDbNumMultiget("rocksdb.blobdb.num.multiget"),
332        /// # of Seek/SeekToFirst/SeekToLast/SeekForPrev to BlobDB iterator. Only
333        /// applicable to legacy BlobDB.
334        BlobDbNumSeek("rocksdb.blobdb.num.seek"),
335        /// # of Next to BlobDB iterator. Only applicable to legacy BlobDB.
336        BlobDbNumNext("rocksdb.blobdb.num.next"),
337        /// # of Prev to BlobDB iterator. Only applicable to legacy BlobDB.
338        BlobDbNumPrev("rocksdb.blobdb.num.prev"),
339        /// # of keys written to BlobDB. Only applicable to legacy BlobDB.
340        BlobDbNumKeysWritten("rocksdb.blobdb.num.keys.written"),
341        /// # of keys read from BlobDB. Only applicable to legacy BlobDB.
342        BlobDbNumKeysRead("rocksdb.blobdb.num.keys.read"),
343        /// # of bytes (key + value) written to BlobDB. Only applicable to legacy
344        /// BlobDB.
345        BlobDbBytesWritten("rocksdb.blobdb.bytes.written"),
346        /// # of bytes (keys + value) read from BlobDB. Only applicable to legacy
347        /// BlobDB.
348        BlobDbBytesRead("rocksdb.blobdb.bytes.read"),
349        /// # of keys written by BlobDB as non-Ttl inlined value. Only applicable to
350        /// legacy BlobDB.
351        BlobDbWriteInlined("rocksdb.blobdb.write.inlined"),
352        /// # of keys written by BlobDB as Ttl inlined value. Only applicable to legacy
353        /// BlobDB.
354        BlobDbWriteInlinedTtl("rocksdb.blobdb.write.inlined.ttl"),
355        /// # of keys written by BlobDB as non-Ttl blob value. Only applicable to
356        /// legacy BlobDB.
357        BlobDbWriteBlob("rocksdb.blobdb.write.blob"),
358        /// # of keys written by BlobDB as Ttl blob value. Only applicable to legacy
359        /// BlobDB.
360        BlobDbWriteBlobTtl("rocksdb.blobdb.write.blob.ttl"),
361        /// # of bytes written to blob file.
362        BlobDbBlobFileBytesWritten("rocksdb.blobdb.blob.file.bytes.written"),
363        /// # of bytes read from blob file.
364        BlobDbBlobFileBytesRead("rocksdb.blobdb.blob.file.bytes.read"),
365        /// # of times a blob files being synced.
366        BlobDbBlobFileSynced("rocksdb.blobdb.blob.file.synced"),
367        /// # of blob index evicted from base DB by BlobDB compaction filter because
368        /// of expiration. Only applicable to legacy BlobDB.
369        BlobDbBlobIndexExpiredCount("rocksdb.blobdb.blob.index.expired.count"),
370        /// size of blob index evicted from base DB by BlobDB compaction filter
371        /// because of expiration. Only applicable to legacy BlobDB.
372        BlobDbBlobIndexExpiredSize("rocksdb.blobdb.blob.index.expired.size"),
373        /// # of blob index evicted from base DB by BlobDB compaction filter because
374        /// of corresponding file deleted. Only applicable to legacy BlobDB.
375        BlobDbBlobIndexEvictedCount("rocksdb.blobdb.blob.index.evicted.count"),
376        /// size of blob index evicted from base DB by BlobDB compaction filter
377        /// because of corresponding file deleted. Only applicable to legacy BlobDB.
378        BlobDbBlobIndexEvictedSize("rocksdb.blobdb.blob.index.evicted.size"),
379        /// # of blob files that were obsoleted by garbage collection. Only applicable
380        /// to legacy BlobDB.
381        BlobDbGcNumFiles("rocksdb.blobdb.gc.num.files"),
382        /// # of blob files generated by garbage collection. Only applicable to legacy
383        /// BlobDB.
384        BlobDbGcNumNewFiles("rocksdb.blobdb.gc.num.new.files"),
385        /// # of BlobDB garbage collection failures. Only applicable to legacy BlobDB.
386        BlobDbGcFailures("rocksdb.blobdb.gc.failures"),
387        /// # of keys relocated to new blob file by garbage collection.
388        BlobDbGcNumKeysRelocated("rocksdb.blobdb.gc.num.keys.relocated"),
389        /// # of bytes relocated to new blob file by garbage collection.
390        BlobDbGcBytesRelocated("rocksdb.blobdb.gc.bytes.relocated"),
391        /// # of blob files evicted because of BlobDB is full. Only applicable to
392        /// legacy BlobDB.
393        BlobDbFifoNumFilesEvicted("rocksdb.blobdb.fifo.num.files.evicted"),
394        /// # of keys in the blob files evicted because of BlobDB is full. Only
395        /// applicable to legacy BlobDB.
396        BlobDbFifoNumKeysEvicted("rocksdb.blobdb.fifo.num.keys.evicted"),
397        /// # of bytes in the blob files evicted because of BlobDB is full. Only
398        /// applicable to legacy BlobDB.
399        BlobDbFifoBytesEvicted("rocksdb.blobdb.fifo.bytes.evicted"),
400
401        /// These counters indicate a performance issue in WritePrepared transactions.
402        /// We should not seem them ticking them much.
403        /// # of times prepare_mutex_ is acquired in the fast path.
404        TxnPrepareMutexOverhead("rocksdb.txn.overhead.mutex.prepare"),
405        /// # of times old_commit_map_mutex_ is acquired in the fast path.
406        TxnOldCommitMapMutexOverhead("rocksdb.txn.overhead.mutex.old.commit.map"),
407        /// # of times we checked a batch for duplicate keys.
408        TxnDuplicateKeyOverhead("rocksdb.txn.overhead.duplicate.key"),
409        /// # of times snapshot_mutex_ is acquired in the fast path.
410        TxnSnapshotMutexOverhead("rocksdb.txn.overhead.mutex.snapshot"),
411        /// # of times ::Get returned TryAgain due to expired snapshot seq
412        TxnGetTryAgain("rocksdb.txn.get.tryagain"),
413
414        /// Number of keys actually found in MultiGet calls (vs number requested by
415        /// caller)
416        /// NumberMultigetKeys_Read gives the number requested by caller
417        NumberMultigetKeysFound("rocksdb.number.multiget.keys.found"),
418
419        NoIteratorCreated("rocksdb.num.iterator.created"),
420        /// number of iterators created
421        NoIteratorDeleted("rocksdb.num.iterator.deleted"),
422        /// number of iterators deleted
423        BlockCacheCompressionDictMiss("rocksdb.block.cache.compression.dict.miss"),
424        BlockCacheCompressionDictHit("rocksdb.block.cache.compression.dict.hit"),
425        BlockCacheCompressionDictAdd("rocksdb.block.cache.compression.dict.add"),
426        BlockCacheCompressionDictBytesInsert("rocksdb.block.cache.compression.dict.bytes.insert"),
427
428        /// # of blocks redundantly inserted into block cache.
429        /// REQUIRES: BlockCacheAddRedundant <= BlockCacheAdd
430        BlockCacheAddRedundant("rocksdb.block.cache.add.redundant"),
431        /// # of index blocks redundantly inserted into block cache.
432        /// REQUIRES: BlockCacheIndexAddRedundant <= BlockCacheIndexAdd
433        BlockCacheIndexAddRedundant("rocksdb.block.cache.index.add.redundant"),
434        /// # of filter blocks redundantly inserted into block cache.
435        /// REQUIRES: BlockCacheFilterAddRedundant <= BlockCacheFilterAdd
436        BlockCacheFilterAddRedundant("rocksdb.block.cache.filter.add.redundant"),
437        /// # of data blocks redundantly inserted into block cache.
438        /// REQUIRES: BlockCacheDataAddRedundant <= BlockCacheDataAdd
439        BlockCacheDataAddRedundant("rocksdb.block.cache.data.add.redundant"),
440        /// # of dict blocks redundantly inserted into block cache.
441        /// REQUIRES: BlockCacheCompressionDictAddRedundant
442        ///           <= BlockCacheCompressionDictAdd
443        BlockCacheCompressionDictAddRedundant("rocksdb.block.cache.compression.dict.add.redundant"),
444
445        /// # of files marked as trash by sst file manager and will be deleted
446        /// later by background thread.
447        FilesMarkedTrash("rocksdb.files.marked.trash"),
448        /// # of trash files deleted by the background thread from the trash queue.
449        FilesDeletedFromTrashQueue("rocksdb.files.marked.trash.deleted"),
450        /// # of files deleted immediately by sst file manager through delete
451        /// scheduler.
452        FilesDeletedImmediately("rocksdb.files.deleted.immediately"),
453
454        /// The counters for error handler, not that, bg_io_error is the subset of
455        /// bg_error and bg_retryable_io_error is the subset of bg_io_error.
456        /// The misspelled versions are deprecated and only kept for compatibility.
457        /// ToDO: remove the misspelled tickers in the next major release.
458        ErrorHandlerBgErrorCount("rocksdb.error.handler.bg.error.count"),
459        ErrorHandlerBgErrorCountMisspelled("rocksdb.error.handler.bg.errro.count"),
460        ErrorHandlerBgIoErrorCount("rocksdb.error.handler.bg.io.error.count"),
461        ErrorHandlerBgIoErrorCountMisspelled("rocksdb.error.handler.bg.io.errro.count"),
462        ErrorHandlerBgRetryableIoErrorCount("rocksdb.error.handler.bg.retryable.io.error.count"),
463        ErrorHandlerBgRetryableIoErrorCountMisspelled("rocksdb.error.handler.bg.retryable.io.errro.count"),
464        ErrorHandlerAutoResumeCount("rocksdb.error.handler.autoresume.count"),
465        ErrorHandlerAutoResumeRetryTotalCount("rocksdb.error.handler.autoresume.retry.total.count"),
466        ErrorHandlerAutoResumeSuccessCount("rocksdb.error.handler.autoresume.success.count"),
467
468        /// Statistics for memtable garbage collection:
469        /// Raw bytes of data (payload) present on memtable at flush time.
470        MemtablePayloadBytesAtFlush("rocksdb.memtable.payload.bytes.at.flush"),
471        /// Outdated bytes of data present on memtable at flush time.
472        MemtableGarbageBytesAtFlush("rocksdb.memtable.garbage.bytes.at.flush"),
473
474        /// Secondary cache statistics
475        SecondaryCacheHits("rocksdb.secondary.cache.hits"),
476
477        /// Bytes read by `VerifyChecksum()` and `VerifyFileChecksums()` APIs.
478        VerifyChecksumReadBytes("rocksdb.verify_checksum.read.bytes"),
479
480        /// Bytes read/written while creating backups
481        BackupReadBytes("rocksdb.backup.read.bytes"),
482        BackupWriteBytes("rocksdb.backup.write.bytes"),
483
484        /// Remote compaction read/write statistics
485        RemoteCompactReadBytes("rocksdb.remote.compact.read.bytes"),
486        RemoteCompactWriteBytes("rocksdb.remote.compact.write.bytes"),
487
488        /// Tiered storage related statistics
489        HotFileReadBytes("rocksdb.hot.file.read.bytes"),
490        WarmFileReadBytes("rocksdb.warm.file.read.bytes"),
491        ColdFileReadBytes("rocksdb.cold.file.read.bytes"),
492        HotFileReadCount("rocksdb.hot.file.read.count"),
493        WarmFileReadCount("rocksdb.warm.file.read.count"),
494        ColdFileReadCount("rocksdb.cold.file.read.count"),
495
496        /// Last level and non-last level read statistics
497        LastLevelReadBytes("rocksdb.last.level.read.bytes"),
498        LastLevelReadCount("rocksdb.last.level.read.count"),
499        NonLastLevelReadBytes("rocksdb.non.last.level.read.bytes"),
500        NonLastLevelReadCount("rocksdb.non.last.level.read.count"),
501
502        /// Statistics on iterator Seek() (and variants) for each sorted run. I.e. a
503        /// single user Seek() can result in many sorted run Seek()s.
504        /// The stats are split between last level and non-last level.
505        /// Filtered: a filter such as prefix Bloom filter indicate the Seek() would
506        /// not find anything relevant, so avoided a likely access to data+index
507        /// blocks.
508        LastLevelSeekFiltered("rocksdb.last.level.seek.filtered"),
509        /// Filter match: a filter such as prefix Bloom filter was queried but did
510        /// not filter out the seek.
511        LastLevelSeekFilterMatch("rocksdb.last.level.seek.filter.match"),
512        /// At least one data block was accessed for a Seek() (or variant) on a
513        /// sorted run.
514        LastLevelSeekData("rocksdb.last.level.seek.data"),
515        /// At least one value() was accessed for the seek (suggesting it was useful),
516        /// and no filter such as prefix Bloom was queried.
517        LastLevelSeekDataUsefulNoFilter("rocksdb.last.level.seek.data.useful.no.filter"),
518        /// At least one value() was accessed for the seek (suggesting it was useful),
519        /// after querying a filter such as prefix Bloom.
520        LastLevelSeekDataUsefulFilterMatch("rocksdb.last.level.seek.data.useful.filter.match"),
521        /// The same set of stats, but for non-last level seeks.
522        NonLastLevelSeekFiltered("rocksdb.non.last.level.seek.filtered"),
523        NonLastLevelSeekFilterMatch("rocksdb.non.last.level.seek.filter.match"),
524        NonLastLevelSeekData("rocksdb.non.last.level.seek.data"),
525        NonLastLevelSeekDataUsefulNoFilter("rocksdb.non.last.level.seek.data.useful.no.filter"),
526        NonLastLevelSeekDataUsefulFilterMatch("rocksdb.non.last.level.seek.data.useful.filter.match"),
527
528        /// Number of block checksum verifications
529        BlockChecksumComputeCount("rocksdb.block.checksum.compute.count"),
530        /// Number of times RocksDB detected a corruption while verifying a block
531        /// checksum. RocksDB does not remember corruptions that happened during user
532        /// reads so the same block corruption may be detected multiple times.
533        BlockChecksumMismatchCount("rocksdb.block.checksum.mismatch.count"),
534
535        MultigetCoroutineCount("rocksdb.multiget.coroutine.count"),
536
537        /// Integrated BlobDB specific stats
538        /// # of times cache miss when accessing blob from blob cache.
539        BlobDbCacheMiss("rocksdb.blobdb.cache.miss"),
540        /// # of times cache hit when accessing blob from blob cache.
541        BlobDbCacheHit("rocksdb.blobdb.cache.hit"),
542        /// # of data blocks added to blob cache.
543        BlobDbCacheAdd("rocksdb.blobdb.cache.add"),
544        /// # of failures when adding blobs to blob cache.
545        BlobDbCacheAddFailures("rocksdb.blobdb.cache.add.failures"),
546        /// # of bytes read from blob cache.
547        BlobDbCacheBytesRead("rocksdb.blobdb.cache.bytes.read"),
548        /// # of bytes written into blob cache.
549        BlobDbCacheBytesWrite("rocksdb.blobdb.cache.bytes.write"),
550
551        /// Time spent in the ReadAsync file system call
552        ReadAsyncMicros("rocksdb.read.async.micros"),
553        /// Number of errors returned to the async read callback
554        AsyncReadErrorCount("rocksdb.async.read.error.count"),
555
556        /// Fine grained secondary cache stats
557        SecondaryCacheFilterHits("rocksdb.secondary.cache.filter.hits"),
558        SecondaryCacheIndexHits("rocksdb.secondary.cache.index.hits"),
559        SecondaryCacheDataHits("rocksdb.secondary.cache.data.hits"),
560
561        /// Number of lookup into the prefetched tail (see
562        /// `TableOpenPrefetchTailReadBytes`)
563        /// that can't find its data for table open
564        TableOpenPrefetchTailMiss("rocksdb.table.open.prefetch.tail.miss"),
565        /// Number of lookup into the prefetched tail (see
566        /// `TableOpenPrefetchTailReadBytes`)
567        /// that finds its data for table open
568        TableOpenPrefetchTailHit("rocksdb.table.open.prefetch.tail.hit"),
569
570        /// Statistics on the filtering by user-defined timestamps
571        /// # of times timestamps are checked on accessing the table
572        TimestampFilterTableChecked("rocksdb.timestamp.filter.table.checked"),
573        /// # of times timestamps can successfully help skip the table access
574        TimestampFilterTableFiltered("rocksdb.timestamp.filter.table.filtered"),
575
576        /// Number of input bytes (uncompressed) to compression for SST blocks that
577        /// are stored compressed.
578        BytesCompressedFrom("rocksdb.bytes.compressed.from"),
579        /// Number of output bytes (compressed) from compression for SST blocks that
580        /// are stored compressed.
581        BytesCompressedTo("rocksdb.bytes.compressed.to"),
582        /// Number of uncompressed bytes for SST blocks that are stored uncompressed
583        /// because compression type is kNoCompression, or some error case caused
584        /// compression not to run or produce an output. Index blocks are only counted
585        /// if enable_index_compression is true.
586        BytesCompressionBypassed("rocksdb.bytes.compression_bypassed"),
587        /// Number of input bytes (uncompressed) to compression for SST blocks that
588        /// are stored uncompressed because the compression result was rejected,
589        /// either because the ratio was not acceptable (see
590        /// CompressionOptions::max_compressed_bytes_per_kb) or found invalid by the
591        /// `verify_compression` option.
592        BytesCompressionRejected("rocksdb.bytes.compression.rejected"),
593
594        /// Like BytesCompressionBypassed but counting number of blocks
595        NumberBlockCompressionBypassed("rocksdb.number.block_compression_bypassed"),
596        /// Like BytesCompressionRejected but counting number of blocks
597        NumberBlockCompressionRejected("rocksdb.number.block_compression_rejected"),
598
599        /// Number of input bytes (compressed) to decompression in reading compressed
600        /// SST blocks from storage.
601        BytesDecompressedFrom("rocksdb.bytes.decompressed.from"),
602        /// Number of output bytes (uncompressed) from decompression in reading
603        /// compressed SST blocks from storage.
604        BytesDecompressedTo("rocksdb.bytes.decompressed.to"),
605
606        /// Number of times readahead is trimmed during scans when
607        /// ReadOptions.auto_readahead_size is set.
608        ReadAheadTrimmed("rocksdb.readahead.trimmed"),
609
610        /// Number of Fifo compactions that drop files based on different reasons
611        FifoMaxSizeCompactions("rocksdb.fifo.max.size.compactions"),
612        FifoTtlCompactions("rocksdb.fifo.ttl.compactions"),
613
614        /// Number of bytes prefetched during user initiated scan
615        PrefetchBytes("rocksdb.prefetch.bytes"),
616
617        /// Number of prefetched bytes that were actually useful
618        PrefetchBytesUseful("rocksdb.prefetch.bytes.useful"),
619
620        /// Number of FS reads avoided due to scan prefetching
621        PrefetchHits("rocksdb.prefetch.hits"),
622
623        /// Compressed secondary cache related stats
624        CompressedSecondaryCacheDummyHits("rocksdb.compressed.secondary.cache.dummy.hits"),
625        CompressedSecondaryCacheHits("rocksdb.compressed.secondary.cache.hits"),
626        CompressedSecondaryCachePromotions("rocksdb.compressed.secondary.cache.promotions"),
627        CompressedSecondaryCachePromotionSkips("rocksdb.compressed.secondary.cache.promotion.skips"),
628    }
629}
630
631iterable_named_enum! {
632    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
633    #[repr(u32)]
634    pub enum Histogram {
635        DbGet("rocksdb.db.get.micros") = 0,
636        DbWrite("rocksdb.db.write.micros"),
637        CompactionTime("rocksdb.compaction.times.micros"),
638        CompactionCpuTime("rocksdb.compaction.times.cpu_micros"),
639        SubcompactionSetupTime("rocksdb.subcompaction.setup.times.micros"),
640        TableSyncMicros("rocksdb.table.sync.micros"),
641        CompactionOutfileSyncMicros("rocksdb.compaction.outfile.sync.micros"),
642        WalFileSyncMicros("rocksdb.wal.file.sync.micros"),
643        ManifestFileSyncMicros("rocksdb.manifest.file.sync.micros"),
644        /// Time spent in IO during table open
645        TableOpenIoMicros("rocksdb.table.open.io.micros"),
646        DbMultiget("rocksdb.db.multiget.micros"),
647        ReadBlockCompactionMicros("rocksdb.read.block.compaction.micros"),
648        ReadBlockGetMicros("rocksdb.read.block.get.micros"),
649        WriteRawBlockMicros("rocksdb.write.raw.block.micros"),
650        NumFilesInSingleCompaction("rocksdb.numfiles.in.singlecompaction"),
651        DbSeek("rocksdb.db.seek.micros"),
652        WriteStall("rocksdb.db.write.stall"),
653        /// Time spent in reading block-based or plain SST table
654        SstReadMicros("rocksdb.sst.read.micros"),
655        /// Time spent in reading SST table (currently only block-based table) or blob
656        /// file corresponding to `Env::IOActivity`
657        FileReadFlushMicros("rocksdb.file.read.flush.micros"),
658        FileReadCompactionMicros("rocksdb.file.read.compaction.micros"),
659        FileReadDbOpenMicros("rocksdb.file.read.db.open.micros"),
660        /// The following `FILE_READ_*` require stats level greater than
661        /// `StatsLevel::kExceptDetailedTimers`
662        FileReadGetMicros("rocksdb.file.read.get.micros"),
663        FileReadMultigetMicros("rocksdb.file.read.multiget.micros"),
664        FileReadDbIteratorMicros("rocksdb.file.read.db.iterator.micros"),
665        FileReadVerifyDbChecksumMicros("rocksdb.file.read.verify.db.checksum.micros"),
666        FileReadVerifyFileChecksumsMicros("rocksdb.file.read.verify.file.checksums.micros"),
667        /// The number of subcompactions actually scheduled during a compaction
668        NumSubcompactionsScheduled("rocksdb.num.subcompactions.scheduled"),
669        /// Value size distribution in each operation
670        BytesPerRead("rocksdb.bytes.per.read"),
671        BytesPerWrite("rocksdb.bytes.per.write"),
672        BytesPerMultiget("rocksdb.bytes.per.multiget"),
673        BytesCompressed("rocksdb.bytes.compressed"),
674        /// DEPRECATED / unused (see BytesCompressed{From,To})
675        BytesDecompressed("rocksdb.bytes.decompressed"),
676        /// DEPRECATED / unused (see BytesDecompressed{From,To})
677        CompressionTimesNanos("rocksdb.compression.times.nanos"),
678        DecompressionTimesNanos("rocksdb.decompression.times.nanos"),
679        /// Number of merge operands passed to the merge operator in user read
680        /// requests.
681        ReadNumMergeOperands("rocksdb.read.num.merge_operands"),
682        /// BlobDB specific stats
683        /// Size of keys written to BlobDB. Only applicable to legacy BlobDB.
684        BlobDbKeySize("rocksdb.blobdb.key.size"),
685        /// Size of values written to BlobDB. Only applicable to legacy BlobDB.
686        BlobDbValueSize("rocksdb.blobdb.value.size"),
687        /// BlobDB Put/PutWithTTL/PutUntil/Write latency. Only applicable to legacy
688        /// BlobDB.
689        BlobDbWriteMicros("rocksdb.blobdb.write.micros"),
690        /// BlobDB Get latency. Only applicable to legacy BlobDB.
691        BlobDbGetMicros("rocksdb.blobdb.get.micros"),
692        /// BlobDB MultiGet latency. Only applicable to legacy BlobDB.
693        BlobDbMultigetMicros("rocksdb.blobdb.multiget.micros"),
694        /// BlobDB Seek/SeekToFirst/SeekToLast/SeekForPrev latency. Only applicable to
695        /// legacy BlobDB.
696        BlobDbSeekMicros("rocksdb.blobdb.seek.micros"),
697        /// BlobDB Next latency. Only applicable to legacy BlobDB.
698        BlobDbNextMicros("rocksdb.blobdb.next.micros"),
699        /// BlobDB Prev latency. Only applicable to legacy BlobDB.
700        BlobDbPrevMicros("rocksdb.blobdb.prev.micros"),
701        /// Blob file write latency.
702        BlobDbBlobFileWriteMicros("rocksdb.blobdb.blob.file.write.micros"),
703        /// Blob file read latency.
704        BlobDbBlobFileReadMicros("rocksdb.blobdb.blob.file.read.micros"),
705        /// Blob file sync latency.
706        BlobDbBlobFileSyncMicros("rocksdb.blobdb.blob.file.sync.micros"),
707        /// BlobDB compression time.
708        BlobDbCompressionMicros("rocksdb.blobdb.compression.micros"),
709        /// BlobDB decompression time.
710        BlobDbDecompressionMicros("rocksdb.blobdb.decompression.micros"),
711        /// Time spent flushing memtable to disk
712        FlushTime("rocksdb.db.flush.micros"),
713        SstBatchSize("rocksdb.sst.batch.size"),
714        /// MultiGet stats logged per level
715        /// Num of index and filter blocks read from file system per level.
716        NumIndexAndFilterBlocksReadPerLevel("rocksdb.num.index.and.filter.blocks.read.per.level"),
717        /// Num of sst files read from file system per level.
718        NumSstReadPerLevel("rocksdb.num.sst.read.per.level"),
719        /// Error handler statistics
720        ErrorHandlerAutoresumeRetryCount("rocksdb.error.handler.autoresume.retry.count"),
721        /// Stats related to asynchronous read requests.
722        AsyncReadBytes("rocksdb.async.read.bytes"),
723        PollWaitMicros("rocksdb.poll.wait.micros"),
724        /// Number of prefetched bytes discarded by RocksDB.
725        PrefetchedBytesDiscarded("rocksdb.prefetched.bytes.discarded"),
726        /// Number of IOs issued in parallel in a MultiGet batch
727        MultigetIoBatchSize("rocksdb.multiget.io.batch.size"),
728        /// Number of levels requiring IO for MultiGet
729        NumLevelReadPerMultiget("rocksdb.num.level.read.per.multiget"),
730        /// Wait time for aborting async read in FilePrefetchBuffer destructor
731        AsyncPrefetchAbortMicros("rocksdb.async.prefetch.abort.micros"),
732        /// Number of bytes read for RocksDB's prefetching contents (as opposed to file
733        /// system's prefetch) from the end of SST table during block based table open
734        TableOpenPrefetchTailReadBytes("rocksdb.table.open.prefetch.tail.read.bytes"),
735    }
736}
737
738pub struct HistogramData {
739    pub(crate) inner: *mut ffi::rocksdb_statistics_histogram_data_t,
740}
741
742impl HistogramData {
743    pub fn new() -> HistogramData {
744        HistogramData::default()
745    }
746    pub fn median(&self) -> f64 {
747        unsafe { ffi::rocksdb_statistics_histogram_data_get_median(self.inner) }
748    }
749    pub fn average(&self) -> f64 {
750        unsafe { ffi::rocksdb_statistics_histogram_data_get_average(self.inner) }
751    }
752    pub fn p95(&self) -> f64 {
753        unsafe { ffi::rocksdb_statistics_histogram_data_get_p95(self.inner) }
754    }
755    pub fn p99(&self) -> f64 {
756        unsafe { ffi::rocksdb_statistics_histogram_data_get_p99(self.inner) }
757    }
758    pub fn max(&self) -> f64 {
759        unsafe { ffi::rocksdb_statistics_histogram_data_get_max(self.inner) }
760    }
761    pub fn min(&self) -> f64 {
762        unsafe { ffi::rocksdb_statistics_histogram_data_get_min(self.inner) }
763    }
764    pub fn sum(&self) -> u64 {
765        unsafe { ffi::rocksdb_statistics_histogram_data_get_sum(self.inner) }
766    }
767    pub fn count(&self) -> u64 {
768        unsafe { ffi::rocksdb_statistics_histogram_data_get_count(self.inner) }
769    }
770    pub fn std_dev(&self) -> f64 {
771        unsafe { ffi::rocksdb_statistics_histogram_data_get_std_dev(self.inner) }
772    }
773}
774
775impl Default for HistogramData {
776    fn default() -> Self {
777        let histogram_data_inner = unsafe { ffi::rocksdb_statistics_histogram_data_create() };
778        assert!(
779            !histogram_data_inner.is_null(),
780            "Could not create RocksDB histogram data"
781        );
782
783        Self {
784            inner: histogram_data_inner,
785        }
786    }
787}
788
789impl Drop for HistogramData {
790    fn drop(&mut self) {
791        unsafe {
792            ffi::rocksdb_statistics_histogram_data_destroy(self.inner);
793        }
794    }
795}
796
797#[test]
798fn sanity_checks() {
799    let want = "rocksdb.async.read.bytes";
800    assert_eq!(want, Histogram::AsyncReadBytes.name());
801
802    let want = "rocksdb.block.cache.index.miss";
803    assert_eq!(want, Ticker::BlockCacheIndexMiss.to_string());
804
805    // assert enum lengths
806    assert_eq!(Ticker::iter().count(), 215 /* TICKER_ENUM_MAX */);
807    assert_eq!(Histogram::iter().count(), 60 /* HISTOGRAM_ENUM_MAX */);
808}