You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.7 KiB
153 lines
4.7 KiB
// Copyright 2025 The Prometheus Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package schema
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/prometheus/common/model"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/prometheus/prometheus/model/labels"
|
|
"github.com/prometheus/prometheus/util/testutil"
|
|
)
|
|
|
|
func TestMetadata(t *testing.T) {
|
|
testMeta := Metadata{
|
|
Name: "metric_total",
|
|
Type: model.MetricTypeCounter,
|
|
Unit: "seconds",
|
|
}
|
|
|
|
for _, tcase := range []struct {
|
|
emptyName, emptyType, emptyUnit bool
|
|
}{
|
|
{},
|
|
{emptyName: true},
|
|
{emptyType: true},
|
|
{emptyUnit: true},
|
|
{emptyName: true, emptyType: true, emptyUnit: true},
|
|
} {
|
|
var (
|
|
expectedMeta Metadata
|
|
expectedLabels labels.Labels
|
|
)
|
|
{
|
|
// Setup expectations.
|
|
lb := labels.NewScratchBuilder(0)
|
|
lb.Add("foo", "bar")
|
|
|
|
if !tcase.emptyName {
|
|
lb.Add(metricName, testMeta.Name)
|
|
expectedMeta.Name = testMeta.Name
|
|
}
|
|
if !tcase.emptyType {
|
|
lb.Add(metricType, string(testMeta.Type))
|
|
expectedMeta.Type = testMeta.Type
|
|
} else {
|
|
expectedMeta.Type = model.MetricTypeUnknown
|
|
}
|
|
if !tcase.emptyUnit {
|
|
lb.Add(metricUnit, testMeta.Unit)
|
|
expectedMeta.Unit = testMeta.Unit
|
|
}
|
|
lb.Sort()
|
|
expectedLabels = lb.Labels()
|
|
}
|
|
|
|
t.Run(fmt.Sprintf("meta=%#v", expectedMeta), func(t *testing.T) {
|
|
{
|
|
// From labels to Metadata.
|
|
got := NewMetadataFromLabels(expectedLabels)
|
|
require.Equal(t, expectedMeta, got)
|
|
}
|
|
{
|
|
// Empty methods.
|
|
require.Equal(t, tcase.emptyName, expectedMeta.IsEmptyFor(metricName))
|
|
require.Equal(t, tcase.emptyType, expectedMeta.IsEmptyFor(metricType))
|
|
require.Equal(t, tcase.emptyType, expectedMeta.IsTypeEmpty())
|
|
require.Equal(t, tcase.emptyUnit, expectedMeta.IsEmptyFor(metricUnit))
|
|
}
|
|
{
|
|
// From Metadata to labels for various builders.
|
|
slb := labels.NewScratchBuilder(0)
|
|
slb.Add("foo", "bar")
|
|
expectedMeta.AddToLabels(&slb)
|
|
slb.Sort()
|
|
testutil.RequireEqual(t, expectedLabels, slb.Labels())
|
|
|
|
lb := labels.NewBuilder(labels.FromStrings("foo", "bar"))
|
|
expectedMeta.SetToLabels(lb)
|
|
testutil.RequireEqual(t, expectedLabels, lb.Labels())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIgnoreOverriddenMetadataLabelsScratchBuilder(t *testing.T) {
|
|
// PROM-39 specifies that metadata labels should be sourced primarily from the metadata structures.
|
|
// However, the original labels should be preserved IF the metadata structure does not set or support certain information.
|
|
// Test those cases with common label interactions.
|
|
incomingLabels := labels.FromStrings(metricName, "different_name", metricType, string(model.MetricTypeSummary), metricUnit, "MB", "foo", "bar")
|
|
for _, tcase := range []struct {
|
|
highPrioMeta Metadata
|
|
expectedLabels labels.Labels
|
|
}{
|
|
{
|
|
expectedLabels: incomingLabels,
|
|
},
|
|
{
|
|
highPrioMeta: Metadata{
|
|
Name: "metric_total",
|
|
Type: model.MetricTypeCounter,
|
|
Unit: "seconds",
|
|
},
|
|
expectedLabels: labels.FromStrings(metricName, "metric_total", metricType, string(model.MetricTypeCounter), metricUnit, "seconds", "foo", "bar"),
|
|
},
|
|
{
|
|
highPrioMeta: Metadata{
|
|
Name: "metric_total",
|
|
Type: model.MetricTypeCounter,
|
|
},
|
|
expectedLabels: labels.FromStrings(metricName, "metric_total", metricType, string(model.MetricTypeCounter), metricUnit, "MB", "foo", "bar"),
|
|
},
|
|
{
|
|
highPrioMeta: Metadata{
|
|
Type: model.MetricTypeCounter,
|
|
Unit: "seconds",
|
|
},
|
|
expectedLabels: labels.FromStrings(metricName, "different_name", metricType, string(model.MetricTypeCounter), metricUnit, "seconds", "foo", "bar"),
|
|
},
|
|
{
|
|
highPrioMeta: Metadata{
|
|
Name: "metric_total",
|
|
Type: model.MetricTypeUnknown,
|
|
Unit: "seconds",
|
|
},
|
|
expectedLabels: labels.FromStrings(metricName, "metric_total", metricType, string(model.MetricTypeSummary), metricUnit, "seconds", "foo", "bar"),
|
|
},
|
|
} {
|
|
t.Run(fmt.Sprintf("meta=%#v", tcase.highPrioMeta), func(t *testing.T) {
|
|
lb := labels.NewScratchBuilder(0)
|
|
tcase.highPrioMeta.AddToLabels(&lb)
|
|
wrapped := &IgnoreOverriddenMetadataLabelsScratchBuilder{ScratchBuilder: &lb, Overwrite: tcase.highPrioMeta}
|
|
incomingLabels.Range(func(l labels.Label) {
|
|
wrapped.Add(l.Name, l.Value)
|
|
})
|
|
lb.Sort()
|
|
require.Equal(t, tcase.expectedLabels, lb.Labels())
|
|
})
|
|
}
|
|
}
|
|
|