diff --git a/packages/lib/src/prometheus.ts b/packages/lib/src/prometheus.ts index 2a55ddd7..becdf0cb 100644 --- a/packages/lib/src/prometheus.ts +++ b/packages/lib/src/prometheus.ts @@ -272,18 +272,27 @@ function labelsToKey(labels: LabelValues, metricLabels: string[]) { function keyToLabels(key: string) { let labels = new Map(); - if (key !== "") { - for (let pair of key.split(",")) { - let [name, value] = pair.split("=", 2); - if (!name || value === undefined) { - continue; + let pos = 0; + let matchLabel = /([^=]+)="(([^\\"]|\\["n\\])+)"/y; + while (pos < key.length) { + if (pos !== 0) { + if (key[pos] !== ",") { + throw Error(`Expected , at pos ${pos} in "${key}"`); } + pos += 1; + } + matchLabel.lastIndex = pos; + const match = matchLabel.exec(key); + if (match) { + let [, name, value] = match; labels.set(name, value - .slice(1, -1) .replace(/\\"/g, "\"") .replace(/\\n/g, "\n") .replace(/\\\\/g, "\\") ); + pos += match[0].length; + } else { + throw new Error(`Failed to parse label at pos ${pos} in "${key}"`); } } diff --git a/test/lib/prometheus.js b/test/lib/prometheus.js index b0f24ca3..ade1b09f 100644 --- a/test/lib/prometheus.js +++ b/test/lib/prometheus.js @@ -651,8 +651,21 @@ describe("lib/prometheus", function() { let gauge = new prometheus.Gauge( "test", "Help", { register: false, labels: ["a", "b"] } ); - gauge.labels('x\\\\\n\"\"\n\\', "2"); - gauge.removeAll({ a: 'x\\\\\n\"\"\n\\' }); + + let labelValue = ""; + for (let i = 0; i < 128; i++) { + const char = String.fromCodePoint(i); + if (!/[1-9B-Zb-z]/.test(char)) { // exclude boring characters + labelValue += char; + } + } + labelValue += "©💣"; + + gauge.labels(labelValue, "2"); + gauge.removeAll({ a: labelValue }); + assert(gauge._values.size === 0, "Matching labels remained"); + gauge.labels("1", labelValue); + gauge.removeAll({ a: "1" }); assert(gauge._values.size === 0, "Matching labels remained"); }); });