Skip to content

fix: the translator no longer panics on a label name holding its key-list separator bytes - #761

Merged
szibis merged 2 commits into
mainfrom
fix/translator-label-separator-bytes
Oct 14, 2026
Merged

szibis merged 2 commits into
mainfrom
fix/translator-label-separator-bytes

Conversation

@szibis

@szibis szibis commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

FuzzTranslateWithStreamFields found a panic in the query translator (CI fuzz-smoke):

{app="x"} | json | \x01a_b="v"
panic: runtime error: index out of range [0] with length 0
  translateParsedKeyFilter (parsed_key_variants.go:130)

The translator encodes the candidate keys of a sanitized label as one string: keys are joined by \x00, and a name_extracted collision candidate is marked with a leading \x01. A label name that itself held those bytes was decoded as a key list: a leading \x01 recursed past the end of the list, and an inner \x00 split one name into two keys.

  • withParsedKeyVariants leaves a name holding either byte as a plain name.
  • translateSingleLabelFilter splits the translation into keys only when the label name itself holds no separator.

Client impact

None. The request path validates the query with the Loki grammar first and answers Loki's parse error (400) for these names, so only direct translator callers (and the fuzz target) could reach the panic.

Tests

  • TestParsedKeyFilterNameWithSeparatorBytes: panics on main, passes here.
  • FuzzTranslateWithStreamFields for 60 s locally: pass.
  • go test -short ./internal/translator ./internal/proxy, golangci-lint, the changelog and conformance gates: pass.

No change to translated queries for valid label names, so no A/B or e2e run.

…list separator bytes

A label filter after | json or | logfmt whose name starts with the byte
0x01 was read as a name_extracted key list and indexed an empty slice; a
name holding 0x00 was split into two keys. Such names are now translated
as plain names. The request path already rejects these queries with
Loki's parse error, so only direct translator callers were affected.
@github-actions github-actions Bot added size/S Small change scope/translator LogQL translator scope/docs Documentation scope/tests Tests bugfix Bug fix and removed size/S Small change labels Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

⚪ Performance A/B: no change beyond noise

105 shape×range — 105 ⚪ same · results vs Loki: 88 same, 0 new difference(s), 17 pre-existing

Every shape is within noise of the base build (±30% and 100 ms).

105 unchanged shape×range (within noise)
shape range base p50 PR p50 change Loki p50 PR ÷ Loki result vs Loki
⚪ bytes_over_time by app 1h 68 ms 69 ms ⚪ +1% 89 ms 0.78× ✅ same
⚪ drilldown service landing 1h 38 ms 33 ms ⚪ -13% 26 ms 1.27× ✅ same
⚪ instant json filtered instant 364 ms 373 ms ⚪ +2% 76 ms 4.91× ✅ same
⚪ instant json volume instant 404 ms 409 ms ⚪ +1% 98 ms 4.17× ✅ same
⚪ instant ungrouped rate instant 9 ms 8 ms ⚪ -11% 74 ms 0.11× ✅ same
⚪ json rate by level (no filter, no drop) 1h 400 400 ⚪ +0% 400 — ✅ same
⚪ json volume no filters 1h 202 ms 201 ms ⚪ -0% 3 ms 67× ✅ same
⚪ logfmt count by level, filter, drop 1h 429 ms 439 ms ⚪ +2% 59 ms 7.44× ✅ same
⚪ logfmt volume 1h 312 ms 313 ms ⚪ +0% 62 ms 5.05× ✅ same
⚪ logs plain 1h 72 ms 68 ms ⚪ -6% 42 ms 1.62× ✅ same
⚪ logs | json 1h 101 ms 98 ms ⚪ -3% 64 ms 1.53× ✅ same
⚪ logs | logfmt 1h 150 ms 156 ms ⚪ +4% 51 ms 3.06× ✅ same
⚪ stream-label count by app 1h 32 ms 25 ms ⚪ -22% 39 ms 0.64× ✅ same
⚪ topk rate by app 1h 45 ms 45 ms ⚪ +0% 87 ms 0.52× ➖ differs (as base)
⚪ ungrouped rate 1h 19 ms 12 ms ⚪ -37% 81 ms 0.15× ✅ same
⚪ DB3 json field breakdown user_id 1h 51 ms 50 ms ⚪ -2% 25 ms 2.00× ✅ same
⚪ DB4 json field breakdown batch_id 1h 99 ms 92 ms ⚪ -7% 54 ms 1.70× ✅ same
⚪ X1 json filter level_extracted, by level 1h 413 ms 432 ms ⚪ +5% 45 ms 9.60× ✅ same
⚪ X2 json group by level_extracted 1h 341 ms 342 ms ⚪ +0% 48 ms 7.12× ✅ same
⚪ X3 json rate, level_extracted equality 1h 322 ms 313 ms ⚪ -3% 37 ms 8.46× ✅ same
⚪ X4 json bytes, level_extracted regexp 1h 434 ms 448 ms ⚪ +3% 94 ms 4.77× ✅ same
⚪ X5 logfmt filter level_extracted, by level 1h 737 ms 696 ms ⚪ -6% 56 ms 12× ✅ same
⚪ E1 logs, json parser over stream labels 1h 118 ms 114 ms ⚪ -3% 63 ms 1.81× ✅ same
⚪ E2 logs, logfmt parser over stream labels 1h 84 ms 78 ms ⚪ -7% 53 ms 1.47× ✅ same
⚪ E3 logs, json, existence filter on level_extracted 1h 151 ms 145 ms ⚪ -4% 81 ms 1.79× ✅ same
⚪ E4 logs, logfmt, existence filter on level_extracted 1h 99 ms 89 ms ⚪ -10% 57 ms 1.56× ✅ same
⚪ E5 logs, json, drop level_extracted 1h 116 ms 111 ms ⚪ -4% 62 ms 1.79× ✅ same
⚪ E6 logfmt count by level_extracted 1h 46 ms 46 ms ⚪ +0% 8 ms 5.75× ✅ same
⚪ E7 json count by level_extracted 1h 163 ms 159 ms ⚪ -2% 16 ms 9.94× ✅ same
⚪ E8 instant logfmt by level_extracted instant 7 ms 7 ms ⚪ +0% 11 ms 0.64× ✅ same
⚪ A explore volume, 2 filters, drop 1h 174 ms 167 ms ⚪ -4% 110 ms 1.52× ✅ same
⚪ B grouped sum, filter, no drop 1h 106 ms 101 ms ⚪ -5% 37 ms 2.73× ✅ same
⚪ C ungrouped sum, filter, no drop 1h 102 ms 104 ms ⚪ +2% 35 ms 2.97× ✅ same
⚪ D volume, no filters 1h 227 ms 230 ms ⚪ +1% 47 ms 4.89× ✅ same
⚪ E field breakdown pipeline (explore) 1h 101 ms 103 ms ⚪ +2% 37 ms 2.78× ✅ same
⚪ F field breakdown service_version (explore) 1h 147 ms 166 ms ⚪ +13% 43 ms 3.86× ✅ same
⚪ G field breakdown pipeline (drilldown) 1h 59 ms 59 ms ⚪ +0% 23 ms 2.57× ✅ same
⚪ H field breakdown service_version (drilldown) 1h 88 ms 93 ms ⚪ +6% 25 ms 3.72× ✅ same
⚪ I grafana volume of B 1h 98 ms 100 ms ⚪ +2% 36 ms 2.78× ✅ same
⚪ O2 explore log volume (Grafana form), underscore structured-metadata filter 1h 70 ms 70 ms ⚪ +0% 36 ms 1.94× ✅ same
⚪ DL1 drilldown field breakdown json-expr, level filter 1h 489 ms 485 ms ⚪ -1% 23 ms 21× ✅ same
⚪ DL2 drilldown field breakdown, level + stream-label filter before json 1h 49 ms 52 ms ⚪ +6% 8 ms 6.50× ✅ same
⚪ DL3 drilldown logfmt field breakdown, level filter 1h 624 ms 634 ms ⚪ +2% 92 ms 6.89× ➖ differs (as base)
⚪ DL4 instant count, level filter, json+logfmt, 1h instant 522 ms 514 ms ⚪ -2% 1.35 s 0.38× ✅ sum ±0.29%
⚪ DL6 explore volume, level filter before json 1h 500 ms 499 ms ⚪ -0% 41 ms 12× ✅ sum ±0.30%
⚪ OR1 logs, or alternatives 1h 86 ms 77 ms ⚪ -10% 68 ms 1.13× ✅ same
⚪ OR2 logs, negated or alternatives 1h 73 ms 68 ms ⚪ -7% 50 ms 1.36× ✅ same
⚪ OR3 logs, regexp or alternatives 1h 67 ms 63 ms ⚪ -6% 71 ms 0.89× ✅ same
⚪ OR4 count by level, or alternatives with parser 1h 83 ms 84 ms ⚪ +1% 32 ms 2.62× ✅ same
⚪ OR5 rate, negated regexp or alternatives 1h 59 ms 59 ms ⚪ +0% 90 ms 0.66× ✅ same
⚪ OR6 instant, or alternatives instant 8 ms 9 ms ⚪ +12% 66 ms 0.14× ✅ same
⚪ P1 api-gateway empty pattern 1h 24 ms 24 ms ⚪ +0% 7 ms 3.43× ✅ same
⚪ P2 api-gateway not empty pattern, line filter 1h 76 ms 78 ms ⚪ +3% 21 ms 3.71× ✅ same
⚪ P3 nginx count_over_time, pattern with spaces 1h 14 ms 13 ms ⚪ -7% 7 ms 1.86× ✅ same
⚪ P4 nginx count_over_time, GET request pattern 1h 15 ms 15 ms ⚪ +0% 6 ms 2.50× ✅ same
⚪ A1 nginx include GET, log query 1h 18 ms 19 ms ⚪ +6% 11 ms 1.73× ✅ same
⚪ A2 nginx exclude GET, log query 1h 21 ms 21 ms ⚪ +0% 15 ms 1.40× ✅ same
⚪ A3 nginx include GET, count_over_time 1h 1 ms 1 ms ⚪ +0% 2 ms 0.50× ✅ same
⚪ A4 nginx exclude GET, count_over_time 1h 20 ms 21 ms ⚪ +5% 7 ms 3.00× ✅ same
⚪ A5 drilldown exclude, volume by detected_level 1h 25 ms 24 ms ⚪ -4% 6 ms 4.00× ✅ same
⚪ A6 nginx include ends on a literal, log query 1h 14 ms 15 ms ⚪ +7% 5 ms 3.00× ✅ same
⚪ A7 nginx exclude ends on a literal, log query 1h 17 ms 17 ms ⚪ +0% 16 ms 1.06× ✅ same
⚪ A8 nginx include two literals, count_over_time 1h 26 ms 26 ms ⚪ +0% 6 ms 4.33× ✅ same
⚪ A9 nginx include two literals, ends on a literal, count_over_time 1h 23 ms 23 ms ⚪ +0% 6 ms 3.83× ✅ same
⚪ P1 logs, json, level equals 1h 135 ms 128 ms ⚪ -5% 80 ms 1.60× ✅ same
⚪ P2 logs, logfmt, level not equal 1h 31 ms 32 ms ⚪ +3% 5 ms 6.40× ✅ same
⚪ P3 logs, json, level existence 1h 132 ms 130 ms ⚪ -2% 68 ms 1.91× ✅ same
⚪ P4 logfmt count by level 1h 33 ms 33 ms ⚪ +0% 7 ms 4.71× ✅ same
⚪ P5 json count by level 1h 87 ms 90 ms ⚪ +3% 16 ms 5.62× ✅ same
⚪ P6 json count, level filter 1h 20 ms 17 ms ⚪ -15% 14 ms 1.21× ✅ same
⚪ P7 json rate by level, level regexp 1h 18 ms 19 ms ⚪ +6% 15 ms 1.27× ✅ same
⚪ P8 json count by a name that is no stream label 1h 93 ms 89 ms ⚪ -4% 14 ms 6.36× ✅ same
⚪ P9 instant logfmt by level instant 6 ms 6 ms ⚪ +0% 10 ms 0.60× ✅ same
⚪ E1 json duration_ms sum by service 1h 91 ms 92 ms ⚪ +1% 16 ms 5.75× ➖ differs (as base)
⚪ E2 json duration_ms p95 by service 1h 326 ms 336 ms ⚪ +3% 16 ms 21× ✅ same
⚪ E3 logfmt latency_ms rate, production 1h 488 ms 500 ms ⚪ +2% 128 ms 3.91× ➖ differs (as base)
⚪ E4 logfmt size_bytes max by service 1h 48 ms 46 ms ⚪ -4% 16 ms 2.88× ➖ differs (as base)
⚪ E5 json duration_ms sum, instant instant 30 ms 29 ms ⚪ -3% 28 ms 1.04× ✅ same
⚪ E6 logfmt ttl unit string (Loki 400) 1h 400 400 ⚪ +3% 400 — ✅ same
⚪ E7 json hexadecimal trace_id (Loki 400) 1h 400 400 ⚪ +0% 400 — ✅ same
⚪ E8 json duration_ms sum by service, namespace prod 1h 193 ms 194 ms ⚪ +1% 82 ms 2.37× ➖ differs (as base)
⚪ E9 logfmt latency_ms sum by service, namespace prod 1h 302 ms 299 ms ⚪ -1% 90 ms 3.32× ➖ differs (as base)
⚪ U1 logfmt amount rate 1h 39 ms 37 ms ⚪ -5% 14 ms 2.64× ✅ same
⚪ U2 json duration_ms rate 1h 91 ms 92 ms ⚪ +1% 24 ms 3.83× ✅ same
⚪ U3 json duration_ms rate, error filter 1h 91 ms 90 ms ⚪ -1% 29 ms 3.10× ✅ same
⚪ U4 logfmt latency_ms rate, production 1h 351 ms 353 ms ⚪ +1% 126 ms 2.80× ➖ differs (as base)
⚪ U5 logfmt amount rate, instant instant 8 ms 7 ms ⚪ -12% 12 ms 0.58× ✅ same
⚪ U6 json duration_ms rate, instant instant 13 ms 13 ms ⚪ +0% 20 ms 0.65× ✅ same
⚪ U7 json duration_ms sum_over_time, instant instant 16 ms 16 ms ⚪ +0% 21 ms 0.76× ✅ same
⚪ U8 logfmt amount rate by service (grouped) 1h 44 ms 43 ms ⚪ -2% 13 ms 3.31× ✅ same
⚪ U9 logfmt amount rate_counter (folded per series) 1h 230 ms 224 ms ⚪ -3% 33 ms 6.79× ➖ differs (as base)
⚪ U1 json duration_ms sum by service 1h 93 ms 86 ms ⚪ -8% 16 ms 5.37× ➖ differs (as base)
⚪ U10 instant sum_over_time unwrap instant 29 ms 31 ms ⚪ +7% 29 ms 1.07× ✅ same
⚪ U11 instant max_over_time missing label instant 6 ms 5 ms ⚪ -17% 16 ms 0.31× ✅ same
⚪ U12 json duration_ms over every service 1h 248 ms 255 ms ⚪ +3% 44 ms 5.80× ➖ differs (as base)
⚪ U13 logfmt latency_ms over every service 1h 506 ms 503 ms ⚪ -1% 58 ms 8.67× ➖ differs (as base)
⚪ U14 duration() of a unit string 1h 47 ms 44 ms ⚪ -6% 8 ms 5.50× ➖ differs (as base)
⚪ U2 json duration_ms max by service 1h 98 ms 103 ms ⚪ +5% 43 ms 2.40× ➖ differs (as base)
⚪ U3 json duration_ms sliding sum 1h 92 ms 86 ms ⚪ -7% 34 ms 2.53× ➖ differs (as base)
⚪ U4 logfmt size_bytes sum by service 1h 41 ms 39 ms ⚪ -5% 7 ms 5.57× ➖ differs (as base)
⚪ U5 logfmt ttl unit string (no sample) 1h 41 ms 41 ms ⚪ +0% 7 ms 5.86× ✅ same
⚪ U6 missing label, no parser 1h 23 ms 23 ms ⚪ +0% 10 ms 2.30× ✅ same
⚪ U7 missing label, ungrouped sum 1h 22 ms 22 ms ⚪ +0% 9 ms 2.44× ✅ same
⚪ U8 rate of an unwrapped label 1h 93 ms 89 ms ⚪ -4% 16 ms 5.56× ✅ same
⚪ U9 bytes() conversion 1h 52 ms 54 ms ⚪ +4% 12 ms 4.50× ➖ differs (as base)
Cold (first-run) timings — what a user opening a panel sees
shape range base cold PR cold Loki cold PR ÷ Loki cold
bytes_over_time by app 1h 73 ms 73 ms 729 ms 0.10×
drilldown service landing 1h 39 ms 38 ms 522 ms 0.07×
instant json filtered instant 390 ms 386 ms 77 ms 5.01×
instant json volume instant 441 ms 428 ms 102 ms 4.20×
instant ungrouped rate instant 8 ms 8 ms 76 ms 0.11×
json rate by level (no filter, no drop) 1h 400 400 400 —
json volume no filters 1h 204 ms 211 ms 3 ms 70.33×
logfmt count by level, filter, drop 1h 437 ms 436 ms 976 ms 0.45×
logfmt volume 1h 250 ms 239 ms 1.08 s 0.22×
logs plain 1h 96 ms 80 ms 45 ms 1.78×
logs | json 1h 124 ms 105 ms 65 ms 1.62×
logs | logfmt 1h 171 ms 166 ms 56 ms 2.96×
stream-label count by app 1h 26 ms 29 ms 517 ms 0.06×
topk rate by app 1h 64 ms 69 ms 566 ms 0.12×
ungrouped rate 1h 12 ms 12 ms 679 ms 0.02×
DB3 json field breakdown user_id 1h 69 ms 53 ms 643 ms 0.08×
DB4 json field breakdown batch_id 1h 99 ms 126 ms 497 ms 0.25×
X1 json filter level_extracted, by level 1h 3.99 s 3.97 s 779 ms 5.10×
X2 json group by level_extracted 1h 383 ms 345 ms 685 ms 0.50×
X3 json rate, level_extracted equality 1h 310 ms 312 ms 513 ms 0.61×
X4 json bytes, level_extracted regexp 1h 448 ms 443 ms 769 ms 0.58×
X5 logfmt filter level_extracted, by level 1h 704 ms 703 ms 914 ms 0.77×
E1 logs, json parser over stream labels 1h 147 ms 121 ms 66 ms 1.83×
E2 logs, logfmt parser over stream labels 1h 77 ms 68 ms 56 ms 1.21×
E3 logs, json, existence filter on level_extracted 1h 154 ms 144 ms 215 ms 0.67×
E4 logs, logfmt, existence filter on level_extracted 1h 102 ms 95 ms 69 ms 1.38×
E5 logs, json, drop level_extracted 1h 124 ms 115 ms 61 ms 1.89×
E6 logfmt count by level_extracted 1h 46 ms 46 ms 37 ms 1.24×
E7 json count by level_extracted 1h 1.58 s 1.56 s 180 ms 8.66×
E8 instant logfmt by level_extracted instant 8 ms 9 ms 10 ms 0.90×
A explore volume, 2 filters, drop 1h 2.60 s 1.83 s 1.15 s 1.60×
B grouped sum, filter, no drop 1h 126 ms 129 ms 485 ms 0.27×
C ungrouped sum, filter, no drop 1h 124 ms 123 ms 487 ms 0.25×
D volume, no filters 1h 211 ms 213 ms 855 ms 0.25×
E field breakdown pipeline (explore) 1h 108 ms 106 ms 476 ms 0.22×
F field breakdown service_version (explore) 1h 1.49 s 1.47 s 528 ms 2.77×
G field breakdown pipeline (drilldown) 1h 47 ms 45 ms 674 ms 0.07×
H field breakdown service_version (drilldown) 1h 144 ms 142 ms 520 ms 0.27×
I grafana volume of B 1h 120 ms 127 ms 470 ms 0.27×
O2 explore log volume (Grafana form), underscore structured-metadata filter 1h 176 ms 153 ms 494 ms 0.31×
DL1 drilldown field breakdown json-expr, level filter 1h 499 ms 482 ms 412 ms 1.17×
DL2 drilldown field breakdown, level + stream-label filter before json 1h 86 ms 85 ms 28 ms 3.04×
DL3 drilldown logfmt field breakdown, level filter 1h 645 ms 642 ms 897 ms 0.72×
DL4 instant count, level filter, json+logfmt, 1h instant 521 ms 514 ms 1.38 s 0.37×
DL6 explore volume, level filter before json 1h 1.02 s 1.00 s 699 ms 1.43×
OR1 logs, or alternatives 1h 101 ms 76 ms 66 ms 1.15×
OR2 logs, negated or alternatives 1h 77 ms 83 ms 52 ms 1.60×
OR3 logs, regexp or alternatives 1h 65 ms 62 ms 70 ms 0.89×
OR4 count by level, or alternatives with parser 1h 127 ms 126 ms 558 ms 0.23×
OR5 rate, negated regexp or alternatives 1h 57 ms 57 ms 603 ms 0.09×
OR6 instant, or alternatives instant 7 ms 8 ms 68 ms 0.12×
P1 api-gateway empty pattern 1h 46 ms 24 ms 60 ms 0.40×
P2 api-gateway not empty pattern, line filter 1h 84 ms 79 ms 21 ms 3.76×
P3 nginx count_over_time, pattern with spaces 1h 13 ms 14 ms 21 ms 0.67×
P4 nginx count_over_time, GET request pattern 1h 22 ms 18 ms 26 ms 0.69×
A1 nginx include GET, log query 1h 35 ms 19 ms 12 ms 1.58×
A2 nginx exclude GET, log query 1h 24 ms 22 ms 12 ms 1.83×
A3 nginx include GET, count_over_time 1h 1 ms 1 ms 2 ms 0.50×
A4 nginx exclude GET, count_over_time 1h 19 ms 22 ms 28 ms 0.79×
A5 drilldown exclude, volume by detected_level 1h 25 ms 24 ms 25 ms 0.96×
A6 nginx include ends on a literal, log query 1h 14 ms 14 ms 24 ms 0.58×
A7 nginx exclude ends on a literal, log query 1h 19 ms 17 ms 16 ms 1.06×
A8 nginx include two literals, count_over_time 1h 25 ms 25 ms 29 ms 0.86×
A9 nginx include two literals, ends on a literal, count_over_time 1h 23 ms 23 ms 25 ms 0.92×
P1 logs, json, level equals 1h 200 ms 151 ms 135 ms 1.12×
P2 logs, logfmt, level not equal 1h 40 ms 32 ms 34 ms 0.94×
P3 logs, json, level existence 1h 126 ms 125 ms 75 ms 1.67×
P4 logfmt count by level 1h 33 ms 34 ms 44 ms 0.77×
P5 json count by level 1h 104 ms 96 ms 159 ms 0.60×
P6 json count, level filter 1h 22 ms 29 ms 163 ms 0.18×
P7 json rate by level, level regexp 1h 18 ms 22 ms 141 ms 0.16×
P8 json count by a name that is no stream label 1h 107 ms 104 ms 123 ms 0.85×
P9 instant logfmt by level instant 6 ms 9 ms 10 ms 0.90×
E1 json duration_ms sum by service 1h 107 ms 90 ms 159 ms 0.57×
E2 json duration_ms p95 by service 1h 344 ms 342 ms 183 ms 1.87×
E3 logfmt latency_ms rate, production 1h 483 ms 485 ms 893 ms 0.54×
E4 logfmt size_bytes max by service 1h 45 ms 46 ms 193 ms 0.24×
E5 json duration_ms sum, instant instant 33 ms 31 ms 32 ms 0.97×
E6 logfmt ttl unit string (Loki 400) 1h 400 400 400 —
E7 json hexadecimal trace_id (Loki 400) 1h 400 400 400 —
E8 json duration_ms sum by service, namespace prod 1h 196 ms 204 ms 647 ms 0.32×
E9 logfmt latency_ms sum by service, namespace prod 1h 291 ms 308 ms 572 ms 0.54×
U1 logfmt amount rate 1h 58 ms 39 ms 47 ms 0.83×
U2 json duration_ms rate 1h 92 ms 93 ms 128 ms 0.73×
U3 json duration_ms rate, error filter 1h 94 ms 91 ms 234 ms 0.39×
U4 logfmt latency_ms rate, production 1h 350 ms 352 ms 829 ms 0.42×
U5 logfmt amount rate, instant instant 8 ms 8 ms 11 ms 0.73×
U6 json duration_ms rate, instant instant 13 ms 15 ms 23 ms 0.65×
U7 json duration_ms sum_over_time, instant instant 17 ms 18 ms 23 ms 0.78×
U8 logfmt amount rate by service (grouped) 1h 43 ms 42 ms 57 ms 0.74×
U9 logfmt amount rate_counter (folded per series) 1h 233 ms 227 ms 470 ms 0.48×
U1 json duration_ms sum by service 1h 107 ms 88 ms 161 ms 0.55×
U10 instant sum_over_time unwrap instant 35 ms 29 ms 29 ms 1.00×
U11 instant max_over_time missing label instant 5 ms 6 ms 16 ms 0.38×
U12 json duration_ms over every service 1h 246 ms 250 ms 599 ms 0.42×
U13 logfmt latency_ms over every service 1h 504 ms 507 ms 1.10 s 0.46×
U14 duration() of a unit string 1h 47 ms 44 ms 38 ms 1.16×
U2 json duration_ms max by service 1h 101 ms 101 ms 862 ms 0.12×
U3 json duration_ms sliding sum 1h 94 ms 87 ms 174 ms 0.50×
U4 logfmt size_bytes sum by service 1h 41 ms 40 ms 42 ms 0.95×
U5 logfmt ttl unit string (no sample) 1h 41 ms 40 ms 40 ms 1.00×
U6 missing label, no parser 1h 23 ms 24 ms 76 ms 0.32×
U7 missing label, ungrouped sum 1h 27 ms 21 ms 65 ms 0.32×
U8 rate of an unwrapped label 1h 95 ms 98 ms 161 ms 0.61×
U9 bytes() conversion 1h 54 ms 52 ms 45 ms 1.16×
Why these shapes
  • internal/translator/translator.go → 103: control/bytes_over_time by app, control/instant json filtered, control/instant json volume, control/instant ungrouped rate, control/json rate by level (no filter, no drop), control/json volume no filters, control/logfmt count by level, filter, drop, control/logfmt volume …
  • internal/translator/parsed_key_variants.go → 59: control/instant json filtered, control/instant json volume, control/json rate by level (no filter, no drop), control/json volume no filters, extracted-pushdown/X1 json filter level_extracted, by level, extracted-pushdown/X2 json group by level_extracted, extracted-pushdown/X3 json rate, level_extracted equality, extracted-pushdown/X4 json bytes, level_extracted regexp …
  • control smoke → 8: control/drilldown service landing, control/instant ungrouped rate, control/json rate by level (no filter, no drop), control/json volume no filters, control/logs plain, control/logs | json, control/stream-label count by app, control/topk rate by app

base 1dcb79e0fe → PR 17ae095659 · 4 runs (first is cold), warm p50 · ranges 1h · noise ±30% and 100 ms · VictoriaLogs restarts 0→0 · 10.4 min. Same runner, one fresh stack, targets interleaved per request. How to read and reproduce: bench/ab/README.md.

@github-actions

Copy link
Copy Markdown
Contributor

PR Quality Report

Compared against base branch main.

Coverage and tests

Signal Base PR Delta
Test count 9738 9739 1
Coverage 87.9% 87.9% 0.0% (stable)

Compatibility

Track Base PR Delta
Loki API 100.0% 11/11 (100.0%) 0.0% (stable)
Logs Drilldown 100.0% 17/17 (100.0%) 0.0% (stable)
VictoriaLogs 100.0% 11/11 (100.0%) 0.0% (stable)

Performance smoke

Lower CPU cost (ns/op) is better. Lower benchmark memory cost (B/op, allocs/op) is better. Higher throughput is better. Lower load-test memory growth is better. Benchmark rows are medians from repeated samples.

Signal Base PR Delta
QueryRange cache-hit CPU cost 3387.0 ns/op 3515.0 ns/op +3.8% (stable)
QueryRange cache-hit memory 1240.0 B/op 1240.0 B/op 0.0% (stable)
QueryRange cache-hit allocations 27.0 allocs/op 27.0 allocs/op 0.0% (stable)
QueryRange cache-bypass CPU cost 4352.0 ns/op 4234.0 ns/op -2.7% (stable)
QueryRange cache-bypass memory 1304.0 B/op 1303.0 B/op -0.1% (stable)
QueryRange cache-bypass allocations 27.0 allocs/op 27.0 allocs/op 0.0% (stable)
Labels cache-hit CPU cost 892.7 ns/op 911.9 ns/op +2.2% (stable)
Labels cache-hit memory 48.0 B/op 48.0 B/op 0.0% (stable)
Labels cache-hit allocations 3.0 allocs/op 3.0 allocs/op 0.0% (stable)
Labels cache-bypass CPU cost 1571.0 ns/op 1512.0 ns/op -3.8% (stable)
Labels cache-bypass memory 399.0 B/op 399.0 B/op 0.0% (stable)
Labels cache-bypass allocations 14.0 allocs/op 14.0 allocs/op 0.0% (stable)

State

  • Coverage, compatibility, and sampled performance are reported here from the same PR workflow.
  • This is a delta report, not a release gate by itself. Required checks still decide merge safety.
  • Performance is a smoke comparison, not a full benchmark lab run.
  • Delta states use the same noise guards as the quality gate (percent + absolute + low-baseline checks), so report labels match merge-gate behavior.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Visual smoke: passed

Base 1dcb79e0fe vs PR c94b583260, Grafana through the proxy builds and Loki on one fresh stack; run.
Core set: 5 capture(s) at 1h. Detailed set: 26 entries (explore-metric-plain, explore-A, explore-B, explore-C, explore-E, explore-F, explore-logs-json, explore-logfmt-metric, ...). 32 capture(s), 15m/1h/6h, 24h and 7d stay out of PR runs.
Trimmed to the 1h range for the capture budget: explore-A, explore-B, explore-C, explore-E, explore-F, explore-logs-json, explore-logfmt-metric, explore-logs-extracted, explore-extracted-metric, explore-extracted-filter-metric, explore-extracted-group-metric, explore-logs-plain-level, explore-plain-level-metric, explore-logs-line-filter-or, explore-metric-line-filter-or, explore-unwrap-sum, explore-unwrap-unit-string, explore-unwrap-missing-label, explore-unwrap-conversion-error, explore-unwrap-rate-sum, explore-empty-pattern-filter, explore-pattern-filter-anchored, dd-field-service_version, dd-field-pipeline.

page range set base = PR (data) vs Loki (PR) pixel diff result
dd-fields 1h core ✅ identical identical (4 explained, 1 history-dependent) 0.11% ✅
dd-landing 1h core ✅ identical identical (3 explained) 0.13% ✅
dd-service-logs 1h core ✅ identical identical (3 explained, 1 history-dependent) 0.11% ✅
explore-logs-plain 1h core ✅ identical identical (1 explained) 0.07% ✅
explore-metric-plain 1h core ✅ identical identical (1 explained) 0.04% ✅
dd-field-pipeline 1h detailed ✅ identical identical (3 explained, 1 history-dependent) 0.11% ✅
dd-field-service_version 1h detailed ✅ identical identical (3 explained, 1 history-dependent) 0.11% ✅
explore-A 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-B 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-C 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-E 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-F 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-empty-pattern-filter 1h detailed ✅ identical identical (1 explained) 0.07% ✅
explore-extracted-filter-metric 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-extracted-group-metric 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-extracted-metric 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-logfmt-metric 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-logs-extracted 1h detailed ✅ identical identical (1 explained) 0.07% ✅
explore-logs-json 1h detailed ✅ identical identical (1 explained) 0.07% ✅
explore-logs-line-filter-or 1h detailed ✅ identical identical (1 explained) 0.07% ✅
explore-logs-plain-level 1h detailed ✅ identical identical (2 explained) 0.07% ✅
explore-metric-line-filter-or 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-metric-plain 15m detailed ✅ identical identical (1 explained) 0.04% ✅
explore-metric-plain 6h detailed ✅ identical n/a (beyond the Loki window) 0.04% ✅
explore-pattern-filter-anchored 1h detailed ✅ identical identical (1 explained) 0.07% ✅
explore-plain-level-metric 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-unwrap-conversion-error 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-unwrap-missing-label 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-unwrap-rate-sum 1h detailed ✅ identical identical (1 explained) 0.04% ✅
explore-unwrap-sum 1h detailed ✅ identical 1 difference(s), 1 on base too; 1 explained 0.04% ✅
explore-unwrap-unit-string 1h detailed ✅ identical identical (1 explained) 0.04% ✅
tail-json-filter live detailed ✅ identical entries in the window: PR 1904, Loki 687, in both 687 7.15% ✅

Gate: a base-vs-PR data difference passes when the PR is closer to Loki, and fails when the PR diverges from Loki or Loki cannot decide it (at a range Loki does not hold, a difference passes when the same page proved it closer to Loki at a shorter range; otherwise label the pull request visual-change-expected to accept an intended change). Also failing: a panel empty on the PR but not on the base, an error banner, panel error, error answer or new "No data" panel on the PR, a PR side that never settled, a difference that did not reproduce on the recapture. Pixel differences only warn.

Core set montages (5): base | PR | Loki

dd-fields-1h

dd-fields-1h

dd-landing-1h

dd-landing-1h

dd-service-logs-1h

dd-service-logs-1h

explore-logs-plain-1h

explore-logs-plain-1h

explore-metric-plain-1h

explore-metric-plain-1h

All montages of this run: pr-visuals/pr-761.

@szibis
szibis merged commit bcb9438 into main Oct 14, 2026
62 checks passed
@szibis
szibis deleted the fix/translator-label-separator-bytes branch October 14, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Bug fix scope/docs Documentation scope/tests Tests scope/translator LogQL translator size/S Small change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant