mirror of
https://github.com/prometheus/prometheus.git
synced 2025-11-02 01:11:01 +01:00
Merge branch 'release-3.7' into krajo/merge-release-3071-to-main
This commit is contained in:
commit
ea398c15e8
@ -2,6 +2,10 @@
|
||||
|
||||
## main / unreleased
|
||||
|
||||
## 3.7.1 / 2025-10-16
|
||||
|
||||
* [BUGFIX] OTLP: Prefix `key_` to label name when translating an OTel attribute name starting with a single underscore, and keep multiple consecutive underscores in label name when translating an OTel attribute name. This reverts the breaking changes introduced in 3.7.0. #17344
|
||||
|
||||
## 3.7.0 / 2025-10-15
|
||||
|
||||
* [CHANGE] Remote-write: the following metrics are deprecated:
|
||||
|
||||
@ -88,7 +88,11 @@ func (c *PrometheusConverter) createAttributes(resource pcommon.Resource, attrib
|
||||
c.scratchBuilder.Sort()
|
||||
sortedLabels := c.scratchBuilder.Labels()
|
||||
|
||||
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: settings.AllowUTF8}
|
||||
labelNamer := otlptranslator.LabelNamer{
|
||||
UTF8Allowed: settings.AllowUTF8,
|
||||
UnderscoreLabelSanitization: settings.LabelNameUnderscoreSanitization,
|
||||
PreserveMultipleUnderscores: settings.LabelNamePreserveMultipleUnderscores,
|
||||
}
|
||||
|
||||
if settings.AllowUTF8 {
|
||||
// UTF8 is allowed, so conflicts aren't possible.
|
||||
@ -118,7 +122,7 @@ func (c *PrometheusConverter) createAttributes(resource pcommon.Resource, attrib
|
||||
}
|
||||
}
|
||||
|
||||
err := settings.PromoteResourceAttributes.addPromotedAttributes(c.builder, resourceAttrs, settings.AllowUTF8)
|
||||
err := settings.PromoteResourceAttributes.addPromotedAttributes(c.builder, resourceAttrs, labelNamer)
|
||||
if err != nil {
|
||||
return labels.EmptyLabels(), err
|
||||
}
|
||||
|
||||
@ -67,15 +67,35 @@ func TestCreateAttributes(t *testing.T) {
|
||||
attrs.PutStr("metric-attr", "metric value")
|
||||
attrs.PutStr("metric-attr-other", "metric value other")
|
||||
|
||||
// Setup resources with underscores for sanitization tests
|
||||
resourceAttrsWithUnderscores := map[string]string{
|
||||
"service.name": "service name",
|
||||
"service.instance.id": "service ID",
|
||||
"_private": "private value",
|
||||
"__reserved__": "reserved value",
|
||||
"label___multi": "multi value",
|
||||
}
|
||||
resourceWithUnderscores := pcommon.NewResource()
|
||||
for k, v := range resourceAttrsWithUnderscores {
|
||||
resourceWithUnderscores.Attributes().PutStr(k, v)
|
||||
}
|
||||
attrsWithUnderscores := pcommon.NewMap()
|
||||
attrsWithUnderscores.PutStr("_metric_private", "private metric")
|
||||
attrsWithUnderscores.PutStr("metric___multi", "multi metric")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
scope scope
|
||||
promoteAllResourceAttributes bool
|
||||
promoteResourceAttributes []string
|
||||
promoteScope bool
|
||||
ignoreResourceAttributes []string
|
||||
ignoreAttrs []string
|
||||
expectedLabels labels.Labels
|
||||
name string
|
||||
resource pcommon.Resource
|
||||
attrs pcommon.Map
|
||||
scope scope
|
||||
promoteAllResourceAttributes bool
|
||||
promoteResourceAttributes []string
|
||||
promoteScope bool
|
||||
ignoreResourceAttributes []string
|
||||
ignoreAttrs []string
|
||||
labelNameUnderscoreLabelSanitization bool
|
||||
labelNamePreserveMultipleUnderscores bool
|
||||
expectedLabels labels.Labels
|
||||
}{
|
||||
{
|
||||
name: "Successful conversion without resource attribute promotion and without scope promotion",
|
||||
@ -251,6 +271,121 @@ func TestCreateAttributes(t *testing.T) {
|
||||
"otel_scope_attr2", "value2",
|
||||
),
|
||||
},
|
||||
// Label sanitization test cases
|
||||
{
|
||||
name: "Underscore sanitization enabled - prepends key_ to labels starting with single _",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"key_private", "private value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Underscore sanitization disabled - keeps labels with _ as-is",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"_private", "private value",
|
||||
"_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Multiple underscores preserved - keeps consecutive underscores",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"label___multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Multiple underscores collapsed - collapses to single underscore",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"label_multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Both sanitization options enabled",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private", "label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"key_private", "private value",
|
||||
"label___multi", "multi value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Both sanitization options disabled",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private", "label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"_private", "private value",
|
||||
"label_multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Reserved labels (starting with __) are never modified",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"__reserved__"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"__reserved__", "reserved value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@ -261,9 +396,24 @@ func TestCreateAttributes(t *testing.T) {
|
||||
PromoteResourceAttributes: tc.promoteResourceAttributes,
|
||||
IgnoreResourceAttributes: tc.ignoreResourceAttributes,
|
||||
}),
|
||||
PromoteScopeMetadata: tc.promoteScope,
|
||||
PromoteScopeMetadata: tc.promoteScope,
|
||||
LabelNameUnderscoreSanitization: tc.labelNameUnderscoreLabelSanitization,
|
||||
LabelNamePreserveMultipleUnderscores: tc.labelNamePreserveMultipleUnderscores,
|
||||
}
|
||||
lbls, err := c.createAttributes(resource, attrs, tc.scope, settings, tc.ignoreAttrs, false, Metadata{}, model.MetricNameLabel, "test_metric")
|
||||
// Use test case specific resource/attrs if provided, otherwise use defaults
|
||||
// Check if tc.resource is initialized (non-zero) by trying to get its attributes
|
||||
testResource := resource
|
||||
testAttrs := attrs
|
||||
// For pcommon types, we can check if they're non-zero by seeing if they have attributes
|
||||
// Since zero-initialized Resource is not valid, we use a simple heuristic:
|
||||
// if the struct has been explicitly set in the test case, use it
|
||||
if tc.resource != (pcommon.Resource{}) {
|
||||
testResource = tc.resource
|
||||
}
|
||||
if tc.attrs != (pcommon.Map{}) {
|
||||
testAttrs = tc.attrs
|
||||
}
|
||||
lbls, err := c.createAttributes(testResource, testAttrs, tc.scope, settings, tc.ignoreAttrs, false, Metadata{}, model.MetricNameLabel, "test_metric")
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.RequireEqual(t, lbls, tc.expectedLabels)
|
||||
|
||||
@ -54,6 +54,12 @@ type Settings struct {
|
||||
// PromoteScopeMetadata controls whether to promote OTel scope metadata to metric labels.
|
||||
PromoteScopeMetadata bool
|
||||
EnableTypeAndUnitLabels bool
|
||||
// LabelNameUnderscoreSanitization controls whether to enable prepending of 'key' to labels
|
||||
// starting with '_'. Reserved labels starting with `__` are not modified.
|
||||
LabelNameUnderscoreSanitization bool
|
||||
// LabelNamePreserveMultipleUnderscores enables preserving of multiple
|
||||
// consecutive underscores in label names when AllowUTF8 is false.
|
||||
LabelNamePreserveMultipleUnderscores bool
|
||||
}
|
||||
|
||||
// PrometheusConverter converts from OTel write format to Prometheus remote write format.
|
||||
@ -305,12 +311,11 @@ func NewPromoteResourceAttributes(otlpCfg config.OTLPConfig) *PromoteResourceAtt
|
||||
}
|
||||
|
||||
// addPromotedAttributes adds labels for promoted resourceAttributes to the builder.
|
||||
func (s *PromoteResourceAttributes) addPromotedAttributes(builder *labels.Builder, resourceAttributes pcommon.Map, allowUTF8 bool) error {
|
||||
func (s *PromoteResourceAttributes) addPromotedAttributes(builder *labels.Builder, resourceAttributes pcommon.Map, labelNamer otlptranslator.LabelNamer) error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: allowUTF8}
|
||||
if s.promoteAll {
|
||||
var err error
|
||||
resourceAttributes.Range(func(name string, value pcommon.Value) bool {
|
||||
|
||||
@ -680,6 +680,10 @@ func (rw *rwExporter) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) er
|
||||
AllowDeltaTemporality: rw.allowDeltaTemporality,
|
||||
LookbackDelta: rw.lookbackDelta,
|
||||
EnableTypeAndUnitLabels: rw.enableTypeAndUnitLabels,
|
||||
// For backwards compatibility.
|
||||
LabelNameUnderscoreSanitization: true,
|
||||
// For backwards compatibility.
|
||||
LabelNamePreserveMultipleUnderscores: true,
|
||||
})
|
||||
|
||||
defer func() {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@prometheus-io/mantine-ui",
|
||||
"private": true,
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
@ -28,7 +28,7 @@
|
||||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"@nexucis/fuzzy": "^0.5.1",
|
||||
"@nexucis/kvsearch": "^0.9.1",
|
||||
"@prometheus-io/codemirror-promql": "0.307.0",
|
||||
"@prometheus-io/codemirror-promql": "0.307.1",
|
||||
"@reduxjs/toolkit": "^2.9.0",
|
||||
"@tabler/icons-react": "^3.35.0",
|
||||
"@tanstack/react-query": "^5.90.2",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@prometheus-io/codemirror-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"description": "a CodeMirror mode for the PromQL language",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"module": "dist/esm/index.js",
|
||||
@ -29,7 +29,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md",
|
||||
"dependencies": {
|
||||
"@prometheus-io/lezer-promql": "0.307.0",
|
||||
"@prometheus-io/lezer-promql": "0.307.1",
|
||||
"lru-cache": "^11.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@prometheus-io/lezer-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"description": "lezer-based PromQL grammar",
|
||||
"main": "dist/index.cjs",
|
||||
"type": "module",
|
||||
|
||||
14
web/ui/package-lock.json
generated
14
web/ui/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "prometheus-io",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "prometheus-io",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"workspaces": [
|
||||
"mantine-ui",
|
||||
"module/*"
|
||||
@ -24,7 +24,7 @@
|
||||
},
|
||||
"mantine-ui": {
|
||||
"name": "@prometheus-io/mantine-ui",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.19.0",
|
||||
"@codemirror/language": "^6.11.3",
|
||||
@ -42,7 +42,7 @@
|
||||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"@nexucis/fuzzy": "^0.5.1",
|
||||
"@nexucis/kvsearch": "^0.9.1",
|
||||
"@prometheus-io/codemirror-promql": "0.307.0",
|
||||
"@prometheus-io/codemirror-promql": "0.307.1",
|
||||
"@reduxjs/toolkit": "^2.9.0",
|
||||
"@tabler/icons-react": "^3.35.0",
|
||||
"@tanstack/react-query": "^5.90.2",
|
||||
@ -87,10 +87,10 @@
|
||||
},
|
||||
"module/codemirror-promql": {
|
||||
"name": "@prometheus-io/codemirror-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prometheus-io/lezer-promql": "0.307.0",
|
||||
"@prometheus-io/lezer-promql": "0.307.1",
|
||||
"lru-cache": "^11.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -120,7 +120,7 @@
|
||||
},
|
||||
"module/lezer-promql": {
|
||||
"name": "@prometheus-io/lezer-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@lezer/generator": "^1.8.0",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "prometheus-io",
|
||||
"description": "Monorepo for the Prometheus UI",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "bash build_ui.sh --all",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user