From 0a7f367853f197ac34b1fceb5af37d7a3ba94b80 Mon Sep 17 00:00:00 2001 From: TJ Hoplock Date: Mon, 15 Dec 2025 02:08:09 -0500 Subject: [PATCH 1/4] fix: updates for tsdb blocks handling Two small fixes: - I forgot the implementation for `*apiClientImpl.Do()` already extracts the response content from the enveloped `data` field in the response, so the wrapper struct isn't needed here. - The `compaction` section of a block has an optional `parents` field for tracking block lineage in deeper compaction levels. This slipped my mind during implementation because I was looking at the example API response on the API docs, which use a mock response with a single block that is uncompacted. I noticed these while working on tjhop/prometheus-mcp-server#77 Signed-off-by: TJ Hoplock --- api/prometheus/v1/api.go | 20 ++++++----- api/prometheus/v1/api_test.go | 66 ++++++++++++++++------------------- 2 files changed, 41 insertions(+), 45 deletions(-) diff --git a/api/prometheus/v1/api.go b/api/prometheus/v1/api.go index 8e5e6a390..b48c7fef6 100644 --- a/api/prometheus/v1/api.go +++ b/api/prometheus/v1/api.go @@ -696,14 +696,8 @@ type TSDBHeadStats struct { MaxTime int `json:"maxTime"` } -// TSDBBlocksResult contains the results from querying the tsdb blocks endpoint. -type TSDBBlocksResult struct { - Status string `json:"status"` - Data TSDBBlocksData `json:"data"` -} - // TSDBBlocksData contains the metadata for the tsdb blocks. -type TSDBBlocksData struct { +type TSDBBlocksResult struct { Blocks []TSDBBlocksBlockMetadata `json:"blocks"` } @@ -724,10 +718,18 @@ type TSDBBlocksStats struct { NumChunks int `json:"numChunks"` } +// TSDBBlocksCompactionParent contains details on parent blocks for a single tsdb block. +type TSDBBlocksCompactionParent struct { + Ulid string `json:"ulid"` + MinTime int64 `json:"minTime"` + MaxTime int64 `json:"maxTime"` +} + // TSDBBlocksCompaction contains block compaction details for a single block. type TSDBBlocksCompaction struct { - Level int `json:"level"` - Sources []string `json:"sources"` + Level int `json:"level"` + Sources []string `json:"sources"` + Parents []TSDBBlocksCompactionParent `json:"parents,omitempty"` } // WalReplayStatus represents the wal replay status. diff --git a/api/prometheus/v1/api_test.go b/api/prometheus/v1/api_test.go index aa26cba8d..7a3b12f90 100644 --- a/api/prometheus/v1/api_test.go +++ b/api/prometheus/v1/api_test.go @@ -1206,48 +1206,42 @@ func TestAPIs(t *testing.T) { reqMethod: "GET", reqPath: "/api/v1/status/tsdb/blocks", inRes: map[string]interface{}{ - "status": "success", - "data": map[string]interface{}{ - "blocks": []interface{}{ - map[string]interface{}{ - "ulid": "01JZ8JKZY6XSK3PTDP9ZKRWT60", - "minTime": 1750860620060, - "maxTime": 1750867200000, - "stats": map[string]interface{}{ - "numSamples": 13701, - "numSeries": 716, - "numChunks": 716, - }, - "compaction": map[string]interface{}{ - "level": 1, - "sources": []interface{}{ - "01JZ8JKZY6XSK3PTDP9ZKRWT60", - }, + "blocks": []interface{}{ + map[string]interface{}{ + "ulid": "01JZ8JKZY6XSK3PTDP9ZKRWT60", + "minTime": 1750860620060, + "maxTime": 1750867200000, + "stats": map[string]interface{}{ + "numSamples": 13701, + "numSeries": 716, + "numChunks": 716, + }, + "compaction": map[string]interface{}{ + "level": 1, + "sources": []interface{}{ + "01JZ8JKZY6XSK3PTDP9ZKRWT60", }, - "version": 1, }, + "version": 1, }, }, }, res: TSDBBlocksResult{ - Status: "success", - Data: TSDBBlocksData{ - Blocks: []TSDBBlocksBlockMetadata{{ - Ulid: "01JZ8JKZY6XSK3PTDP9ZKRWT60", - MinTime: 1750860620060, - MaxTime: 1750867200000, - Version: 1, - Stats: TSDBBlocksStats{ - NumSamples: 13701, - NumSeries: 716, - NumChunks: 716, - }, - Compaction: TSDBBlocksCompaction{ - Level: 1, - Sources: []string{"01JZ8JKZY6XSK3PTDP9ZKRWT60"}, - }, - }}, - }, + Blocks: []TSDBBlocksBlockMetadata{{ + Ulid: "01JZ8JKZY6XSK3PTDP9ZKRWT60", + MinTime: 1750860620060, + MaxTime: 1750867200000, + Version: 1, + Stats: TSDBBlocksStats{ + NumSamples: 13701, + NumSeries: 716, + NumChunks: 716, + }, + Compaction: TSDBBlocksCompaction{ + Level: 1, + Sources: []string{"01JZ8JKZY6XSK3PTDP9ZKRWT60"}, + }, + }}, }, }, From 6fb5643d200cda4d884cfdf5111b5454785cf41a Mon Sep 17 00:00:00 2001 From: TJ Hoplock Date: Thu, 29 Jan 2026 16:50:30 -0500 Subject: [PATCH 2/4] fix(api): align tsdb blocks struct names with upstream, reduce stutter Signed-off-by: TJ Hoplock --- api/prometheus/v1/api.go | 76 +++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/api/prometheus/v1/api.go b/api/prometheus/v1/api.go index b48c7fef6..7bfdd7149 100644 --- a/api/prometheus/v1/api.go +++ b/api/prometheus/v1/api.go @@ -696,40 +696,60 @@ type TSDBHeadStats struct { MaxTime int `json:"maxTime"` } -// TSDBBlocksData contains the metadata for the tsdb blocks. +// TSDBBlocksResult contains the result from querying the tsdb blocks endpoint. +// +// Note: TSDB block types are defined locally rather than importing from +// prometheus/prometheus to avoid circular dependencies and minimize the +// dependency footprint. These types match the HTTP API wire format and use +// string for ULID fields (since JSON serializes ULIDs as strings). See the +// individual type comments for links to upstream Prometheus definitions. type TSDBBlocksResult struct { - Blocks []TSDBBlocksBlockMetadata `json:"blocks"` -} - -// TSDBBlocksBlockMetadata contains the metadata for a single tsdb block. -type TSDBBlocksBlockMetadata struct { - Ulid string `json:"ulid"` - MinTime int64 `json:"minTime"` - MaxTime int64 `json:"maxTime"` - Stats TSDBBlocksStats `json:"stats"` - Compaction TSDBBlocksCompaction `json:"compaction"` - Version int `json:"version"` -} - -// TSDBBlocksStats contains block stats for a single tsdb block. -type TSDBBlocksStats struct { - NumSamples int `json:"numSamples"` - NumSeries int `json:"numSeries"` - NumChunks int `json:"numChunks"` -} - -// TSDBBlocksCompactionParent contains details on parent blocks for a single tsdb block. -type TSDBBlocksCompactionParent struct { + Blocks []TSDBBlockMeta `json:"blocks"` +} + +// TSDBBlockMeta contains the metadata for a single TSDB block. +// Counterpart to prometheus/prometheus tsdb.BlockMeta: +// https://github.com/prometheus/prometheus/blob/304dcdf6959d7a45530e9b6efa4080c5ca37dbf7/tsdb/block.go#L164 +type TSDBBlockMeta struct { + Ulid string `json:"ulid"` + MinTime int64 `json:"minTime"` + MaxTime int64 `json:"maxTime"` + Stats TSDBBlockStats `json:"stats,omitempty"` + Compaction TSDBBlockMetaCompaction `json:"compaction"` + Version int `json:"version"` +} + +// TSDBBlockStats contains block stats for a single TSDB block. +// Counterpart to prometheus/prometheus tsdb.BlockStats: +// https://github.com/prometheus/prometheus/blob/304dcdf6959d7a45530e9b6efa4080c5ca37dbf7/tsdb/block.go#L184 +type TSDBBlockStats struct { + NumSamples uint64 `json:"numSamples"` + NumFloatSamples uint64 `json:"numFloatSamples,omitempty"` + NumHistogramSamples uint64 `json:"numHistogramSamples,omitempty"` + NumSeries uint64 `json:"numSeries"` + NumChunks uint64 `json:"numChunks"` + NumTombstones uint64 `json:"numTombstones,omitempty"` +} + +// TSDBBlockDesc describes a TSDB block reference, used in compaction parent tracking. +// Counterpart to prometheus/prometheus tsdb.BlockDesc: +// https://github.com/prometheus/prometheus/blob/304dcdf6959d7a45530e9b6efa4080c5ca37dbf7/tsdb/block.go#L192 +type TSDBBlockDesc struct { Ulid string `json:"ulid"` MinTime int64 `json:"minTime"` MaxTime int64 `json:"maxTime"` } -// TSDBBlocksCompaction contains block compaction details for a single block. -type TSDBBlocksCompaction struct { - Level int `json:"level"` - Sources []string `json:"sources"` - Parents []TSDBBlocksCompactionParent `json:"parents,omitempty"` +// TSDBBlockMetaCompaction contains block compaction details for a single TSDB block. +// Counterpart to prometheus/prometheus tsdb.BlockMetaCompaction: +// https://github.com/prometheus/prometheus/blob/304dcdf6959d7a45530e9b6efa4080c5ca37dbf7/tsdb/block.go#L198 +type TSDBBlockMetaCompaction struct { + Level int `json:"level"` + Sources []string `json:"sources"` + Deletable bool `json:"deletable,omitempty"` + Parents []TSDBBlockDesc `json:"parents,omitempty"` + Failed bool `json:"failed,omitempty"` + Hints []string `json:"hints,omitempty"` } // WalReplayStatus represents the wal replay status. From d78b175ba6c51cda39585250188578363f2ef622 Mon Sep 17 00:00:00 2001 From: TJ Hoplock Date: Thu, 29 Jan 2026 16:52:25 -0500 Subject: [PATCH 3/4] test(api): expand test coverage for tsdb blocks endpoint we've been bit by missing fields and bad parity already, so this drammatically expands test coverage for the tsdb blocks endpoint to more ocmprehensively handle optional fields, unset fields, etc etc. Signed-off-by: TJ Hoplock --- api/prometheus/v1/api_test.go | 502 +++++++++++++++++++++++++++++++++- 1 file changed, 499 insertions(+), 3 deletions(-) diff --git a/api/prometheus/v1/api_test.go b/api/prometheus/v1/api_test.go index 7a3b12f90..af9a35416 100644 --- a/api/prometheus/v1/api_test.go +++ b/api/prometheus/v1/api_test.go @@ -1201,6 +1201,20 @@ func TestAPIs(t *testing.T) { err: errors.New("some error"), }, + // Empty blocks list. + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": []interface{}{}, + }, + res: TSDBBlocksResult{ + Blocks: []TSDBBlockMeta{}, + }, + }, + + // Single uncompacted block with minimal fields. { do: doTSDBBlocks(), reqMethod: "GET", @@ -1227,17 +1241,17 @@ func TestAPIs(t *testing.T) { }, }, res: TSDBBlocksResult{ - Blocks: []TSDBBlocksBlockMetadata{{ + Blocks: []TSDBBlockMeta{{ Ulid: "01JZ8JKZY6XSK3PTDP9ZKRWT60", MinTime: 1750860620060, MaxTime: 1750867200000, Version: 1, - Stats: TSDBBlocksStats{ + Stats: TSDBBlockStats{ NumSamples: 13701, NumSeries: 716, NumChunks: 716, }, - Compaction: TSDBBlocksCompaction{ + Compaction: TSDBBlockMetaCompaction{ Level: 1, Sources: []string{"01JZ8JKZY6XSK3PTDP9ZKRWT60"}, }, @@ -1245,6 +1259,488 @@ func TestAPIs(t *testing.T) { }, }, + // Block with all optional fields populated. + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": []interface{}{ + map[string]interface{}{ + "ulid": "01AAAAAAAAAAAAAAAAAAAAAA00", + "minTime": 1750860000000, + "maxTime": 1750867200000, + "stats": map[string]interface{}{ + "numSamples": 50000, + "numFloatSamples": 30000, + "numHistogramSamples": 20000, + "numSeries": 1000, + "numChunks": 2000, + "numTombstones": 5, + }, + "compaction": map[string]interface{}{ + "level": 3, + "sources": []interface{}{ + "01AAAAAAAAAAAAAAAAAAAAAA01", + "01AAAAAAAAAAAAAAAAAAAAAA02", + "01AAAAAAAAAAAAAAAAAAAAAA03", + }, + "deletable": true, + "parents": []interface{}{ + map[string]interface{}{ + "ulid": "01AAAAAAAAAAAAAAAAAAAAAA01", + "minTime": 1750853000000, + "maxTime": 1750860000000, + }, + map[string]interface{}{ + "ulid": "01AAAAAAAAAAAAAAAAAAAAAA02", + "minTime": 1750860000000, + "maxTime": 1750867200000, + }, + }, + "failed": true, + "hints": []interface{}{ + "deduplication", + "downsampling", + }, + }, + "version": 1, + }, + }, + }, + res: TSDBBlocksResult{ + Blocks: []TSDBBlockMeta{{ + Ulid: "01AAAAAAAAAAAAAAAAAAAAAA00", + MinTime: 1750860000000, + MaxTime: 1750867200000, + Version: 1, + Stats: TSDBBlockStats{ + NumSamples: 50000, + NumFloatSamples: 30000, + NumHistogramSamples: 20000, + NumSeries: 1000, + NumChunks: 2000, + NumTombstones: 5, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 3, + Sources: []string{ + "01AAAAAAAAAAAAAAAAAAAAAA01", + "01AAAAAAAAAAAAAAAAAAAAAA02", + "01AAAAAAAAAAAAAAAAAAAAAA03", + }, + Deletable: true, + Parents: []TSDBBlockDesc{ + { + Ulid: "01AAAAAAAAAAAAAAAAAAAAAA01", + MinTime: 1750853000000, + MaxTime: 1750860000000, + }, + { + Ulid: "01AAAAAAAAAAAAAAAAAAAAAA02", + MinTime: 1750860000000, + MaxTime: 1750867200000, + }, + }, + Failed: true, + Hints: []string{"deduplication", "downsampling"}, + }, + }}, + }, + }, + + // Multiple blocks at different compaction levels. + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": []interface{}{ + map[string]interface{}{ + "ulid": "01BBBBBBBBBBBBBBBBBBBBBB01", + "minTime": 1750860000000, + "maxTime": 1750867200000, + "stats": map[string]interface{}{ + "numSamples": 5000, + "numSeries": 200, + "numChunks": 200, + }, + "compaction": map[string]interface{}{ + "level": 1, + "sources": []interface{}{ + "01BBBBBBBBBBBBBBBBBBBBBB01", + }, + }, + "version": 1, + }, + map[string]interface{}{ + "ulid": "01BBBBBBBBBBBBBBBBBBBBBB02", + "minTime": 1750846800000, + "maxTime": 1750867200000, + "stats": map[string]interface{}{ + "numSamples": 25000, + "numSeries": 500, + "numChunks": 1500, + }, + "compaction": map[string]interface{}{ + "level": 2, + "sources": []interface{}{ + "01BBBBBBBBBBBBBBBBBBBBBB03", + "01BBBBBBBBBBBBBBBBBBBBBB04", + }, + "parents": []interface{}{ + map[string]interface{}{ + "ulid": "01BBBBBBBBBBBBBBBBBBBBBB03", + "minTime": 1750846800000, + "maxTime": 1750860000000, + }, + }, + }, + "version": 1, + }, + map[string]interface{}{ + "ulid": "01BBBBBBBBBBBBBBBBBBBBBB05", + "minTime": 1750820000000, + "maxTime": 1750867200000, + "stats": map[string]interface{}{ + "numSamples": 100000, + "numSeries": 1000, + "numChunks": 5000, + }, + "compaction": map[string]interface{}{ + "level": 3, + "sources": []interface{}{ + "01BBBBBBBBBBBBBBBBBBBBBB06", + "01BBBBBBBBBBBBBBBBBBBBBB07", + "01BBBBBBBBBBBBBBBBBBBBBB08", + }, + "parents": []interface{}{ + map[string]interface{}{ + "ulid": "01BBBBBBBBBBBBBBBBBBBBBB06", + "minTime": 1750820000000, + "maxTime": 1750840000000, + }, + map[string]interface{}{ + "ulid": "01BBBBBBBBBBBBBBBBBBBBBB07", + "minTime": 1750840000000, + "maxTime": 1750855000000, + }, + map[string]interface{}{ + "ulid": "01BBBBBBBBBBBBBBBBBBBBBB08", + "minTime": 1750855000000, + "maxTime": 1750867200000, + }, + }, + }, + "version": 1, + }, + }, + }, + res: TSDBBlocksResult{ + Blocks: []TSDBBlockMeta{ + { + Ulid: "01BBBBBBBBBBBBBBBBBBBBBB01", + MinTime: 1750860000000, + MaxTime: 1750867200000, + Version: 1, + Stats: TSDBBlockStats{ + NumSamples: 5000, + NumSeries: 200, + NumChunks: 200, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 1, + Sources: []string{"01BBBBBBBBBBBBBBBBBBBBBB01"}, + }, + }, + { + Ulid: "01BBBBBBBBBBBBBBBBBBBBBB02", + MinTime: 1750846800000, + MaxTime: 1750867200000, + Version: 1, + Stats: TSDBBlockStats{ + NumSamples: 25000, + NumSeries: 500, + NumChunks: 1500, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 2, + Sources: []string{ + "01BBBBBBBBBBBBBBBBBBBBBB03", + "01BBBBBBBBBBBBBBBBBBBBBB04", + }, + Parents: []TSDBBlockDesc{ + { + Ulid: "01BBBBBBBBBBBBBBBBBBBBBB03", + MinTime: 1750846800000, + MaxTime: 1750860000000, + }, + }, + }, + }, + { + Ulid: "01BBBBBBBBBBBBBBBBBBBBBB05", + MinTime: 1750820000000, + MaxTime: 1750867200000, + Version: 1, + Stats: TSDBBlockStats{ + NumSamples: 100000, + NumSeries: 1000, + NumChunks: 5000, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 3, + Sources: []string{ + "01BBBBBBBBBBBBBBBBBBBBBB06", + "01BBBBBBBBBBBBBBBBBBBBBB07", + "01BBBBBBBBBBBBBBBBBBBBBB08", + }, + Parents: []TSDBBlockDesc{ + { + Ulid: "01BBBBBBBBBBBBBBBBBBBBBB06", + MinTime: 1750820000000, + MaxTime: 1750840000000, + }, + { + Ulid: "01BBBBBBBBBBBBBBBBBBBBBB07", + MinTime: 1750840000000, + MaxTime: 1750855000000, + }, + { + Ulid: "01BBBBBBBBBBBBBBBBBBBBBB08", + MinTime: 1750855000000, + MaxTime: 1750867200000, + }, + }, + }, + }, + }, + }, + }, + + // Null blocks field (server returns null instead of empty array). + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": nil, + }, + res: TSDBBlocksResult{ + Blocks: nil, + }, + }, + + // Block with missing optional stats field (should deserialize with zero values). + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": []interface{}{ + map[string]interface{}{ + "ulid": "01CCCCCCCCCCCCCCCCCCCCCC01", + "minTime": 1750860000000, + "maxTime": 1750867200000, + "compaction": map[string]interface{}{ + "level": 1, + "sources": []interface{}{ + "01CCCCCCCCCCCCCCCCCCCCCC01", + }, + }, + "version": 1, + // Note: no "stats" field + }, + }, + }, + res: TSDBBlocksResult{ + Blocks: []TSDBBlockMeta{{ + Ulid: "01CCCCCCCCCCCCCCCCCCCCCC01", + MinTime: 1750860000000, + MaxTime: 1750867200000, + Version: 1, + Stats: TSDBBlockStats{}, // zero values + Compaction: TSDBBlockMetaCompaction{ + Level: 1, + Sources: []string{"01CCCCCCCCCCCCCCCCCCCCCC01"}, + }, + }}, + }, + }, + + // Block with "out-of-order" hint (specific to Prometheus OOO feature). + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": []interface{}{ + map[string]interface{}{ + "ulid": "01DDDDDDDDDDDDDDDDDDDDDD01", + "minTime": 1750860000000, + "maxTime": 1750867200000, + "stats": map[string]interface{}{ + "numSamples": 1000, + "numSeries": 100, + "numChunks": 100, + }, + "compaction": map[string]interface{}{ + "level": 1, + "sources": []interface{}{ + "01DDDDDDDDDDDDDDDDDDDDDD01", + }, + "hints": []interface{}{ + "out-of-order", + }, + }, + "version": 1, + }, + }, + }, + res: TSDBBlocksResult{ + Blocks: []TSDBBlockMeta{{ + Ulid: "01DDDDDDDDDDDDDDDDDDDDDD01", + MinTime: 1750860000000, + MaxTime: 1750867200000, + Version: 1, + Stats: TSDBBlockStats{ + NumSamples: 1000, + NumSeries: 100, + NumChunks: 100, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 1, + Sources: []string{"01DDDDDDDDDDDDDDDDDDDDDD01"}, + Hints: []string{"out-of-order"}, + }, + }}, + }, + }, + + // Block with zero-value time boundaries (edge case). + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": []interface{}{ + map[string]interface{}{ + "ulid": "01EEEEEEEEEEEEEEEEEEEEEE01", + "minTime": 0, + "maxTime": 0, + "stats": map[string]interface{}{ + "numSamples": 0, + "numSeries": 0, + "numChunks": 0, + }, + "compaction": map[string]interface{}{ + "level": 1, + "sources": []interface{}{ + "01EEEEEEEEEEEEEEEEEEEEEE01", + }, + }, + "version": 1, + }, + }, + }, + res: TSDBBlocksResult{ + Blocks: []TSDBBlockMeta{{ + Ulid: "01EEEEEEEEEEEEEEEEEEEEEE01", + MinTime: 0, + MaxTime: 0, + Version: 1, + Stats: TSDBBlockStats{ + NumSamples: 0, + NumSeries: 0, + NumChunks: 0, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 1, + Sources: []string{"01EEEEEEEEEEEEEEEEEEEEEE01"}, + }, + }}, + }, + }, + + // Block with different version values. + { + do: doTSDBBlocks(), + reqMethod: "GET", + reqPath: "/api/v1/status/tsdb/blocks", + inRes: map[string]interface{}{ + "blocks": []interface{}{ + map[string]interface{}{ + "ulid": "01FFFFFFFFFFFFFFFFFFFFFF01", + "minTime": 1750860000000, + "maxTime": 1750867200000, + "stats": map[string]interface{}{ + "numSamples": 500, + "numSeries": 50, + "numChunks": 50, + }, + "compaction": map[string]interface{}{ + "level": 1, + "sources": []interface{}{ + "01FFFFFFFFFFFFFFFFFFFFFF01", + }, + }, + "version": 0, // Version 0 (legacy/unset) + }, + map[string]interface{}{ + "ulid": "01FFFFFFFFFFFFFFFFFFFFFF02", + "minTime": 1750867200000, + "maxTime": 1750874400000, + "stats": map[string]interface{}{ + "numSamples": 600, + "numSeries": 60, + "numChunks": 60, + }, + "compaction": map[string]interface{}{ + "level": 1, + "sources": []interface{}{ + "01FFFFFFFFFFFFFFFFFFFFFF02", + }, + }, + "version": 2, // Hypothetical future version + }, + }, + }, + res: TSDBBlocksResult{ + Blocks: []TSDBBlockMeta{ + { + Ulid: "01FFFFFFFFFFFFFFFFFFFFFF01", + MinTime: 1750860000000, + MaxTime: 1750867200000, + Version: 0, + Stats: TSDBBlockStats{ + NumSamples: 500, + NumSeries: 50, + NumChunks: 50, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 1, + Sources: []string{"01FFFFFFFFFFFFFFFFFFFFFF01"}, + }, + }, + { + Ulid: "01FFFFFFFFFFFFFFFFFFFFFF02", + MinTime: 1750867200000, + MaxTime: 1750874400000, + Version: 2, + Stats: TSDBBlockStats{ + NumSamples: 600, + NumSeries: 60, + NumChunks: 60, + }, + Compaction: TSDBBlockMetaCompaction{ + Level: 1, + Sources: []string{"01FFFFFFFFFFFFFFFFFFFFFF02"}, + }, + }, + }, + }, + }, + { do: doWalReply(), reqMethod: "GET", From 68fb72f7a881b8633bbc6b11b4f4b4649ee2780c Mon Sep 17 00:00:00 2001 From: TJ Hoplock Date: Thu, 29 Jan 2026 16:59:53 -0500 Subject: [PATCH 4/4] style: go fmt My commit hook didn't run it seems. Oops. Signed-off-by: TJ Hoplock --- api/prometheus/v1/api.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/prometheus/v1/api.go b/api/prometheus/v1/api.go index 7bfdd7149..451ccaecf 100644 --- a/api/prometheus/v1/api.go +++ b/api/prometheus/v1/api.go @@ -711,12 +711,12 @@ type TSDBBlocksResult struct { // Counterpart to prometheus/prometheus tsdb.BlockMeta: // https://github.com/prometheus/prometheus/blob/304dcdf6959d7a45530e9b6efa4080c5ca37dbf7/tsdb/block.go#L164 type TSDBBlockMeta struct { - Ulid string `json:"ulid"` - MinTime int64 `json:"minTime"` - MaxTime int64 `json:"maxTime"` - Stats TSDBBlockStats `json:"stats,omitempty"` + Ulid string `json:"ulid"` + MinTime int64 `json:"minTime"` + MaxTime int64 `json:"maxTime"` + Stats TSDBBlockStats `json:"stats,omitempty"` Compaction TSDBBlockMetaCompaction `json:"compaction"` - Version int `json:"version"` + Version int `json:"version"` } // TSDBBlockStats contains block stats for a single TSDB block.