mirror of https://github.com/prometheus/prometheus
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.
442 lines
12 KiB
442 lines
12 KiB
// Copyright 2024 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. |
|
// Provenance-includes-location: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/debbf30360b8d3a0ded8db09c4419d2a9c99b94a/pkg/translator/prometheusremotewrite/helper_test.go |
|
// Provenance-includes-license: Apache-2.0 |
|
// Provenance-includes-copyright: Copyright The OpenTelemetry Authors. |
|
|
|
package prometheusremotewrite |
|
|
|
import ( |
|
"context" |
|
"testing" |
|
"time" |
|
|
|
"github.com/stretchr/testify/assert" |
|
"go.opentelemetry.io/collector/pdata/pcommon" |
|
"go.opentelemetry.io/collector/pdata/pmetric" |
|
|
|
"github.com/prometheus/common/model" |
|
|
|
"github.com/prometheus/prometheus/prompb" |
|
) |
|
|
|
func TestCreateAttributes(t *testing.T) { |
|
resourceAttrs := map[string]string{ |
|
"service.name": "service name", |
|
"service.instance.id": "service ID", |
|
"existent-attr": "resource value", |
|
// This one is for testing conflict with metric attribute. |
|
"metric-attr": "resource value", |
|
// This one is for testing conflict with auto-generated job attribute. |
|
"job": "resource value", |
|
// This one is for testing conflict with auto-generated instance attribute. |
|
"instance": "resource value", |
|
} |
|
|
|
resource := pcommon.NewResource() |
|
for k, v := range resourceAttrs { |
|
resource.Attributes().PutStr(k, v) |
|
} |
|
attrs := pcommon.NewMap() |
|
attrs.PutStr("metric-attr", "metric value") |
|
|
|
testCases := []struct { |
|
name string |
|
promoteResourceAttributes []string |
|
expectedLabels []prompb.Label |
|
}{ |
|
{ |
|
name: "Successful conversion without resource attribute promotion", |
|
promoteResourceAttributes: nil, |
|
expectedLabels: []prompb.Label{ |
|
{ |
|
Name: "__name__", |
|
Value: "test_metric", |
|
}, |
|
{ |
|
Name: "instance", |
|
Value: "service ID", |
|
}, |
|
{ |
|
Name: "job", |
|
Value: "service name", |
|
}, |
|
{ |
|
Name: "metric_attr", |
|
Value: "metric value", |
|
}, |
|
}, |
|
}, |
|
{ |
|
name: "Successful conversion with resource attribute promotion", |
|
promoteResourceAttributes: []string{"non-existent-attr", "existent-attr"}, |
|
expectedLabels: []prompb.Label{ |
|
{ |
|
Name: "__name__", |
|
Value: "test_metric", |
|
}, |
|
{ |
|
Name: "instance", |
|
Value: "service ID", |
|
}, |
|
{ |
|
Name: "job", |
|
Value: "service name", |
|
}, |
|
{ |
|
Name: "metric_attr", |
|
Value: "metric value", |
|
}, |
|
{ |
|
Name: "existent_attr", |
|
Value: "resource value", |
|
}, |
|
}, |
|
}, |
|
{ |
|
name: "Successful conversion with resource attribute promotion, conflicting resource attributes are ignored", |
|
promoteResourceAttributes: []string{"non-existent-attr", "existent-attr", "metric-attr", "job", "instance"}, |
|
expectedLabels: []prompb.Label{ |
|
{ |
|
Name: "__name__", |
|
Value: "test_metric", |
|
}, |
|
{ |
|
Name: "instance", |
|
Value: "service ID", |
|
}, |
|
{ |
|
Name: "job", |
|
Value: "service name", |
|
}, |
|
{ |
|
Name: "existent_attr", |
|
Value: "resource value", |
|
}, |
|
{ |
|
Name: "metric_attr", |
|
Value: "metric value", |
|
}, |
|
}, |
|
}, |
|
{ |
|
name: "Successful conversion with resource attribute promotion, attributes are only promoted once", |
|
promoteResourceAttributes: []string{"existent-attr", "existent-attr"}, |
|
expectedLabels: []prompb.Label{ |
|
{ |
|
Name: "__name__", |
|
Value: "test_metric", |
|
}, |
|
{ |
|
Name: "instance", |
|
Value: "service ID", |
|
}, |
|
{ |
|
Name: "job", |
|
Value: "service name", |
|
}, |
|
{ |
|
Name: "existent_attr", |
|
Value: "resource value", |
|
}, |
|
{ |
|
Name: "metric_attr", |
|
Value: "metric value", |
|
}, |
|
}, |
|
}, |
|
} |
|
for _, tc := range testCases { |
|
t.Run(tc.name, func(t *testing.T) { |
|
settings := Settings{ |
|
PromoteResourceAttributes: tc.promoteResourceAttributes, |
|
} |
|
lbls := createAttributes(resource, attrs, settings, nil, false, model.MetricNameLabel, "test_metric") |
|
|
|
assert.ElementsMatch(t, lbls, tc.expectedLabels) |
|
}) |
|
} |
|
} |
|
|
|
func Test_convertTimeStamp(t *testing.T) { |
|
tests := []struct { |
|
name string |
|
arg pcommon.Timestamp |
|
want int64 |
|
}{ |
|
{"zero", 0, 0}, |
|
{"1ms", 1_000_000, 1}, |
|
{"1s", pcommon.Timestamp(time.Unix(1, 0).UnixNano()), 1000}, |
|
} |
|
for _, tt := range tests { |
|
t.Run(tt.name, func(t *testing.T) { |
|
got := convertTimeStamp(tt.arg) |
|
assert.Equal(t, tt.want, got) |
|
}) |
|
} |
|
} |
|
|
|
func TestPrometheusConverter_AddSummaryDataPoints(t *testing.T) { |
|
ts := pcommon.Timestamp(time.Now().UnixNano()) |
|
tests := []struct { |
|
name string |
|
metric func() pmetric.Metric |
|
want func() map[uint64]*prompb.TimeSeries |
|
}{ |
|
{ |
|
name: "summary with start time", |
|
metric: func() pmetric.Metric { |
|
metric := pmetric.NewMetric() |
|
metric.SetName("test_summary") |
|
metric.SetEmptySummary() |
|
|
|
dp := metric.Summary().DataPoints().AppendEmpty() |
|
dp.SetTimestamp(ts) |
|
dp.SetStartTimestamp(ts) |
|
|
|
return metric |
|
}, |
|
want: func() map[uint64]*prompb.TimeSeries { |
|
labels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_summary" + countStr}, |
|
} |
|
createdLabels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_summary" + createdSuffix}, |
|
} |
|
sumLabels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_summary" + sumStr}, |
|
} |
|
return map[uint64]*prompb.TimeSeries{ |
|
timeSeriesSignature(labels): { |
|
Labels: labels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
timeSeriesSignature(sumLabels): { |
|
Labels: sumLabels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
timeSeriesSignature(createdLabels): { |
|
Labels: createdLabels, |
|
Samples: []prompb.Sample{ |
|
{Value: float64(convertTimeStamp(ts)), Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
} |
|
}, |
|
}, |
|
{ |
|
name: "summary without start time", |
|
metric: func() pmetric.Metric { |
|
metric := pmetric.NewMetric() |
|
metric.SetName("test_summary") |
|
metric.SetEmptySummary() |
|
|
|
dp := metric.Summary().DataPoints().AppendEmpty() |
|
dp.SetTimestamp(ts) |
|
|
|
return metric |
|
}, |
|
want: func() map[uint64]*prompb.TimeSeries { |
|
labels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_summary" + countStr}, |
|
} |
|
sumLabels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_summary" + sumStr}, |
|
} |
|
return map[uint64]*prompb.TimeSeries{ |
|
timeSeriesSignature(labels): { |
|
Labels: labels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
timeSeriesSignature(sumLabels): { |
|
Labels: sumLabels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
} |
|
}, |
|
}, |
|
} |
|
for _, tt := range tests { |
|
t.Run(tt.name, func(t *testing.T) { |
|
metric := tt.metric() |
|
converter := NewPrometheusConverter() |
|
|
|
converter.addSummaryDataPoints( |
|
context.Background(), |
|
metric.Summary().DataPoints(), |
|
pcommon.NewResource(), |
|
Settings{ |
|
ExportCreatedMetric: true, |
|
}, |
|
metric.Name(), |
|
) |
|
|
|
assert.Equal(t, tt.want(), converter.unique) |
|
assert.Empty(t, converter.conflicts) |
|
}) |
|
} |
|
} |
|
|
|
func TestPrometheusConverter_AddHistogramDataPoints(t *testing.T) { |
|
ts := pcommon.Timestamp(time.Now().UnixNano()) |
|
tests := []struct { |
|
name string |
|
metric func() pmetric.Metric |
|
want func() map[uint64]*prompb.TimeSeries |
|
}{ |
|
{ |
|
name: "histogram with start time", |
|
metric: func() pmetric.Metric { |
|
metric := pmetric.NewMetric() |
|
metric.SetName("test_hist") |
|
metric.SetEmptyHistogram().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative) |
|
|
|
pt := metric.Histogram().DataPoints().AppendEmpty() |
|
pt.SetTimestamp(ts) |
|
pt.SetStartTimestamp(ts) |
|
|
|
return metric |
|
}, |
|
want: func() map[uint64]*prompb.TimeSeries { |
|
labels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_hist" + countStr}, |
|
} |
|
createdLabels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_hist" + createdSuffix}, |
|
} |
|
infLabels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_hist_bucket"}, |
|
{Name: model.BucketLabel, Value: "+Inf"}, |
|
} |
|
return map[uint64]*prompb.TimeSeries{ |
|
timeSeriesSignature(infLabels): { |
|
Labels: infLabels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
timeSeriesSignature(labels): { |
|
Labels: labels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
timeSeriesSignature(createdLabels): { |
|
Labels: createdLabels, |
|
Samples: []prompb.Sample{ |
|
{Value: float64(convertTimeStamp(ts)), Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
} |
|
}, |
|
}, |
|
{ |
|
name: "histogram without start time", |
|
metric: func() pmetric.Metric { |
|
metric := pmetric.NewMetric() |
|
metric.SetName("test_hist") |
|
metric.SetEmptyHistogram().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative) |
|
|
|
pt := metric.Histogram().DataPoints().AppendEmpty() |
|
pt.SetTimestamp(ts) |
|
|
|
return metric |
|
}, |
|
want: func() map[uint64]*prompb.TimeSeries { |
|
labels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_hist" + countStr}, |
|
} |
|
infLabels := []prompb.Label{ |
|
{Name: model.MetricNameLabel, Value: "test_hist_bucket"}, |
|
{Name: model.BucketLabel, Value: "+Inf"}, |
|
} |
|
return map[uint64]*prompb.TimeSeries{ |
|
timeSeriesSignature(infLabels): { |
|
Labels: infLabels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
timeSeriesSignature(labels): { |
|
Labels: labels, |
|
Samples: []prompb.Sample{ |
|
{Value: 0, Timestamp: convertTimeStamp(ts)}, |
|
}, |
|
}, |
|
} |
|
}, |
|
}, |
|
} |
|
for _, tt := range tests { |
|
t.Run(tt.name, func(t *testing.T) { |
|
metric := tt.metric() |
|
converter := NewPrometheusConverter() |
|
|
|
converter.addHistogramDataPoints( |
|
context.Background(), |
|
metric.Histogram().DataPoints(), |
|
pcommon.NewResource(), |
|
Settings{ |
|
ExportCreatedMetric: true, |
|
}, |
|
metric.Name(), |
|
) |
|
|
|
assert.Equal(t, tt.want(), converter.unique) |
|
assert.Empty(t, converter.conflicts) |
|
}) |
|
} |
|
} |
|
|
|
func TestGetPromExemplars(t *testing.T) { |
|
ctx := context.Background() |
|
everyN := &everyNTimes{n: 1} |
|
|
|
t.Run("Exemplars with int value", func(t *testing.T) { |
|
pt := pmetric.NewNumberDataPoint() |
|
exemplar := pt.Exemplars().AppendEmpty() |
|
exemplar.SetTimestamp(pcommon.Timestamp(time.Now().UnixNano())) |
|
exemplar.SetIntValue(42) |
|
exemplars, err := getPromExemplars(ctx, everyN, pt) |
|
assert.NoError(t, err) |
|
assert.Len(t, exemplars, 1) |
|
assert.Equal(t, float64(42), exemplars[0].Value) |
|
}) |
|
|
|
t.Run("Exemplars with double value", func(t *testing.T) { |
|
pt := pmetric.NewNumberDataPoint() |
|
exemplar := pt.Exemplars().AppendEmpty() |
|
exemplar.SetTimestamp(pcommon.Timestamp(time.Now().UnixNano())) |
|
exemplar.SetDoubleValue(69.420) |
|
exemplars, err := getPromExemplars(ctx, everyN, pt) |
|
assert.NoError(t, err) |
|
assert.Len(t, exemplars, 1) |
|
assert.Equal(t, 69.420, exemplars[0].Value) |
|
}) |
|
|
|
t.Run("Exemplars with unsupported value type", func(t *testing.T) { |
|
pt := pmetric.NewNumberDataPoint() |
|
exemplar := pt.Exemplars().AppendEmpty() |
|
exemplar.SetTimestamp(pcommon.Timestamp(time.Now().UnixNano())) |
|
_, err := getPromExemplars(ctx, everyN, pt) |
|
assert.Error(t, err) |
|
}) |
|
}
|
|
|