ingotctl, HTTP layer, and self-instrumentation

Add cmd/ingotctl with four subcommands: blocks (list with stats),
inspect (series/postings dump), chunks (decode raw samples by ref), and
fsck (CRC and index integrity validation across all blocks).

Add cmd/ingothttp with JSON query endpoints: /api/v1/query_range
(Prometheus-style matrix response), /api/v1/read (matcher-based read
requests), and /epi/v1/status (DB stats snapshot). Uses JSON instead of
protobuf to maintain zero dependencies.

Add self-instrumentation via the normal Appender path so metrics are
queryable with the same API: ingot_head_series,
ingot_head_chunks_active, ingot_blocks_total, ingot_compactions_total,
ingot_wal_fsync_duration_seconds.

Supporting changes: block.Validate() and block.ReadMeta() exports,
Head.Stats() for series/chunk counts, WAL.LastSyncDuration() with timed
fsync tracking, DB.Stats() for the HTTP status endpoint.
This commit is contained in:
2026-07-04 17:40:50 -04:00
parent 0356f2e082
commit 30a93a868e
12 changed files with 1878 additions and 2 deletions
+26
View File
@@ -272,3 +272,29 @@ func (h *Head) AllPostings() []uint64 {
func (h *Head) DataDir() string {
return h.dataDir
}
// Stats returns a snapshot of head statistics.
func (h *Head) Stats() HeadStats {
var s HeadStats
h.series.forEach(func(ms *memSeries) {
s.NumSeries++
ms.mu.Lock()
if ms.chunk != nil && ms.chunk.NumSamples() > 0 {
s.NumActiveChunks++
}
s.NumActiveChunks += len(ms.sealed)
ms.mu.Unlock()
})
return s
}
// HeadStats holds a snapshot of head statistics.
type HeadStats struct {
NumSeries int
NumActiveChunks int
}
// WALSyncDuration returns the duration of the most recent WAL fsync in seconds.
func (h *Head) WALSyncDuration() float64 {
return h.wal.LastSyncDuration()
}