diff --git a/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts b/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts index 45b1abdad48..d9b4b0f05cd 100644 --- a/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts +++ b/packages/opentelemetry-exporter-prometheus/src/PrometheusSerializer.ts @@ -111,17 +111,19 @@ function stringify( let labelsStr = ''; for (const [key, val] of Object.entries(labels)) { + const sanitizedLabelName = sanitizePrometheusMetricName(key); hasLabel = true; - labelsStr += `${labelsStr.length > 0 ? ',' : ''}${key}="${escapeLabelValue( - val - )}"`; + labelsStr += `${ + labelsStr.length > 0 ? ',' : '' + }${sanitizedLabelName}="${escapeLabelValue(val)}"`; } if (additionalLabels) { for (const [key, val] of Object.entries(additionalLabels)) { + const sanitizedLabelName = sanitizePrometheusMetricName(key); hasLabel = true; labelsStr += `${ labelsStr.length > 0 ? ',' : '' - }${key}="${escapeLabelValue(val)}"`; + }${sanitizedLabelName}="${escapeLabelValue(val)}"`; } } diff --git a/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts b/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts index 4495154f921..7a05e52334c 100644 --- a/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts +++ b/packages/opentelemetry-exporter-prometheus/test/PrometheusSerializer.test.ts @@ -487,6 +487,34 @@ describe('PrometheusSerializer', () => { `} 1 ${mockedHrTimeMs}\n` ); }); + + it('should sanitize label names', async () => { + const serializer = new PrometheusSerializer(); + + const meter = new MeterProvider({ + processor: new ExactProcessor(SumAggregator), + }).getMeter('test'); + const counter = meter.createCounter('test') as CounterMetric; + // if you try to use a label name like account-id prometheus will complain + // with an error like: + // error while linting: text format parsing error in line 282: expected '=' after label name, found '-' + counter + .bind(({ + 'account-id': '123456', + } as unknown) as Labels) + .add(1); + const records = await counter.getMetricRecord(); + const record = records[0]; + + const result = serializer.serializeRecord( + record.descriptor.name, + record + ); + assert.strictEqual( + result, + `test{account_id="123456"} 1 ${mockedHrTimeMs}\n` + ); + }); }); }); });