From ad156e35442b0fe83a12007257abcebd57097cd5 Mon Sep 17 00:00:00 2001 From: Kyle Deal Date: Sun, 4 Jan 2026 00:37:07 -0500 Subject: [PATCH 1/4] Move CLI root to main.go --- README.md | 3 + mimir_utils/cmd/mimir_utils/main.go | 18 +++ mimir_utils/go.mod | 5 + mimir_utils/internal/analyzer/top_metrics.go | 146 +++++++++++++++++++ mimir_utils/internal/cli/main.go | 39 +++++ mimir_utils/internal/cli/top_metrics.go | 71 +++++++++ mimir_utils/internal/cli/top_metrics_test.go | 29 ++++ 7 files changed, 311 insertions(+) create mode 100644 mimir_utils/cmd/mimir_utils/main.go create mode 100644 mimir_utils/go.mod create mode 100644 mimir_utils/internal/analyzer/top_metrics.go create mode 100644 mimir_utils/internal/cli/main.go create mode 100644 mimir_utils/internal/cli/top_metrics.go create mode 100644 mimir_utils/internal/cli/top_metrics_test.go diff --git a/README.md b/README.md index 0e74270..7f4a5b1 100644 --- a/README.md +++ b/README.md @@ -16,3 +16,6 @@ Rust command-line tool that streamlines and automates pieces of a personal workf ## wkfl-app Tauri desktop application scaffold that complements the wkfl tooling with a GUI experiment. + +## mimir_utils +Go-based command-line utilities for exploring Mimir and Prometheus TSDB blocks. diff --git a/mimir_utils/cmd/mimir_utils/main.go b/mimir_utils/cmd/mimir_utils/main.go new file mode 100644 index 0000000..405b7a6 --- /dev/null +++ b/mimir_utils/cmd/mimir_utils/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "mimir_utils/internal/cli" +) + +func main() { + flag.Usage = cli.RootUsage + + if err := cli.Execute(os.Args[1:]); err != nil { + fmt.Fprintln(os.Stderr, "error:", err) + os.Exit(1) + } +} diff --git a/mimir_utils/go.mod b/mimir_utils/go.mod new file mode 100644 index 0000000..bdaf092 --- /dev/null +++ b/mimir_utils/go.mod @@ -0,0 +1,5 @@ +module mimir_utils + +go 1.25.1 + +require github.com/prometheus/prometheus v0.56.0 diff --git a/mimir_utils/internal/analyzer/top_metrics.go b/mimir_utils/internal/analyzer/top_metrics.go new file mode 100644 index 0000000..fa89740 --- /dev/null +++ b/mimir_utils/internal/analyzer/top_metrics.go @@ -0,0 +1,146 @@ +package analyzer + +import ( + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/tsdb/chunkenc" + "github.com/prometheus/prometheus/tsdb/chunks" + "github.com/prometheus/prometheus/tsdb/index" +) + +// MetricStat captures byte usage information for a metric across a set of blocks. +type MetricStat struct { + Name string + Bytes int64 + Series int + Chunks int +} + +// TopNMetrics walks the provided directory for TSDB blocks and returns the top metrics by bytes used. +func TopNMetrics(root string, limit int) ([]MetricStat, error) { + aggregate := map[string]*MetricStat{} + + blockDirs, err := findBlockDirs(root) + if err != nil { + return nil, err + } + + for _, blockDir := range blockDirs { + if err := accumulateBlock(blockDir, aggregate); err != nil { + return nil, fmt.Errorf("block %s: %w", blockDir, err) + } + } + + stats := make([]MetricStat, 0, len(aggregate)) + for _, stat := range aggregate { + stats = append(stats, *stat) + } + + sort.Slice(stats, func(i, j int) bool { + if stats[i].Bytes == stats[j].Bytes { + return stats[i].Name < stats[j].Name + } + return stats[i].Bytes > stats[j].Bytes + }) + + if limit > 0 && len(stats) > limit { + stats = stats[:limit] + } + + return stats, nil +} + +func findBlockDirs(root string) ([]string, error) { + entries, err := os.ReadDir(root) + if err != nil { + return nil, err + } + + var blocks []string + for _, entry := range entries { + if !entry.IsDir() { + continue + } + dirPath := filepath.Join(root, entry.Name()) + if _, err := os.Stat(filepath.Join(dirPath, "meta.json")); err == nil { + blocks = append(blocks, dirPath) + } + } + + if len(blocks) == 0 { + return nil, fmt.Errorf("no TSDB blocks found in %s", root) + } + + return blocks, nil +} + +func accumulateBlock(blockDir string, aggregate map[string]*MetricStat) error { + indexPath := filepath.Join(blockDir, "index") + chunkDir := filepath.Join(blockDir, "chunks") + + indexReader, err := index.NewFileReader(indexPath) + if err != nil { + return fmt.Errorf("open index: %w", err) + } + defer indexReader.Close() + + pool := chunkenc.NewPool() + chunkReader, err := chunks.NewDirReader(chunkDir, pool) + if err != nil { + return fmt.Errorf("open chunks: %w", err) + } + defer chunkReader.Close() + + name, value := index.AllPostingsKey() + postings, err := indexReader.Postings(name, value) + if err != nil { + return fmt.Errorf("load postings: %w", err) + } + + for postings.Next() { + ref := postings.At() + var lset labels.Labels + var metas []chunks.Meta + + if err := indexReader.Series(ref, &lset, &metas); err != nil { + return fmt.Errorf("read series %d: %w", ref, err) + } + + metricName := lset.Get("__name__") + if metricName == "" { + metricName = "(no_metric_name)" + } + + var seriesBytes int64 + for _, meta := range metas { + chk, err := chunkReader.Chunk(meta.Ref) + if err != nil { + if strings.Contains(err.Error(), "reference") { + return fmt.Errorf("chunk %d: %w", meta.Ref, err) + } + return fmt.Errorf("read chunk %d: %w", meta.Ref, err) + } + seriesBytes += int64(len(chk.Bytes())) + } + + stat, ok := aggregate[metricName] + if !ok { + stat = &MetricStat{Name: metricName} + aggregate[metricName] = stat + } + stat.Bytes += seriesBytes + stat.Series++ + stat.Chunks += len(metas) + } + + if err := postings.Err(); err != nil { + return fmt.Errorf("postings iteration: %w", err) + } + + return nil +} diff --git a/mimir_utils/internal/cli/main.go b/mimir_utils/internal/cli/main.go new file mode 100644 index 0000000..29e5882 --- /dev/null +++ b/mimir_utils/internal/cli/main.go @@ -0,0 +1,39 @@ +package cli + +import ( + "errors" + "flag" + "fmt" +) + +// RootUsage prints a helpful summary of the available subcommands. +func RootUsage() { + fmt.Fprintf(flag.CommandLine.Output(), `mimir_utils is a collection of small tools. + +Usage: + mimir_utils [options] + +Available subcommands: + top-metrics Analyze TSDB blocks and print the metrics using the most bytes. + +`) +} + +// Execute parses the subcommand and invokes it with the provided arguments. +func Execute(args []string) error { + if len(args) == 0 { + RootUsage() + return errors.New("no subcommand specified") + } + + switch args[0] { + case "top-metrics": + return runTopMetrics(args[1:]) + case "help", "-h", "--help": + RootUsage() + return nil + default: + RootUsage() + return fmt.Errorf("unknown subcommand %q", args[0]) + } +} diff --git a/mimir_utils/internal/cli/top_metrics.go b/mimir_utils/internal/cli/top_metrics.go new file mode 100644 index 0000000..010c4d3 --- /dev/null +++ b/mimir_utils/internal/cli/top_metrics.go @@ -0,0 +1,71 @@ +package cli + +import ( + "flag" + "fmt" + "math" + "os" + "text/tabwriter" + + "mimir_utils/internal/analyzer" +) + +func runTopMetrics(args []string) error { + fs := flag.NewFlagSet("top-metrics", flag.ContinueOnError) + dir := fs.String("dir", "", "Directory containing TSDB blocks") + limit := fs.Int("limit", 10, "Number of metrics to display (0 for all)") + + fs.Usage = func() { + fmt.Fprintf(fs.Output(), `Usage: mimir_utils top-metrics [options] + +Options: +`) + fs.PrintDefaults() + } + + if err := fs.Parse(args); err != nil { + return err + } + + if *dir == "" { + fs.Usage() + return fmt.Errorf("the -dir flag is required") + } + + stats, err := analyzer.TopNMetrics(*dir, *limit) + if err != nil { + return err + } + + if len(stats) == 0 { + fmt.Println("No metrics found.") + return nil + } + + w := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0) + fmt.Fprintln(w, "METRIC\tBYTES\tSERIES\tCHUNKS") + for _, stat := range stats { + fmt.Fprintf(w, "%s\t%s\t%d\t%d\n", stat.Name, humanReadableBytes(stat.Bytes), stat.Series, stat.Chunks) + } + return w.Flush() +} + +func humanReadableBytes(bytes int64) string { + if bytes < 1024 { + return fmt.Sprintf("%d B", bytes) + } + + const unit = 1024.0 + units := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB"} + val := float64(bytes) + exp := math.Floor(math.Log(val) / math.Log(unit)) + if int(exp) >= len(units) { + exp = float64(len(units) - 1) + } + + value := val / math.Pow(unit, exp) + if value >= 10 || exp == 0 { + return fmt.Sprintf("%.0f %s", value, units[int(exp)]) + } + return fmt.Sprintf("%.1f %s", value, units[int(exp)]) +} diff --git a/mimir_utils/internal/cli/top_metrics_test.go b/mimir_utils/internal/cli/top_metrics_test.go new file mode 100644 index 0000000..a57bc05 --- /dev/null +++ b/mimir_utils/internal/cli/top_metrics_test.go @@ -0,0 +1,29 @@ +package cli + +import "testing" + +func TestHumanReadableBytes(t *testing.T) { + tests := []struct { + name string + in int64 + out string + }{ + {"zero bytes", 0, "0 B"}, + {"single byte", 1, "1 B"}, + {"just below kibibyte", 1023, "1023 B"}, + {"one kibibyte", 1024, "1.0 KiB"}, + {"fractional kibibyte", 1536, "1.5 KiB"}, + {"ten kibibytes", 10 * 1024, "10 KiB"}, + {"one mebibyte", 1024 * 1024, "1.0 MiB"}, + {"many gibibytes", 25 * 1024 * 1024 * 1024, "25 GiB"}, + {"overflow past units", 1 << 62, "4 PiB"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := humanReadableBytes(tt.in); got != tt.out { + t.Fatalf("humanReadableBytes(%d) = %q, want %q", tt.in, got, tt.out) + } + }) + } +} From b2fa41409e1ae01807d28ee3e24298b8eb9d121e Mon Sep 17 00:00:00 2001 From: Kyle Deal Date: Sun, 4 Jan 2026 00:51:27 -0500 Subject: [PATCH 2/4] Update dependency and simplify byte formatting --- mimir_utils/go.mod | 2 +- mimir_utils/internal/analyzer/top_metrics.go | 8 ++++---- mimir_utils/internal/cli/top_metrics.go | 19 ++++++++----------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/mimir_utils/go.mod b/mimir_utils/go.mod index bdaf092..6a1cd17 100644 --- a/mimir_utils/go.mod +++ b/mimir_utils/go.mod @@ -2,4 +2,4 @@ module mimir_utils go 1.25.1 -require github.com/prometheus/prometheus v0.56.0 +require github.com/prometheus/prometheus/v3 v3.8.1 diff --git a/mimir_utils/internal/analyzer/top_metrics.go b/mimir_utils/internal/analyzer/top_metrics.go index fa89740..bf46680 100644 --- a/mimir_utils/internal/analyzer/top_metrics.go +++ b/mimir_utils/internal/analyzer/top_metrics.go @@ -7,10 +7,10 @@ import ( "sort" "strings" - "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/tsdb/chunkenc" - "github.com/prometheus/prometheus/tsdb/chunks" - "github.com/prometheus/prometheus/tsdb/index" + "github.com/prometheus/prometheus/v3/model/labels" + "github.com/prometheus/prometheus/v3/tsdb/chunkenc" + "github.com/prometheus/prometheus/v3/tsdb/chunks" + "github.com/prometheus/prometheus/v3/tsdb/index" ) // MetricStat captures byte usage information for a metric across a set of blocks. diff --git a/mimir_utils/internal/cli/top_metrics.go b/mimir_utils/internal/cli/top_metrics.go index 010c4d3..b3f76de 100644 --- a/mimir_utils/internal/cli/top_metrics.go +++ b/mimir_utils/internal/cli/top_metrics.go @@ -51,21 +51,18 @@ Options: } func humanReadableBytes(bytes int64) string { - if bytes < 1024 { - return fmt.Sprintf("%d B", bytes) - } - const unit = 1024.0 units := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB"} val := float64(bytes) - exp := math.Floor(math.Log(val) / math.Log(unit)) - if int(exp) >= len(units) { - exp = float64(len(units) - 1) + exp := 0 + + for val >= unit && exp < len(units)-1 { + val /= unit + exp++ } - value := val / math.Pow(unit, exp) - if value >= 10 || exp == 0 { - return fmt.Sprintf("%.0f %s", value, units[int(exp)]) + if val >= 10 || exp == 0 { + return fmt.Sprintf("%.0f %s", val, units[exp]) } - return fmt.Sprintf("%.1f %s", value, units[int(exp)]) + return fmt.Sprintf("%.1f %s", val, units[exp]) } From 40cfccf81c4016ac031d82631c5742267182e272 Mon Sep 17 00:00:00 2001 From: Kyle Deal Date: Sun, 4 Jan 2026 06:05:47 +0000 Subject: [PATCH 3/4] Fix prometheus import --- mimir_utils/go.mod | 22 ++- mimir_utils/go.sum | 170 +++++++++++++++++++ mimir_utils/internal/analyzer/top_metrics.go | 8 +- 3 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 mimir_utils/go.sum diff --git a/mimir_utils/go.mod b/mimir_utils/go.mod index 6a1cd17..fc5a0b4 100644 --- a/mimir_utils/go.mod +++ b/mimir_utils/go.mod @@ -2,4 +2,24 @@ module mimir_utils go 1.25.1 -require github.com/prometheus/prometheus/v3 v3.8.1 +require github.com/prometheus/prometheus v0.308.1 + +require ( + github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dennwc/varint v1.0.0 // indirect + github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.4 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + golang.org/x/exp v0.0.0-20250808145144-a408d31f581a // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/text v0.30.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect +) diff --git a/mimir_utils/go.sum b/mimir_utils/go.sum new file mode 100644 index 0000000..2601d88 --- /dev/null +++ b/mimir_utils/go.sum @@ -0,0 +1,170 @@ +cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4= +cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 h1:5YTBM8QDVIBN3sxBil89WfdAAqDZbyJTgh688DSxX5w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0 h1:wL5IEG5zb7BVv1Kv0Xm92orq+5hB5Nipn3B5tn4Rqfk= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.12.0/go.mod h1:J7MUC/wtRpfGVbQ5sIItY5/FuVWmvzlY21WAOfQnq/I= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk= +github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE= +github.com/aws/aws-sdk-go-v2/config v1.31.17 h1:QFl8lL6RgakNK86vusim14P2k8BFSxjvUkcWLDjgz9Y= +github.com/aws/aws-sdk-go-v2/config v1.31.17/go.mod h1:V8P7ILjp/Uef/aX8TjGk6OHZN6IKPM5YW6S78QnRD5c= +github.com/aws/aws-sdk-go-v2/credentials v1.18.21 h1:56HGpsgnmD+2/KpG0ikvvR8+3v3COCwaF4r+oWwOeNA= +github.com/aws/aws-sdk-go-v2/credentials v1.18.21/go.mod h1:3YELwedmQbw7cXNaII2Wywd+YY58AmLPwX4LzARgmmA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 h1:T1brd5dR3/fzNFAQch/iBKeX07/ffu/cLu+q+RuzEWk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13/go.mod h1:Peg/GBAQ6JDt+RoBf4meB1wylmAipb7Kg2ZFakZTlwk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 h1:a+8/MLcWlIxo1lF9xaGt3J/u3yOZx+CdSveSNwjhD40= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13/go.mod h1:oGnKwIYZ4XttyU2JWxFrwvhF6YKiK/9/wmE3v3Iu9K8= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 h1:HBSI2kDkMdWz4ZM7FjwE7e/pWDEZ+nR95x8Ztet1ooY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13/go.mod h1:YE94ZoDArI7awZqJzBAZ3PDD2zSfuP7w6P2knOzIn8M= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 h1:kDqdFvMY4AtKoACfzIGD8A0+hbT41KTKF//gq7jITfM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13/go.mod h1:lmKuogqSU3HzQCwZ9ZtcqOc5XGMqtDK7OIc2+DxiUEg= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.1 h1:0JPwLz1J+5lEOfy/g0SURC9cxhbQ1lIMHMa+AHZSzz0= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.1/go.mod h1:fKvyjJcz63iL/ftA6RaM8sRCtN4r4zl4tjL3qw5ec7k= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5 h1:OWs0/j2UYR5LOGi88sD5/lhN6TDLG6SfA7CqsQO9zF0= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5/go.mod h1:klO+ejMvYsB4QATfEOIXk8WAEwN4N0aBfJpvC+5SZBo= +github.com/aws/aws-sdk-go-v2/service/sts v1.39.1 h1:mLlUgHn02ue8whiR4BmxxGJLR2gwU6s6ZzJ5wDamBUs= +github.com/aws/aws-sdk-go-v2/service/sts v1.39.1/go.mod h1:E19xDjpzPZC7LS2knI9E6BaRFDK43Eul7vd6rSq2HWk= +github.com/aws/smithy-go v1.23.2 h1:Crv0eatJUQhaManss33hS5r40CG3ZFH+21XSkqMrIUM= +github.com/aws/smithy-go v1.23.2/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= +github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= +github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= +github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853 h1:cLN4IBkmkYZNnk7EAJ0BHIethd+J6LqxFNw5mSiI2bM= +github.com/grafana/regexp v0.0.0-20250905093917-f7b3be9d1853/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= +github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_golang/exp v0.0.0-20251212205219-7ba246a648ca h1:BOxmsLoL2ymn8lXJtorca7N/m+2vDQUDoEtPjf0iAxA= +github.com/prometheus/client_golang/exp v0.0.0-20251212205219-7ba246a648ca/go.mod h1:gndBHh3ZdjBozGcGrjUYjN3UJLRS3l2drALtu4lUt+k= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc= +github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= +github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= +github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/prometheus v0.308.1 h1:ApMNI/3/es3Ze90Z7CMb+wwU2BsSYur0m5VKeqHj7h4= +github.com/prometheus/prometheus v0.308.1/go.mod h1:aHjYCDz9zKRyoUXvMWvu13K9XHOkBB12XrEqibs3e0A= +github.com/prometheus/sigv4 v0.3.0 h1:QIG7nTbu0JTnNidGI1Uwl5AGVIChWUACxn2B/BQ1kms= +github.com/prometheus/sigv4 v0.3.0/go.mod h1:fKtFYDus2M43CWKMNtGvFNHGXnAJJEGZbiYCmVp/F8I= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/exp v0.0.0-20250808145144-a408d31f581a h1:Y+7uR/b1Mw2iSXZ3G//1haIiSElDQZ8KWh0h+sZPG90= +golang.org/x/exp v0.0.0-20250808145144-a408d31f581a/go.mod h1:rT6SFzZ7oxADUDx58pcaKFTcZ+inxAa9fTrYx/uVYwg= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +google.golang.org/api v0.252.0 h1:xfKJeAJaMwb8OC9fesr369rjciQ704AjU/psjkKURSI= +google.golang.org/api v0.252.0/go.mod h1:dnHOv81x5RAmumZ7BWLShB/u7JZNeyalImxHmtTHxqw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= +k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= +k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= +k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= diff --git a/mimir_utils/internal/analyzer/top_metrics.go b/mimir_utils/internal/analyzer/top_metrics.go index bf46680..fa89740 100644 --- a/mimir_utils/internal/analyzer/top_metrics.go +++ b/mimir_utils/internal/analyzer/top_metrics.go @@ -7,10 +7,10 @@ import ( "sort" "strings" - "github.com/prometheus/prometheus/v3/model/labels" - "github.com/prometheus/prometheus/v3/tsdb/chunkenc" - "github.com/prometheus/prometheus/v3/tsdb/chunks" - "github.com/prometheus/prometheus/v3/tsdb/index" + "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/tsdb/chunkenc" + "github.com/prometheus/prometheus/tsdb/chunks" + "github.com/prometheus/prometheus/tsdb/index" ) // MetricStat captures byte usage information for a metric across a set of blocks. From 461b3b7855f2cbe041ec78ee876a70b9f20cdc42 Mon Sep 17 00:00:00 2001 From: Kyle Deal Date: Wed, 11 Mar 2026 15:21:29 +0000 Subject: [PATCH 4/4] Fix build failures --- mimir_utils/internal/analyzer/top_metrics.go | 12 +++++++----- mimir_utils/internal/cli/top_metrics.go | 1 - 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mimir_utils/internal/analyzer/top_metrics.go b/mimir_utils/internal/analyzer/top_metrics.go index fa89740..3ad64e3 100644 --- a/mimir_utils/internal/analyzer/top_metrics.go +++ b/mimir_utils/internal/analyzer/top_metrics.go @@ -1,6 +1,7 @@ package analyzer import ( + "context" "fmt" "os" "path/filepath" @@ -83,7 +84,7 @@ func accumulateBlock(blockDir string, aggregate map[string]*MetricStat) error { indexPath := filepath.Join(blockDir, "index") chunkDir := filepath.Join(blockDir, "chunks") - indexReader, err := index.NewFileReader(indexPath) + indexReader, err := index.NewFileReader(indexPath, index.DecodePostingsRaw) if err != nil { return fmt.Errorf("open index: %w", err) } @@ -97,20 +98,21 @@ func accumulateBlock(blockDir string, aggregate map[string]*MetricStat) error { defer chunkReader.Close() name, value := index.AllPostingsKey() - postings, err := indexReader.Postings(name, value) + postings, err := indexReader.Postings(context.Background(), name, value) if err != nil { return fmt.Errorf("load postings: %w", err) } for postings.Next() { ref := postings.At() - var lset labels.Labels + var builder labels.ScratchBuilder var metas []chunks.Meta - if err := indexReader.Series(ref, &lset, &metas); err != nil { + if err := indexReader.Series(ref, &builder, &metas); err != nil { return fmt.Errorf("read series %d: %w", ref, err) } + lset := builder.Labels() metricName := lset.Get("__name__") if metricName == "" { metricName = "(no_metric_name)" @@ -118,7 +120,7 @@ func accumulateBlock(blockDir string, aggregate map[string]*MetricStat) error { var seriesBytes int64 for _, meta := range metas { - chk, err := chunkReader.Chunk(meta.Ref) + chk, _, err := chunkReader.ChunkOrIterable(meta) if err != nil { if strings.Contains(err.Error(), "reference") { return fmt.Errorf("chunk %d: %w", meta.Ref, err) diff --git a/mimir_utils/internal/cli/top_metrics.go b/mimir_utils/internal/cli/top_metrics.go index b3f76de..8a02d1c 100644 --- a/mimir_utils/internal/cli/top_metrics.go +++ b/mimir_utils/internal/cli/top_metrics.go @@ -3,7 +3,6 @@ package cli import ( "flag" "fmt" - "math" "os" "text/tabwriter"