From 51480e6b358a0ddf95bf374061e38334a12d80a5 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Wed, 8 Jul 2026 14:58:07 +0200 Subject: [PATCH] add 'index du ' --- cmd/index.go | 22 ++++++++++++++ pkg/es/index.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/cmd/index.go b/cmd/index.go index 67f19e9..09fc656 100644 --- a/cmd/index.go +++ b/cmd/index.go @@ -41,6 +41,7 @@ func Index(conf *cfg.Config) *cli.Command { IndexClose(conf), IndexFields(conf), IndexIlm(conf), + IndexDu(conf), // sub commands IndexAlias(conf), @@ -277,3 +278,24 @@ func IndexIlm(conf *cfg.Config) *cli.Command { }, } } + +func IndexDu(conf *cfg.Config) *cli.Command { + return &cli.Command{ + Name: "du", + Usage: "show index disk usage", + UsageText: "index du ", + + ShellComplete: func(ctx context.Context, cmd *cli.Command) { + complete(conf, cmd, Cindex) + }, + + Action: func(ctx context.Context, cmd *cli.Command) error { + index := cmd.Args().Get(0) + if index == "" { + return errors.New("no index specified") + } + + return es.IndexDiskusage(conf, index) + }, + } +} diff --git a/pkg/es/index.go b/pkg/es/index.go index 7929a7e..e1ab0f7 100644 --- a/pkg/es/index.go +++ b/pkg/es/index.go @@ -18,6 +18,8 @@ package es import ( "context" + "encoding/json" + "errors" "fmt" "log/slog" "regexp" @@ -28,6 +30,7 @@ import ( "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" + "github.com/charmbracelet/lipgloss" "github.com/elastic/go-elasticsearch/v9/typedapi/cat/indices" "github.com/elastic/go-elasticsearch/v9/typedapi/esdsl" "github.com/elastic/go-elasticsearch/v9/typedapi/types/enums/healthstatus" @@ -306,3 +309,79 @@ func IndexFields(conf *cfg.Config, index string) error { return nil } + +type Diskusage struct { + Total int64 `json:"total_in_bytes"` + Points int64 `json:"points_in_bytes"` + Norms int64 `json:"norms_in_bytes"` + TermVectors int64 `json:"term_vectors_in_bytes"` + KnnVectors int64 `json:"knn_vectors_in_bytes"` + BloomFilter int64 `json:"bloom_filter_in_bytes"` +} + +type IndexDiskUsage struct { + AllFields Diskusage `json:"all_fields"` + Fields map[string]Diskusage `json:"fields"` +} + +type ResIndexDiskUsage map[string]IndexDiskUsage + +func IndexDiskusage(conf *cfg.Config, index string) error { + var bold = lipgloss.NewStyle().Bold(true) + + res, err := conf.DefaultCluster.ES().Indices.DiskUsage(index). + RunExpensiveTasks(true). + Do(context.Background()) + if err != nil { + return fmt.Errorf("failed to retrieve index disk usage: %w", esErrorString(err)) + } + + dures := ResIndexDiskUsage{} + if err := json.Unmarshal(res, &dures); err != nil { + return fmt.Errorf("failed to unmarshal disk usage response: %w", err) + } + + du, exists := dures[index] + if !exists { + return errors.New("no disk usage reported for index") + } + + table := printer.NewTableEmpty(conf). + WithHeaders("field", "bloom filter", "norms", "points", "term vectors", "knn vectors", "total") + + for name, field := range du.Fields { + if strings.HasPrefix(name, "_") || strings.HasSuffix(name, ".keyword") { + continue + } + + table.AddRow( + name, + printer.Bytes(field.BloomFilter), + printer.Bytes(field.Norms), + printer.Bytes(field.Points), + printer.Bytes(field.TermVectors), + printer.Bytes(field.KnnVectors), + printer.Bytes(field.Total), + ) + } + + all := du.AllFields + + table.Sort() + + table.AddRowLate( + bold.Render("Summary"), + printer.Bytes(all.BloomFilter), + printer.Bytes(all.Norms), + printer.Bytes(all.Points), + printer.Bytes(all.TermVectors), + printer.Bytes(all.KnnVectors), + printer.Bytes(all.Total), + ) + + if err := table.Print(); err != nil { + return err + } + + return nil +}