Repository navigation
fix(prometheus): accept selector strings in label matches - #1340
matheusleite-plank wants to merge 2 commits into
Conversation
| if err := json.Unmarshal(data, &selector); err != nil { | ||
| return err | ||
| } | ||
| parsed, err := parseSelectorStrings([]string{selector}) |
There was a problem hiding this comment.
[P2] Parse valid Prometheus selectors before applying tolerant normalization
Routing every string through parseSelectorStrings rejects valid selectors because that helper normalizes label-filter syntax before parsing:
upbecomes{up}, andhttp_requests_total{job="api"}becomes{http_requests_total{job="api"}}. Both fail to parse.{path="/search?q=abc"}becomes{path="/search?q="abc""}because the unquoted-value repair also matches=inside an already quoted value.
I reproduced these at 48207c4 using the new Selector decoder and verified that Prometheus's ParseMetricSelector accepts the original inputs. Since both label tools decode matches through this method, these valid string inputs still fail before reaching the backend.
Could we parse the original string first and apply tolerant normalization only if strict parsing fails? Regression tests should include a bare metric name, a metric-prefixed selector, and a quoted label value containing =. The existing focused tests pass but do not cover these cases.
There was a problem hiding this comment.
Thanks, confirmed all three. The decoder now parses the original string with promqlParser.ParseMetricSelector first and only falls back to the tolerant parseSelectorStrings when strict parsing fails. Added regression tests for a bare metric name, a metric-prefixed selector, and = inside a quoted value, plus an unquoted-value case to cover the fallback.
What this changes
list_prometheus_label_valuesandlist_prometheus_label_namesreject Prometheus selector strings inmatches. LLM clients often send the PromQL form ("matches": ["{job=\"api\"}"]) instead of the{"filters": [...]}object, and the call fails with:This adds
Selector.UnmarshalJSON, which accepts either form. A JSON string is parsed with the existingparseSelectorStrings(already used forlabel_selectorsin the alerting tools), so it handles missing braces, unquoted values and all four matcher operators the same way. Objects decode exactly as before, andnullkeeps its previous behavior.The advertised input schema is unchanged:
tools/listoutput is identical before and after (79 tools), so there is no token cost.How you tested it
TestSelectorUnmarshalJSONintools/prometheus_unit_test.go: selector string, string without braces,=~/!~operators, filters object,null, invalid string, and a fullListPrometheusLabelValuesParamsdecode.go test -tags unit ./...,gofmt -l .,golangci-lint run(v2.14.0, 0 issues),lint-jsonschemaandlint-openapipass.mainvs this branch:matchesmain["{job=\"prometheus\"}"]["prometheus"][{"filters":[{"name":"job","value":"prometheus","type":"="}]}]["prometheus"]["prometheus"]["{job=\"nope\"}"][]["not a selector{"]invalid arguments: invalid label selector ...list_prometheus_label_nameswith a string selectorChecklist
make lintandmake test-unitpass locally--disable-write--disable-query(and--disable-writetoo, if the query is passed through unfiltered)