Skip to content

refactor(appenderV2)[PART5a]: add AppendableV2 support to scrape loop + tests#17867

Merged
bwplotka merged 5 commits intomainfrom
bwplotka/a2-scrape-1
Jan 21, 2026
Merged

refactor(appenderV2)[PART5a]: add AppendableV2 support to scrape loop + tests#17867
bwplotka merged 5 commits intomainfrom
bwplotka/a2-scrape-1

Conversation

@bwplotka
Copy link
Member

@bwplotka bwplotka commented Jan 15, 2026

Progresses the #17632

Chained on top of #17835 (comment)

Majority of changed LOCs is the duplicated tests for V2 flow. Will be removed in M2 stage.

This PR:

  • adds the AppendableV2 support to scrape package
  • It does NOT switch prod flow to V2 just yet.
  • It does NOT allow downstream yet to use it as I don't change public scrape.NewManager contructor yet. Will do in the next PRs.

Should not change behavior on e2e level. 2 minor changes to test expectations were added to literally 2 tests to accommodate Appender new contract:

  • Metadata is attached not "updated" (update logic is still maintained, but now on TSDB side). See the v2 flow for func TestScrapeAppend_MetadataUpdate tests.
  • We now add metric family name if we have it, reflected in TestScrapeLoopAppendExemplar extra processing of expected samples.

Does this PR introduce a user-facing change?

NONE

@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch 3 times, most recently from 766d76d to ccbe71a Compare January 15, 2026 12:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds AppendableV2 support to the scrape package to progress towards a new append API. The change is backward-compatible and does not modify production behavior yet, as it introduces parallel V2 code paths alongside existing V1 paths.

Changes:

  • Adds AppendableV2 support to scrapePool and scrapeLoop with runtime selection based on which appendable is configured
  • Implements V2 versions of limiting appenders (limitAppenderV2, timeLimitAppenderV2, bucketLimitAppenderV2, maxSchemaAppenderV2)
  • Duplicates comprehensive test suite with "_AppendV2" suffix to validate V2 flow (tests will be removed in M2 stage)

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scrape/scrape.go Adds appendableV2 fields to scrapePool and scrapeLoop; updates appender() to select V2 or V1 path at runtime
scrape/scrape_append_v2.go Implements scrapeLoopAppenderV2 and V2 limiting appenders with new Append signature
scrape/target.go Adds V2 versions of limiting appenders (limitAppenderV2, timeLimitAppenderV2, bucketLimitAppenderV2, maxSchemaAppenderV2)
scrape/manager.go Updates Manager to support appendableV2 and passes it to newScrapePool
scrape/scrape_test.go Updates existing tests to pass nil for new appendableV2 parameter in newScrapePool calls
scrape/scrape_append_v2_test.go Comprehensive test duplication for V2 flow (4630 lines, to be removed in M2)
scrape/helpers_test.go Adds withAppendableV2 test helper and removes default appendable from newTestScrapeLoop
util/teststorage/appender.go Fixes ref computation logic to handle chained appendables with different ref logic

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@bwplotka
Copy link
Member Author

bwplotka commented Jan 16, 2026

Scraping is ~6% slower for V2 flow. I will investigate where we lose those CPU cycles, I think we shouldn't see that much overhead (although 5% is maybe small) - probably next week.

benchstat -col .name append-v1.txt append-v2.txt 
goos: darwin
goarch: arm64
pkg: github.com/prometheus/prometheus/scrape
cpu: Apple M4 Pro
                                       │ ScrapeLoopAppend │     ScrapeLoopAppend_AppendV2     │
                                       │      sec/op      │   sec/op     vs base              │
*/data=1Fam1000Gauges/fmt=PromText-2          403.1µ ± 3%   423.8µ ± 4%  +5.16% (p=0.002 n=6)
*/data=1Fam1000Gauges/fmt=OMText-2            401.5µ ± 4%   418.0µ ± 1%  +4.11% (p=0.002 n=6)
*/data=1Fam1000Gauges/fmt=PromProto-2         423.7µ ± 1%   453.6µ ± 1%  +7.07% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=PromText-2         566.6µ ± 2%   595.5µ ± 1%  +5.10% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=OMText-2           552.8µ ± 1%   592.2µ ± 1%  +7.13% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=PromProto-2        472.7µ ± 2%   506.5µ ± 5%  +7.16% (p=0.002 n=6)
geomean                                       465.3µ        493.0µ       +5.95%

                                       │ ScrapeLoopAppend │     ScrapeLoopAppend_AppendV2      │
                                       │       B/op       │     B/op      vs base              │
*/data=1Fam1000Gauges/fmt=PromText-2         365.1Ki ± 3%   376.0Ki ± 3%  +3.00% (p=0.002 n=6)
*/data=1Fam1000Gauges/fmt=OMText-2           363.1Ki ± 2%   370.6Ki ± 2%  +2.06% (p=0.015 n=6)
*/data=1Fam1000Gauges/fmt=PromProto-2        479.2Ki ± 1%   503.4Ki ± 1%  +5.04% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=PromText-2        337.9Ki ± 3%   337.9Ki ± 0%  +0.01% (p=0.015 n=6)
*/data=237FamsAllTypes/fmt=OMText-2          338.0Ki ± 0%   338.8Ki ± 5%  +0.22% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=PromProto-2       406.8Ki ± 2%   409.5Ki ± 2%  +0.66% (p=0.035 n=6)
geomean                                      378.8Ki        385.6Ki       +1.81%

                                       │ ScrapeLoopAppend │     ScrapeLoopAppend_AppendV2     │
                                       │    allocs/op     │  allocs/op   vs base              │
*/data=1Fam1000Gauges/fmt=PromText-2          2.012k ± 0%   2.013k ± 0%  +0.05% (p=0.002 n=6)
*/data=1Fam1000Gauges/fmt=OMText-2            2.013k ± 0%   2.014k ± 0%  +0.05% (p=0.002 n=6)
*/data=1Fam1000Gauges/fmt=PromProto-2         2.028k ± 0%   2.029k ± 0%  +0.05% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=PromText-2         1.870k ± 0%   1.871k ± 0%  +0.05% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=OMText-2           1.871k ± 0%   1.872k ± 0%  +0.05% (p=0.002 n=6)
*/data=237FamsAllTypes/fmt=PromProto-2        4.088k ± 0%   4.089k ± 0%  +0.02% (p=0.002 n=6)
geomean                                       2.213k        2.214k       +0.05%

Base automatically changed from bwplotka/a2-storage-support to main January 16, 2026 13:04
Copy link
Member

@krajorama krajorama left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic seems to be good, but I'm really surprised by the testing strategy, especially for the scrape.

Most of the tests go through the scrapeLoopAppendAdapter interface which is common for v1 and v2, so you don't have to actually duplicate tests, just make the test function take the scrapeLoopAppendAdapter as an argument and run it twice. Also scrape_append_v2_test.go has a bunch of tests that don't use v2 at all, just in the name?

I think we should not have scrape_append_v2_test.go , but add the cases to scrape_test.go. The current way of working is very time consuming to actually check.

@bwplotka
Copy link
Member Author

The logic seems to be good, but I'm really surprised by the testing strategy, especially for the scrape.

It's consistent with TSDB and Agent DB.

I see how test cases would be easier, especially after refactor we did. I did follow test case logic in #17872 - easier to review for sure. Let me invest time into it.

@bwplotka bwplotka marked this pull request as draft January 19, 2026 11:06
@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch 8 times, most recently from 4198598 to 126cfab Compare January 19, 2026 13:59
@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch 2 times, most recently from 369ee03 to 429793e Compare January 19, 2026 15:06
@bwplotka bwplotka marked this pull request as ready for review January 19, 2026 15:06
@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch from 429793e to 88a6b80 Compare January 19, 2026 15:09

// In majority cases we can trust that the current series/histogram is matching the lastMeta and lastMFName.
// However, optional TYPE etc metadata and broken OM text can break this, detect those cases here.
if !isSeriesPartOfFamily(lset.Get(model.MetricNameLabel), lastMFName, lastMeta.Type) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one source of the overhead we saw in microbenchmarks (CPU). Notably, to pass correct metadata to V2 we need to check for that broken text format (at least to maintain parity). V1 was only doing this when metadata changes (the broken on - as-is - not really connected to the sample we append)

Microbenchmarks bench appendMetadataToWAL.

This is only for a broken feature, so I'd change / add case microbenchmarks to skip appendMetadataToWAL feature for now, but we probably want to do a move to per parser and rethink this path in general. I am also curious how type and unit handle this (likely they don't) for always-on metadata 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added cases for benchmark.

Keeping this path slower for now, I think it's acceptable given metadata-wal-records has bigger issues. Perhaps worth to add issue and TODO to optimize this (move to parsers)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added #17900

Copy link
Member

@krajorama krajorama left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some nit comments, this is looking much better, thank you

@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch 3 times, most recently from 0615990 to 1c0c729 Compare January 20, 2026 11:18
@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch 4 times, most recently from 1d57f4d to 21315c2 Compare January 20, 2026 12:36
Signed-off-by: bwplotka <bwplotka@gmail.com>
Signed-off-by: bwplotka <bwplotka@gmail.com>
Signed-off-by: bwplotka <bwplotka@gmail.com>
Signed-off-by: bwplotka <bwplotka@gmail.com>
@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch from 21315c2 to 49c60b0 Compare January 20, 2026 12:54
@bwplotka
Copy link
Member Author

bwplotka commented Jan 20, 2026

The latest benchmark for completeness:

The appendMetadataToWAL=true latency is expected (see #17867 (comment))

I am still trying understand why mem and CPU regress (appendMetadataToWAL=false).

benchstat -col /appV2 append.txt                  
goos: darwin
goarch: arm64
pkg: github.com/prometheus/prometheus/scrape
cpu: Apple M4 Pro
                                                                                │    false     │                true                │
                                                                                │    sec/op    │   sec/op     vs base               │
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=PromText-2     317.7µ ±  8%   329.0µ ± 1%        ~ (p=0.065 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=OMText-2       312.8µ ±  1%   327.4µ ± 1%   +4.64% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=PromProto-2    379.9µ ±  2%   392.8µ ± 1%   +3.38% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=PromText-2    488.0µ ±  1%   514.0µ ± 0%   +5.33% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=OMText-2      490.7µ ±  1%   511.8µ ± 1%   +4.30% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=PromProto-2   422.5µ ±  3%   439.9µ ± 1%   +4.11% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=PromText-2      320.7µ ±  1%   357.3µ ± 0%  +11.42% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=OMText-2        320.3µ ±  5%   353.0µ ± 0%  +10.22% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=PromProto-2     415.8µ ±  6%   419.6µ ± 1%        ~ (p=0.310 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=PromText-2     501.2µ ±  1%   546.9µ ± 2%   +9.13% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=OMText-2       503.9µ ±  3%   546.8µ ± 1%   +8.51% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=PromProto-2    437.4µ ± 10%   471.1µ ± 2%        ~ (p=0.065 n=6)
geomean                                                                           402.4µ         426.8µ        +6.06%

                                                                                │    false     │                true                │
                                                                                │     B/op     │     B/op      vs base              │
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=PromText-2     2.075Ki ± 1%   2.138Ki ± 1%  +3.04% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=OMText-2       2.212Ki ± 0%   2.286Ki ± 1%  +3.33% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=PromProto-2    110.9Ki ± 0%   111.1Ki ± 0%  +0.10% (p=0.009 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=PromText-2    2.524Ki ± 1%   2.602Ki ± 0%  +3.10% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=OMText-2      2.676Ki ± 1%   2.735Ki ± 1%  +2.21% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=PromProto-2   74.08Ki ± 0%   74.20Ki ± 0%  +0.15% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=PromText-2      2.110Ki ± 1%   2.233Ki ± 1%  +5.83% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=OMText-2        2.252Ki ± 1%   2.368Ki ± 1%  +5.16% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=PromProto-2     111.0Ki ± 0%   111.1Ki ± 0%       ~ (p=0.310 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=PromText-2     2.588Ki ± 2%   2.711Ki ± 1%  +4.73% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=OMText-2       2.736Ki ± 1%   2.859Ki ± 3%  +4.50% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=PromProto-2    74.15Ki ± 0%   74.36Ki ± 0%  +0.29% (p=0.002 n=6)
geomean                                                                           8.018Ki        8.233Ki       +2.69%

                                                                                │    false    │                true                │
                                                                                │  allocs/op  │  allocs/op   vs base               │
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=PromText-2      18.00 ± 0%    19.00 ± 5%   +5.56% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=OMText-2        19.00 ± 0%    20.00 ± 5%   +5.26% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=1Fam1000Gauges/fmt=PromProto-2     35.00 ± 0%    36.00 ± 0%   +2.86% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=PromText-2     20.00 ± 0%    21.50 ± 2%   +7.50% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=OMText-2       21.00 ± 0%    22.00 ± 5%   +4.76% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=false/data=237FamsAllTypes/fmt=PromProto-2   2.238k ± 0%   2.239k ± 0%   +0.04% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=PromText-2       18.00 ± 0%    20.00 ± 0%  +11.11% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=OMText-2         19.00 ± 0%    21.00 ± 0%  +10.53% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=1Fam1000Gauges/fmt=PromProto-2      35.00 ± 3%    36.00 ± 3%   +2.86% (p=0.013 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=PromText-2      20.00 ± 5%    22.00 ± 0%  +10.00% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=OMText-2        21.00 ± 5%    23.00 ± 0%   +9.52% (p=0.002 n=6)
ScrapeLoopAppend/appendMetadataToWAL=true/data=237FamsAllTypes/fmt=PromProto-2    2.238k ± 0%   2.239k ± 0%   +0.04% (p=0.002 n=6)
geomean                                                                            47.34         50.07        +5.77%
benchstat -col /appV2 appendHistWithExemplars.txt 
goos: darwin
goarch: arm64
pkg: github.com/prometheus/prometheus/scrape
cpu: Apple M4 Pro
                                           │    false    │               true                │
                                           │   sec/op    │   sec/op     vs base              │
ScrapeLoopAppend_HistogramsWithExemplars-2   732.8µ ± 1%   759.7µ ± 2%  +3.67% (p=0.002 n=6)

                                           │    false     │             true              │
                                           │     B/op     │     B/op      vs base         │
ScrapeLoopAppend_HistogramsWithExemplars-2   131.9Ki ± 0%   131.9Ki ± 0%  ~ (p=0.394 n=6)

                                           │    false    │               true                │
                                           │  allocs/op  │  allocs/op   vs base              │
ScrapeLoopAppend_HistogramsWithExemplars-2   2.421k ± 0%   2.422k ± 0%  +0.04% (p=0.002 n=6)

Signed-off-by: bwplotka <bwplotka@gmail.com>
@bwplotka bwplotka force-pushed the bwplotka/a2-scrape-1 branch from 49c60b0 to 28be7e7 Compare January 20, 2026 13:27
Copy link
Member

@krajorama krajorama left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved with comment

// TODO(bwplotka): We should likely reorder only within a group of sequential NaNs or only in scrape package.
func RequireEqual(t testing.TB, expected, got []Sample, msgAndArgs ...any) {
opts := []cmp.Option{sampleComparer}
if includeStaleNaNs(expected) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this at all. It feels like a bug waiting to happen, by obscuring the real ordering. Still it's better than the original that did this unconditionally. I have a better idea how to do this, will open PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@bwplotka bwplotka merged commit 664b255 into main Jan 21, 2026
62 of 68 checks passed
@bwplotka bwplotka deleted the bwplotka/a2-scrape-1 branch January 21, 2026 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants