diff --git a/receiver/prometheusreceiver/internal/otlp_metricfamily.go b/receiver/prometheusreceiver/internal/otlp_metricfamily.go index c467c7a1673..4d7b32850e9 100644 --- a/receiver/prometheusreceiver/internal/otlp_metricfamily.go +++ b/receiver/prometheusreceiver/internal/otlp_metricfamily.go @@ -25,15 +25,21 @@ import ( ) type metricFamilyPdata struct { + // We are composing the already present metricFamily to + // make for a scalable migration, so that we only edit target + // fields progressively, when we are ready to make changes. metricFamily mtype pdata.MetricDataType groups map[string]*metricGroupPdata } -// metricGroup, represents a single metric of a metric family. for example a histogram metric is usually represent by +// metricGroupPdata, represents a single metric of a metric family. for example a histogram metric is usually represent by // a couple data complexValue (buckets and count/sum), a group of a metric family always share a same set of tags. for // simple types like counter and gauge, each data point is a group of itself type metricGroupPdata struct { + // We are composing the already present metricGroup to + // make for a scalable migration, so that we only edit target + // fields progressively, when we are ready to make changes. metricGroup family *metricFamilyPdata groups map[string]*metricGroupPdata diff --git a/receiver/prometheusreceiver/internal/otlp_metricsbuilder.go b/receiver/prometheusreceiver/internal/otlp_metricsbuilder.go index b96fc4970de..ea1b2a2f87e 100644 --- a/receiver/prometheusreceiver/internal/otlp_metricsbuilder.go +++ b/receiver/prometheusreceiver/internal/otlp_metricsbuilder.go @@ -15,32 +15,15 @@ package internal import ( - "regexp" "strconv" - metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/pkg/textparse" - "go.uber.org/zap" "go.opentelemetry.io/collector/consumer/pdata" ) -type pdataMetricBuilder struct { - hasData bool - hasInternalMetric bool - mc MetadataCache - metrics []*metricspb.Metric - numTimeseries int - droppedTimeseries int - useStartTimeMetric bool - startTimeMetricRegex *regexp.Regexp - startTime float64 - logger *zap.Logger - currentMf MetricFamily -} - func isUsefulLabelPdata(mType pdata.MetricDataType, labelKey string) bool { switch labelKey { case model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel: diff --git a/receiver/prometheusreceiver/internal/otlp_metricsbuilder_test.go b/receiver/prometheusreceiver/internal/otlp_metricsbuilder_test.go index dc97c757190..47c1ea759cf 100644 --- a/receiver/prometheusreceiver/internal/otlp_metricsbuilder_test.go +++ b/receiver/prometheusreceiver/internal/otlp_metricsbuilder_test.go @@ -19,8 +19,10 @@ import ( "github.com/prometheus/common/model" "github.com/prometheus/prometheus/pkg/labels" + "github.com/prometheus/prometheus/pkg/textparse" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/consumer/pdata" metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1" @@ -109,3 +111,228 @@ func TestGetBoundaryEquivalence(t *testing.T) { }) } } + +func TestGetBoundaryPdata(t *testing.T) { + tests := []struct { + name string + mtype pdata.MetricDataType + labels labels.Labels + wantValue float64 + wantErr string + }{ + { + name: "cumulative histogram with bucket label", + mtype: pdata.MetricDataTypeHistogram, + labels: labels.Labels{ + {Name: model.BucketLabel, Value: "0.256"}, + }, + wantValue: 0.256, + }, + { + name: "gauge histogram with bucket label", + mtype: pdata.MetricDataTypeIntHistogram, + labels: labels.Labels{ + {Name: model.BucketLabel, Value: "11.71"}, + }, + wantValue: 11.71, + }, + { + name: "summary with bucket label", + mtype: pdata.MetricDataTypeSummary, + labels: labels.Labels{ + {Name: model.BucketLabel, Value: "11.71"}, + }, + wantErr: "QuantileLabel is empty", + }, + { + name: "summary with quantile label", + mtype: pdata.MetricDataTypeSummary, + labels: labels.Labels{ + {Name: model.QuantileLabel, Value: "92.88"}, + }, + wantValue: 92.88, + }, + { + name: "gauge histogram mismatched with bucket label", + mtype: pdata.MetricDataTypeSummary, + labels: labels.Labels{ + {Name: model.BucketLabel, Value: "11.71"}, + }, + wantErr: "QuantileLabel is empty", + }, + { + name: "other data types without matches", + mtype: pdata.MetricDataTypeDoubleGauge, + labels: labels.Labels{ + {Name: model.BucketLabel, Value: "11.71"}, + }, + wantErr: "given metricType has no BucketLabel or QuantileLabel", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + value, err := getBoundaryPdata(tt.mtype, tt.labels) + if tt.wantErr != "" { + require.NotNil(t, err) + require.Contains(t, err.Error(), tt.wantErr) + return + } + + require.Nil(t, err) + require.Equal(t, value, tt.wantValue) + }) + } +} + +func TestConvToPdataMetricType(t *testing.T) { + tests := []struct { + name string + mtype textparse.MetricType + want pdata.MetricDataType + }{ + { + name: "textparse.counter", + mtype: textparse.MetricTypeCounter, + want: pdata.MetricDataTypeDoubleSum, + }, + { + name: "textparse.gauge", + mtype: textparse.MetricTypeCounter, + want: pdata.MetricDataTypeDoubleSum, + }, + { + name: "textparse.unknown", + mtype: textparse.MetricTypeUnknown, + want: pdata.MetricDataTypeDoubleGauge, + }, + { + name: "textparse.histogram", + mtype: textparse.MetricTypeHistogram, + want: pdata.MetricDataTypeHistogram, + }, + { + name: "textparse.summary", + mtype: textparse.MetricTypeSummary, + want: pdata.MetricDataTypeSummary, + }, + { + name: "textparse.metric_type_info", + mtype: textparse.MetricTypeInfo, + want: pdata.MetricDataTypeNone, + }, + { + name: "textparse.metric_state_set", + mtype: textparse.MetricTypeStateset, + want: pdata.MetricDataTypeNone, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + got := convToPdataMetricType(tt.mtype) + require.Equal(t, got, tt.want) + }) + } +} + +func TestIsusefulLabelPdata(t *testing.T) { + tests := []struct { + name string + mtypes []pdata.MetricDataType + labelKeys []string + want bool + }{ + { + name: `unuseful "metric","instance","scheme","path","job" with any kind`, + labelKeys: []string{ + model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel, + }, + mtypes: []pdata.MetricDataType{ + pdata.MetricDataTypeDoubleSum, + pdata.MetricDataTypeDoubleGauge, + pdata.MetricDataTypeIntHistogram, + pdata.MetricDataTypeHistogram, + pdata.MetricDataTypeSummary, + pdata.MetricDataTypeIntSum, + pdata.MetricDataTypeNone, + pdata.MetricDataTypeIntGauge, + pdata.MetricDataTypeIntSum, + }, + want: false, + }, + { + name: `bucket label with "int_histogram", "histogram":: non-useful`, + mtypes: []pdata.MetricDataType{pdata.MetricDataTypeIntHistogram, pdata.MetricDataTypeHistogram}, + labelKeys: []string{model.BucketLabel}, + want: false, + }, + { + name: `bucket label with non "int_histogram", "histogram":: useful`, + mtypes: []pdata.MetricDataType{ + pdata.MetricDataTypeDoubleSum, + pdata.MetricDataTypeDoubleGauge, + pdata.MetricDataTypeSummary, + pdata.MetricDataTypeIntSum, + pdata.MetricDataTypeNone, + pdata.MetricDataTypeIntGauge, + pdata.MetricDataTypeIntSum, + }, + labelKeys: []string{model.BucketLabel}, + want: true, + }, + { + name: `quantile label with "summary": non-useful`, + mtypes: []pdata.MetricDataType{ + pdata.MetricDataTypeSummary, + }, + labelKeys: []string{model.QuantileLabel}, + want: false, + }, + { + name: `quantile label with non-"summary": useful`, + labelKeys: []string{model.QuantileLabel}, + mtypes: []pdata.MetricDataType{ + pdata.MetricDataTypeDoubleSum, + pdata.MetricDataTypeDoubleGauge, + pdata.MetricDataTypeIntHistogram, + pdata.MetricDataTypeHistogram, + pdata.MetricDataTypeIntSum, + pdata.MetricDataTypeNone, + pdata.MetricDataTypeIntGauge, + pdata.MetricDataTypeIntSum, + }, + want: true, + }, + { + name: `any other label with any type:: useful`, + labelKeys: []string{"any_label", "foo.bar"}, + mtypes: []pdata.MetricDataType{ + pdata.MetricDataTypeDoubleSum, + pdata.MetricDataTypeDoubleGauge, + pdata.MetricDataTypeIntHistogram, + pdata.MetricDataTypeHistogram, + pdata.MetricDataTypeSummary, + pdata.MetricDataTypeIntSum, + pdata.MetricDataTypeNone, + pdata.MetricDataTypeIntGauge, + pdata.MetricDataTypeIntSum, + }, + want: true, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + for _, mtype := range tt.mtypes { + for _, labelKey := range tt.labelKeys { + got := isUsefulLabelPdata(mtype, labelKey) + assert.Equal(t, got, tt.want) + } + } + }) + } +}