Repository navigation
fix(otelmetrics): return complete query results and honor Retry-After - #792
Open
petruanica wants to merge 1 commit into
Open
petruanica wants to merge 1 commit into
petruanica wants to merge 1 commit into
Conversation
This was referenced Oct 29, 2026
Closed
petruanica
force-pushed
the
otel-ci-complete-queries
branch
from
November 5, 2026 18:09
1ba6c8c to
769341c
Compare
This was referenced Nov 9, 2026
Open
petruanica
force-pushed
the
otel-ci-complete-queries
branch
from
November 9, 2026 18:28
769341c to
2131a13
Compare
9 of 10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description of the issue
The PromQL endpoint that the OTel suites query returns at most 500 series for one query. It often drops the other series without a warning. A test that reads every series of a metric then sees only part of the cluster, and it can pass without looking at most nodes.
The client also retries a throttled or failed request after a fixed backoff of 1, 2 and 4 seconds. It ignores the
Retry-Afterheader. So a retry can come before the server is ready, or the suite can wait longer than the server asks.Description of changes
OtelMetricsClient.QueryComplete(util/otelmetrics/complete.go) returns every series that a plain vector selector matches. It sends the selector andcount()of the selector at the same time. Both use one evaluation time, which the client picks 5 seconds in the past. If the result has fewer series than the count, it fetches the selector again in disjoint shards. It splits by node first. When one node still has too many series, it also splits by other labels of the result. A label that has more values than one response can list, such asinstance_typeon the Karpenter instance type metrics, is split by value prefix, and so is a label past the first three candidates. The client counts the series per prefix withcount byoverlabel_replace, and a shard that is still over the limit gets a longer prefix. If the shards do not add up to the count, it returns an error and no partial result. A query that is not a plain vector selector goes toQueryunchanged.QueryCachereads throughQueryComplete, soGetandGetWithFilterreturn every series. Each HTTP request, including each shard request, holds one slot of the cache's concurrency limit. A failed read for one host type now fails the wholeGet. Before,Getdropped that host type without an error.The suites had 35 direct
client.Querycalls that run a plain vector selector. They now callQueryComplete: efa (3), filters (1), gpu (3), gpu_filters (3), multi_efa_filters (1), neuron (5), neuron_filters (1), performance (1) and standard (17). Aggregations stay onQuery, because the cap does not cut their input.The retry loop reads
Retry-Afteron HTTP 429 and 5xx responses, as a number of seconds or as an HTTP date. A missing or invalid header keeps the exponential backoff. The wait is at most 30 seconds (maxRetryAfter), so one throttled request cannot stall a suite.This is PR 1 of 4. PR 2 to PR 4 build on it.
License
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Tests
The unit tests in
util/otelmetricsrun without a cluster and pass with-race.client_test.gocoversretryDelayand a throttled request that waits forRetry-After.complete_test.gocovers an untruncated read, the parallel selector and count, and sharding by node. It also covers a node over the limit, a label with too many values and inconsistent counts. The other cases are shard totals that do not match, a selector that cannot be split, a selector that matches no series, and queries that are not plain selectors.complete_test.goalso covers the prefix split: one resource with more instance types than the limit, a prefix shard that needs a longer prefix, values with regex metacharacters, prefix counts that do not add up, a shared value prefix that is shorter than the sample's common prefix, and a label past the candidate limit.query_cache_test.gocovers truncated reads through the cache, a failed host type, and the concurrency limit for shard requests.go vet -tags integrationpasses onutil/otelmetricsand on every package undertest/otel.gofmtreports nothing, andmake compilepasses.The standard and gpu suites ran against an EKS test cluster at the top of this stack (PR 4), with the chart from aws-observability/helm-charts main.
QueryCompletefound reads that the endpoint had cut, for examplekube_pod_status_phaseandcontainer_cpu_usage_seconds_total, and fetched them in shards. The results are in PR 3.PR Checklist
makepasses locally (build, unit tests, lint):make compileandmake simple-lint, the targets that the build-check workflow runs, pass on this commit, and so do theutil/otelmetricsunit tests with-race.QueryCompletetoo.