package frostdb

import (
	
	
	

	filewal 

	
)

var (
	descTxHighWatermark = prometheus.NewDesc(
		"frostdb_tx_high_watermark",
		"The highest transaction number that has been released to be read",
		[]string{"db"}, nil,
	)
	descActiveBlockSize = prometheus.NewDesc(
		"frostdb_table_active_block_size",
		"Size of the active table block in bytes.",
		[]string{"db", "table"}, nil,
	)
)

// collector is a custom prometheus collector that exports metrics from live
// databases and tables.
type collector struct {
	s *ColumnStore
}

var _ prometheus.Collector = (*collector)(nil)

func ( *collector) ( chan<- *prometheus.Desc) {
	 <- descTxHighWatermark
	 <- descActiveBlockSize
}

func ( *collector) ( chan<- prometheus.Metric) {
	for ,  := range .s.DBs() {
		,  := .s.GetDB()
		if  != nil {
			continue
		}
		 <- prometheus.MustNewConstMetric(descTxHighWatermark, prometheus.GaugeValue, float64(.HighWatermark()), )
		for ,  := range .TableNames() {
			,  := .GetTable()
			if  != nil {
				continue
			}
			 := .ActiveBlock()
			if  == nil {
				continue
			}
			 <- prometheus.MustNewConstMetric(descActiveBlockSize, prometheus.GaugeValue, float64(.Size()), , )
		}
	}
}

// globalMetrics defines the store-level metrics registered at instantiation.
// Most metrics are not directly accessed, and instead provided to components
// at instantiation time with preset labels.
type globalMetrics struct {
	shutdownDuration  prometheus.Histogram
	shutdownStarted   prometheus.Counter
	shutdownCompleted prometheus.Counter
	dbMetrics         struct {
		snapshotMetrics struct {
			snapshotsTotal            *prometheus.CounterVec
			snapshotFileSizeBytes     *prometheus.GaugeVec
			snapshotDurationHistogram *prometheus.HistogramVec
		}
		walMetrics struct {
			bytesWritten          *prometheus.CounterVec
			entriesWritten        *prometheus.CounterVec
			appends               *prometheus.CounterVec
			entryBytesRead        *prometheus.CounterVec
			entriesRead           *prometheus.CounterVec
			segmentRotations      *prometheus.CounterVec
			entriesTruncated      *prometheus.CounterVec
			truncations           *prometheus.CounterVec
			lastSegmentAgeSeconds *prometheus.GaugeVec
		}
		fileWalMetrics struct {
			failedLogs            *prometheus.CounterVec
			lastTruncationAt      *prometheus.GaugeVec
			walRepairs            *prometheus.CounterVec
			walRepairsLostRecords *prometheus.CounterVec
			walCloseTimeouts      *prometheus.CounterVec
			walQueueSize          *prometheus.GaugeVec
		}
	}
	tableMetrics struct {
		blockPersisted       *prometheus.CounterVec
		blockRotated         *prometheus.CounterVec
		rowsInserted         *prometheus.CounterVec
		rowBytesInserted     *prometheus.CounterVec
		zeroRowsInserted     *prometheus.CounterVec
		rowInsertSize        *prometheus.HistogramVec
		lastCompletedBlockTx *prometheus.GaugeVec
		numParts             *prometheus.GaugeVec
		indexMetrics         struct {
			compactions        *prometheus.CounterVec
			levelSize          *prometheus.GaugeVec
			compactionDuration *prometheus.HistogramVec
		}
	}
}

func makeLabelsForDBMetric( ...string) []string {
	return append([]string{"db"}, ...)
}

func makeLabelsForTablesMetrics( ...string) []string {
	return append([]string{"db", "table"}, ...)
}

func makeAndRegisterGlobalMetrics( prometheus.Registerer) globalMetrics {
	 := globalMetrics{
		shutdownDuration: promauto.With().NewHistogram(prometheus.HistogramOpts{
			Name: "frostdb_shutdown_duration",
			Help: "time it takes for the columnarstore to complete a full shutdown.",
		}),
		shutdownStarted: promauto.With().NewCounter(prometheus.CounterOpts{
			Name: "frostdb_shutdown_started",
			Help: "Indicates a shutdown of the columnarstore has started.",
		}),
		shutdownCompleted: promauto.With().NewCounter(prometheus.CounterOpts{
			Name: "frostdb_shutdown_completed",
			Help: "Indicates a shutdown of the columnarstore has completed.",
		}),
	}

	// DB metrics.
	{
		// Snapshot metrics.
		{
			 := prometheus.WrapRegistererWithPrefix("frostdb_snapshot_", )
			.dbMetrics.snapshotMetrics.snapshotsTotal = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "total",
				Help: "Total number of snapshots",
			}, makeLabelsForDBMetric("success"))
			.dbMetrics.snapshotMetrics.snapshotFileSizeBytes = promauto.With().NewGaugeVec(prometheus.GaugeOpts{
				Name: "file_size_bytes",
				Help: "Size of snapshots in bytes",
			}, makeLabelsForDBMetric())
			.dbMetrics.snapshotMetrics.snapshotDurationHistogram = promauto.With().NewHistogramVec(prometheus.HistogramOpts{
				Name:    "duration_seconds",
				Help:    "Duration of snapshots in seconds",
				Buckets: prometheus.ExponentialBucketsRange(1, 60, 5),
			}, makeLabelsForDBMetric())
		}
		// WAL metrics.
		{
			 := prometheus.WrapRegistererWithPrefix("frostdb_wal_", )
			.dbMetrics.walMetrics.bytesWritten = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "entry_bytes_written",
				Help: "entry_bytes_written counts the bytes of log entry after encoding." +
					" Actual bytes written to disk might be slightly higher as it" +
					" includes headers and index entries.",
			}, makeLabelsForDBMetric())
			.dbMetrics.walMetrics.entriesWritten = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "entries_written",
				Help: "entries_written counts the number of entries written.",
			}, makeLabelsForDBMetric())
			.dbMetrics.walMetrics.appends = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "appends",
				Help: "appends counts the number of calls to StoreLog(s) i.e." +
					" number of batches of entries appended.",
			}, makeLabelsForDBMetric())
			.dbMetrics.walMetrics.entryBytesRead = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "entry_bytes_read",
				Help: "entry_bytes_read counts the bytes of log entry read from" +
					" segments before decoding. actual bytes read from disk might be higher" +
					" as it includes headers and index entries and possible secondary reads" +
					" for large entries that don't fit in buffers.",
			}, makeLabelsForDBMetric())
			.dbMetrics.walMetrics.entriesRead = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "entries_read",
				Help: "entries_read counts the number of calls to get_log.",
			}, makeLabelsForDBMetric())
			.dbMetrics.walMetrics.segmentRotations = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "segment_rotations",
				Help: "segment_rotations counts how many times we move to a new segment file.",
			}, makeLabelsForDBMetric())
			.dbMetrics.walMetrics.entriesTruncated = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "entries_truncated_total",
				Help: "entries_truncated counts how many log entries have been truncated" +
					" from the front or back.",
			}, makeLabelsForDBMetric("type"))
			.dbMetrics.walMetrics.truncations = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "truncations_total",
				Help: "truncations is the number of truncate calls categorized by whether" +
					" the call was successful or not.",
			}, makeLabelsForDBMetric("type", "success"))
			.dbMetrics.walMetrics.lastSegmentAgeSeconds = promauto.With().NewGaugeVec(prometheus.GaugeOpts{
				Name: "last_segment_age_seconds",
				Help: "last_segment_age_seconds is a gauge that is set each time we" +
					" rotate a segment and describes the number of seconds between when" +
					" that segment file was first created and when it was sealed. this" +
					" gives a rough estimate how quickly writes are filling the disk.",
			}, makeLabelsForDBMetric())
		}
		// FileWAL metrics.
		{
			 := prometheus.WrapRegistererWithPrefix("frostdb_wal_", )
			.dbMetrics.fileWalMetrics.failedLogs = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "failed_logs_total",
				Help: "Number of failed WAL logs",
			}, makeLabelsForDBMetric())
			.dbMetrics.fileWalMetrics.lastTruncationAt = promauto.With().NewGaugeVec(prometheus.GaugeOpts{
				Name: "last_truncation_at",
				Help: "The last transaction the WAL was truncated to",
			}, makeLabelsForDBMetric())
			.dbMetrics.fileWalMetrics.walRepairs = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "repairs_total",
				Help: "The number of times the WAL had to be repaired (truncated) due to corrupt records",
			}, makeLabelsForDBMetric())
			.dbMetrics.fileWalMetrics.walRepairsLostRecords = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "repairs_lost_records_total",
				Help: "The number of WAL records lost due to WAL repairs (truncations)",
			}, makeLabelsForDBMetric())
			.dbMetrics.fileWalMetrics.walCloseTimeouts = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "close_timeouts_total",
				Help: "The number of times the WAL failed to close due to a timeout",
			}, makeLabelsForDBMetric())
			.dbMetrics.fileWalMetrics.walQueueSize = promauto.With().NewGaugeVec(prometheus.GaugeOpts{
				Name: "queue_size",
				Help: "The number of unprocessed requests in the WAL queue",
			}, makeLabelsForDBMetric())
		}
	}

	// Table metrics.
	{
		 := prometheus.WrapRegistererWithPrefix("frostdb_table_", )
		.tableMetrics.blockPersisted = promauto.With().NewCounterVec(prometheus.CounterOpts{
			Name: "blocks_persisted_total",
			Help: "Number of table blocks that have been persisted.",
		}, makeLabelsForTablesMetrics())
		.tableMetrics.blockRotated = promauto.With().NewCounterVec(prometheus.CounterOpts{
			Name: "blocks_rotated_total",
			Help: "Number of table blocks that have been rotated.",
		}, makeLabelsForTablesMetrics())
		.tableMetrics.rowsInserted = promauto.With().NewCounterVec(prometheus.CounterOpts{
			Name: "rows_inserted_total",
			Help: "Number of rows inserted into table.",
		}, makeLabelsForTablesMetrics())
		.tableMetrics.rowBytesInserted = promauto.With().NewCounterVec(prometheus.CounterOpts{
			Name: "row_bytes_inserted_total",
			Help: "Number of bytes inserted into table.",
		}, makeLabelsForTablesMetrics())
		.tableMetrics.zeroRowsInserted = promauto.With().NewCounterVec(prometheus.CounterOpts{
			Name: "zero_rows_inserted_total",
			Help: "Number of times it was attempted to insert zero rows into the table.",
		}, makeLabelsForTablesMetrics())
		.tableMetrics.rowInsertSize = promauto.With().NewHistogramVec(prometheus.HistogramOpts{
			Name:    "row_insert_size",
			Help:    "Size of batch inserts into table.",
			Buckets: prometheus.ExponentialBuckets(1, 2, 10),
		}, makeLabelsForTablesMetrics())
		.tableMetrics.lastCompletedBlockTx = promauto.With().NewGaugeVec(prometheus.GaugeOpts{
			Name: "last_completed_block_tx",
			Help: "Last completed block transaction.",
		}, makeLabelsForTablesMetrics())
		.tableMetrics.numParts = promauto.With().NewGaugeVec(prometheus.GaugeOpts{
			Name: "num_parts",
			Help: "Number of parts currently active.",
		}, makeLabelsForTablesMetrics())

		// LSM metrics.
		{
			 := prometheus.WrapRegistererWithPrefix("frostdb_lsm_", )
			.tableMetrics.indexMetrics.compactions = promauto.With().NewCounterVec(prometheus.CounterOpts{
				Name: "compactions_total",
				Help: "The total number of compactions that have occurred.",
			}, makeLabelsForTablesMetrics("level"))

			.tableMetrics.indexMetrics.levelSize = promauto.With().NewGaugeVec(prometheus.GaugeOpts{
				Name: "level_size_bytes",
				Help: "The size of the level in bytes.",
			}, makeLabelsForTablesMetrics("level"))

			.tableMetrics.indexMetrics.compactionDuration = promauto.With().NewHistogramVec(prometheus.HistogramOpts{
				Name:                        "compaction_total_duration_seconds",
				Help:                        "Total compaction duration",
				NativeHistogramBucketFactor: 1.1,
			}, makeLabelsForTablesMetrics())
		}
	}
	return 
}

type snapshotMetrics struct {
	snapshotsTotal            *prometheus.CounterVec
	snapshotFileSizeBytes     prometheus.Gauge
	snapshotDurationHistogram prometheus.Observer
}

func ( globalMetrics) ( string) snapshotMetrics {
	return snapshotMetrics{
		snapshotsTotal:            .dbMetrics.snapshotMetrics.snapshotsTotal.MustCurryWith(prometheus.Labels{"db": }),
		snapshotFileSizeBytes:     .dbMetrics.snapshotMetrics.snapshotFileSizeBytes.WithLabelValues(),
		snapshotDurationHistogram: .dbMetrics.snapshotMetrics.snapshotDurationHistogram.WithLabelValues(),
	}
}

type tableMetricsProvider struct {
	dbName string
	m      globalMetrics
}

type tableMetrics struct {
	blockPersisted       prometheus.Counter
	blockRotated         prometheus.Counter
	rowsInserted         prometheus.Counter
	rowBytesInserted     prometheus.Counter
	zeroRowsInserted     prometheus.Counter
	rowInsertSize        prometheus.Observer
	lastCompletedBlockTx prometheus.Gauge
	numParts             prometheus.Gauge

	indexMetrics index.LSMMetrics
}

func ( tableMetricsProvider) ( string) tableMetrics {
	return tableMetrics{
		blockPersisted:       .m.tableMetrics.blockPersisted.WithLabelValues(.dbName, ),
		blockRotated:         .m.tableMetrics.blockRotated.WithLabelValues(.dbName, ),
		rowsInserted:         .m.tableMetrics.rowsInserted.WithLabelValues(.dbName, ),
		rowBytesInserted:     .m.tableMetrics.rowBytesInserted.WithLabelValues(.dbName, ),
		zeroRowsInserted:     .m.tableMetrics.zeroRowsInserted.WithLabelValues(.dbName, ),
		rowInsertSize:        .m.tableMetrics.rowInsertSize.WithLabelValues(.dbName, ),
		lastCompletedBlockTx: .m.tableMetrics.lastCompletedBlockTx.WithLabelValues(.dbName, ),
		numParts:             .m.tableMetrics.numParts.WithLabelValues(.dbName, ),
		indexMetrics: index.LSMMetrics{
			Compactions:        .m.tableMetrics.indexMetrics.compactions.MustCurryWith(prometheus.Labels{"db": .dbName, "table": }),
			LevelSize:          .m.tableMetrics.indexMetrics.levelSize.MustCurryWith(prometheus.Labels{"db": .dbName, "table": }),
			CompactionDuration: .m.tableMetrics.indexMetrics.compactionDuration.WithLabelValues(.dbName, ),
		},
	}
}

func ( globalMetrics) ( string) *wal.Metrics {
	return &wal.Metrics{
		BytesWritten:          .dbMetrics.walMetrics.bytesWritten.WithLabelValues(),
		EntriesWritten:        .dbMetrics.walMetrics.entriesWritten.WithLabelValues(),
		Appends:               .dbMetrics.walMetrics.appends.WithLabelValues(),
		EntryBytesRead:        .dbMetrics.walMetrics.entryBytesRead.WithLabelValues(),
		EntriesRead:           .dbMetrics.walMetrics.entriesRead.WithLabelValues(),
		SegmentRotations:      .dbMetrics.walMetrics.segmentRotations.WithLabelValues(),
		EntriesTruncated:      .dbMetrics.walMetrics.entriesTruncated.MustCurryWith(prometheus.Labels{"db": }),
		Truncations:           .dbMetrics.walMetrics.truncations.MustCurryWith(prometheus.Labels{"db": }),
		LastSegmentAgeSeconds: .dbMetrics.walMetrics.lastSegmentAgeSeconds.WithLabelValues(),
	}
}

func ( globalMetrics) ( string) *filewal.Metrics {
	return &filewal.Metrics{
		FailedLogs:            .dbMetrics.fileWalMetrics.failedLogs.WithLabelValues(),
		LastTruncationAt:      .dbMetrics.fileWalMetrics.lastTruncationAt.WithLabelValues(),
		WalRepairs:            .dbMetrics.fileWalMetrics.walRepairs.WithLabelValues(),
		WalRepairsLostRecords: .dbMetrics.fileWalMetrics.walRepairsLostRecords.WithLabelValues(),
		WalCloseTimeouts:      .dbMetrics.fileWalMetrics.walCloseTimeouts.WithLabelValues(),
		WalQueueSize:          .dbMetrics.fileWalMetrics.walQueueSize.WithLabelValues(),
	}
}