func (m *bloomFilterMetrics) collectors() []prometheus.Collector {
	return []prometheus.Collector{
		m.Useful,
		m.FullPositive,
		m.FullTruePositive,
	}
}
collectors satisfies the prom.PrometheusCollector interface.
package rocks
import (
	"fmt"
	"strconv"
	"github.com/bbva/qed/rocksdb"
	"github.com/bbva/qed/storage"
	"github.com/prometheus/client_golang/prometheus"
)
const namespace = "qed_storage"
const blockCacheSubsystem = "block"   
const filterSubsystem = "filter"      
const memtableSubsystem = "memtable"  
const getSubsystem = "get"            
const ioSubsystem = "io"              
const compressSybsystem = "compress"  
type rocksDBMetrics struct {
	*blockCacheMetrics
	*bloomFilterMetrics
	*memtableMetrics
	*getsMetrics
	*ioMetrics
	*compressMetrics
	tables []*perTableMetrics
}
func newRocksDBMetrics(store *RocksDBStore) *rocksDBMetrics {
	tables := make([]*perTableMetrics, 0)
	tables = append(tables, newPerTableMetrics(storage.HyperTable, store))
	tables = append(tables, newPerTableMetrics(storage.HistoryTable, store))
	tables = append(tables, newPerTableMetrics(storage.FSMStateTable, store))
	return &rocksDBMetrics{
		blockCacheMetrics:  newBlockCacheMetrics(store.stats, store.blockCache),
		bloomFilterMetrics: newBloomFilterMetrics(store.stats),
		memtableMetrics:    newMemtableMetrics(store.stats),
		getsMetrics:        newGetsMetrics(store.stats),
		ioMetrics:          newIOMetrics(store.stats),
		compressMetrics:    newCompressMetrics(store.stats),
		tables:             tables,
	}
}
func (m *rocksDBMetrics) collectors() []prometheus.Collector {
	var collectors []prometheus.Collector
	collectors = append(collectors, m.blockCacheMetrics.collectors()...)
	collectors = append(collectors, m.bloomFilterMetrics.collectors()...)
	collectors = append(collectors, m.memtableMetrics.collectors()...)
	collectors = append(collectors, m.getsMetrics.collectors()...)
	collectors = append(collectors, m.ioMetrics.collectors()...)
	collectors = append(collectors, m.compressMetrics.collectors()...)
	for _, table := range m.tables {
		collectors = append(collectors, table.collectors()...)
	}
	return collectors
}
type blockCacheMetrics struct {
	Miss              prometheus.GaugeFunc
	Hit               prometheus.GaugeFunc
	Add               prometheus.GaugeFunc
	AddFailures       prometheus.GaugeFunc
	IndexMiss         prometheus.GaugeFunc
	IndexHit          prometheus.GaugeFunc
	IndexAdd          prometheus.GaugeFunc
	IndexBytesInsert  prometheus.GaugeFunc
	IndexBytesEvict   prometheus.GaugeFunc
	FilterMiss        prometheus.GaugeFunc
	FilterHit         prometheus.GaugeFunc
	FilterAdd         prometheus.GaugeFunc
	FilterBytesInsert prometheus.GaugeFunc
	FilterBytesEvict  prometheus.GaugeFunc
	DataMiss          prometheus.GaugeFunc
	DataHit           prometheus.GaugeFunc
	DataAdd           prometheus.GaugeFunc
	DataBytesInsert   prometheus.GaugeFunc
	BytesRead         prometheus.GaugeFunc
	BytesWrite        prometheus.GaugeFunc
	Usage             prometheus.GaugeFunc
	PinnedUsage       prometheus.GaugeFunc
}
func newBlockCacheMetrics(stats *rocksdb.Statistics, cache *rocksdb.Cache) *blockCacheMetrics {
	return &blockCacheMetrics{
		Miss: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_miss",
				Help:      "Block cache misses.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheMiss),
		),
		Hit: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_hit",
				Help:      "Block cache hits.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheHit),
		),
		Add: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_add",
				Help:      "Block cache adds.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheAdd),
		),
		AddFailures: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_add_failures",
				Help:      "Block cache add failures.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheAddFailures),
		),
		IndexMiss: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_index_miss",
				Help:      "Block cache index misses.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheIndexMiss),
		),
		IndexHit: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_index_hit",
				Help:      "Block cache index hits.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheIndexHit),
		),
		IndexAdd: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_index_add",
				Help:      "Block cache index adds.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheIndexAdd),
		),
		IndexBytesInsert: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_index_bytes_insert",
				Help:      "Block cache index bytes inserted.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheIndexBytesInsert),
		),
		IndexBytesEvict: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_index_bytes_evict",
				Help:      "Block cache index bytes evicted.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheIndexBytesEvict),
		),
		FilterMiss: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_filter_miss",
				Help:      "Block cache filter misses.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheFilterMiss),
		),
		FilterHit: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_filter_hit",
				Help:      "Block cache filter hits.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheFilterHit),
		),
		FilterAdd: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_filter_add",
				Help:      "Block cache filter adds.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheFilterAdd),
		),
		FilterBytesInsert: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_filter_bytes_insert",
				Help:      "Block cache filter bytes inserted.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheFilterBytesInsert),
		),
		FilterBytesEvict: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_filter_bytes_evict",
				Help:      "Block cache filter bytes evicted.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheFilterBytesEvict),
		),
		DataMiss: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_data_miss",
				Help:      "Block cache data misses.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheDataMiss),
		),
		DataHit: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_data_hit",
				Help:      "Block cache data hits.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheDataHit),
		),
		DataAdd: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_data_add",
				Help:      "Block cache data adds.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheDataAdd),
		),
		DataBytesInsert: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_data_bytes_insert",
				Help:      "Block cache data bytes inserted.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheDataBytesInsert),
		),
		BytesRead: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_bytes_read",
				Help:      "Block cache bytes read.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheBytesRead),
		),
		BytesWrite: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_bytes_write",
				Help:      "Block cache bytes written.",
			},
			extractMetric(stats, rocksdb.TickerBlockCacheBytesWrite),
		),
		Usage: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_memory_usage",
				Help:      "Block cache memory usage.",
			},
			func() float64 {
				return float64(cache.GetUsage())
			},
		),
		PinnedUsage: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: blockCacheSubsystem,
				Name:      "cache_pinned_memory_usage",
				Help:      "Block cache pinned memory usage.",
			},
			func() float64 {
				return float64(cache.GetPinnedUsage())
			},
		),
	}
}
func (m *blockCacheMetrics) collectors() []prometheus.Collector {
	return []prometheus.Collector{
		m.Miss,
		m.Hit,
		m.Add,
		m.AddFailures,
		m.IndexMiss,
		m.IndexHit,
		m.IndexAdd,
		m.IndexBytesInsert,
		m.IndexBytesEvict,
		m.FilterMiss,
		m.FilterHit,
		m.FilterAdd,
		m.FilterBytesInsert,
		m.FilterBytesEvict,
		m.DataMiss,
		m.DataHit,
		m.DataAdd,
		m.DataBytesInsert,
		m.BytesRead,
		m.BytesWrite,
		m.Usage,
		m.PinnedUsage,
	}
}
type bloomFilterMetrics struct {
	Useful           prometheus.GaugeFunc
	FullPositive     prometheus.GaugeFunc
	FullTruePositive prometheus.GaugeFunc
}
func newBloomFilterMetrics(stats *rocksdb.Statistics) *bloomFilterMetrics {
	return &bloomFilterMetrics{
		Useful: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: filterSubsystem,
				Name:      "useful",
				Help:      "Number of times bloom filter avoided reads.",
			},
			extractMetric(stats, rocksdb.TickerBloomFilterUseful),
		),
		FullPositive: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: filterSubsystem,
				Name:      "full_positive",
				Help:      "Number of times bloom fullfilter did not avoid reads.",
			},
			extractMetric(stats, rocksdb.TickerBloomFilterFullPositive),
		),
		FullTruePositive: prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Subsystem: filterSubsystem,
				Name:      "full_true_positive",
				Help:      "Number of times bloom fullfilter did not avoid reads and data actually exist.",
			},
			extractMetric(stats, rocksdb.TickerBloomFilterFullTruePositive),
		),
	}
}