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:
@@ -0,0 +1,58 @@
|
||||
// Command ingothttp serves a minimal HTTP query API for an ingot database.
|
||||
//
|
||||
// Endpoints:
|
||||
//
|
||||
// GET /api/v1/query_range?query={name}&start={unix_ms}&end={unix_ms}
|
||||
// POST /api/v1/read (JSON ReadRequest body)
|
||||
// GET /api/v1/status (DB summary stats)
|
||||
//
|
||||
// This is a demo/bridge for Grafana integration, not a full PromQL engine.
|
||||
// The query parameter is a metric name (matched as __name__=<query>).
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"git.dvdt.dev/david/ingot"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
dataDir = flag.String("data", "./data", "ingot data directory")
|
||||
addr = flag.String("addr", ":9001", "HTTP listen address")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
db, err := ingot.Open(*dataDir, ingot.Options{})
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open db: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
h := newHandler(db)
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/api/v1/query_range", h.queryRange)
|
||||
mux.HandleFunc("/api/v1/read", h.read)
|
||||
mux.HandleFunc("/api/v1/status", h.status)
|
||||
|
||||
srv := &http.Server{Addr: *addr, Handler: mux}
|
||||
|
||||
go func() {
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sig
|
||||
fmt.Fprintln(os.Stderr, "\nshutting down...")
|
||||
srv.Close()
|
||||
}()
|
||||
|
||||
log.Printf("ingothttp listening on %s (data: %s)", *addr, *dataDir)
|
||||
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user