diff --git a/exporter/collector/go.mod b/exporter/collector/go.mod index 68f60d253..26fe674f2 100644 --- a/exporter/collector/go.mod +++ b/exporter/collector/go.mod @@ -15,6 +15,7 @@ require ( github.com/stretchr/testify v1.8.3 github.com/tidwall/wal v1.1.7 go.opencensus.io v0.24.0 + go.opentelemetry.io/collector/featuregate v0.77.0 go.opentelemetry.io/collector/pdata v1.0.0-rcv0012 go.opentelemetry.io/collector/semconv v0.78.0 go.opentelemetry.io/otel v1.16.0 diff --git a/exporter/collector/go.sum b/exporter/collector/go.sum index 26623a892..132e69ab2 100644 --- a/exporter/collector/go.sum +++ b/exporter/collector/go.sum @@ -114,6 +114,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/collector/featuregate v0.77.0 h1:m1/IzaXoQh6SgF6CM80vrBOCf5zSJ2GVISfA27fYzGU= +go.opentelemetry.io/collector/featuregate v0.77.0/go.mod h1:/kVAsGUCyJXIDSgHftCN63QiwAEVHRLX2Kh/S+dqgHY= go.opentelemetry.io/collector/pdata v1.0.0-rcv0012 h1:R+cfEUMyLn9Q1QknyQ4QU77pbfc1aJKYEXFHtnwSbCg= go.opentelemetry.io/collector/pdata v1.0.0-rcv0012/go.mod h1:rEAKFqc1L03lidKtra/2/dJtI0Hp+JsQxuPEIkj/2Vg= go.opentelemetry.io/collector/semconv v0.78.0 h1:kiufXJhRiBkjGXPQPLklknbov9xr8N/HV4P/yoICnHI= diff --git a/exporter/collector/integrationtest/go.mod b/exporter/collector/integrationtest/go.mod index c322c4607..7122473f4 100644 --- a/exporter/collector/integrationtest/go.mod +++ b/exporter/collector/integrationtest/go.mod @@ -18,6 +18,7 @@ require ( go.opentelemetry.io/collector v0.78.0 go.opentelemetry.io/collector/component v0.78.0 go.opentelemetry.io/collector/exporter v0.78.0 + go.opentelemetry.io/collector/featuregate v1.0.0-rcv0012 go.opentelemetry.io/collector/pdata v1.0.0-rcv0012 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/sdk v1.16.0 @@ -87,7 +88,6 @@ require ( github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opentelemetry.io/collector/confmap v0.78.0 // indirect go.opentelemetry.io/collector/consumer v0.78.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.0-rcv0012 // indirect go.opentelemetry.io/collector/receiver v0.78.0 // indirect go.opentelemetry.io/collector/semconv v0.78.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.16.1 // indirect diff --git a/exporter/collector/integrationtest/testcases/testcases_metrics.go b/exporter/collector/integrationtest/testcases/testcases_metrics.go index 676cc7db4..c9b3d4922 100644 --- a/exporter/collector/integrationtest/testcases/testcases_metrics.go +++ b/exporter/collector/integrationtest/testcases/testcases_metrics.go @@ -19,6 +19,7 @@ import ( "strings" "time" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/metric/metricdata" @@ -64,6 +65,10 @@ var MetricsTestCases = []TestCase{ OTLPInputFixturePath: "testdata/fixtures/metrics/untyped_prometheus_metrics.json", ExpectFixturePath: "testdata/fixtures/metrics/untyped_prometheus_metrics_expect.json", SkipForSDK: true, + ConfigureCollector: func(cfg *collector.Config) { + //nolint:errcheck + featuregate.GlobalRegistry().Set("gcp.untyped_double_export", true) + }, }, { Name: "Modified prefix unknown domain", diff --git a/exporter/collector/metrics.go b/exporter/collector/metrics.go index fce2a201e..a6ffb0b2e 100644 --- a/exporter/collector/metrics.go +++ b/exporter/collector/metrics.go @@ -50,6 +50,7 @@ import ( "go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/stats/view" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/pmetric" @@ -140,6 +141,13 @@ const ( GCPOpsAgentUntypedMetricKey = "prometheus_untyped_metric" ) +var untypedDoubleExportFeatureGate = featuregate.GlobalRegistry().MustRegister( + "gcp.untyped_double_export", + featuregate.StageAlpha, + featuregate.WithRegisterFromVersion("v0.77.0"), + featuregate.WithRegisterDescription("Enable automatically exporting untyped Prometheus metrics as both gauge and cumulative to GCP."), + featuregate.WithRegisterReferenceURL("https://github.com/GoogleCloudPlatform/opentelemetry-operations-go/pull/668")) + type labels map[string]string func (me *MetricsExporter) Shutdown(ctx context.Context) error { @@ -1236,29 +1244,31 @@ func (m *metricMapper) gaugePointToTimeSeries( // if an untyped prometheus metric from ops agent, double-export as gauge and cumulative // to match GMP exporter behavior. Only for internal use. - val, ok := point.Attributes().Get(GCPOpsAgentUntypedMetricKey) - if ok && val.AsString() == "true" { - metricKind := metricpb.MetricDescriptor_CUMULATIVE - value, valueType := m.numberDataPointToValue(point, metricKind, metric.Unit()) - series = append(series, &monitoringpb.TimeSeries{ - Resource: resource, - Unit: metric.Unit(), - MetricKind: metricKind, - ValueType: valueType, - Points: []*monitoringpb.Point{{ - Interval: &monitoringpb.TimeInterval{ - EndTime: timestamppb.New(point.Timestamp().AsTime()), + if untypedDoubleExportFeatureGate.IsEnabled() { + val, ok := point.Attributes().Get(GCPOpsAgentUntypedMetricKey) + if ok && val.AsString() == "true" { + metricKind := metricpb.MetricDescriptor_CUMULATIVE + value, valueType := m.numberDataPointToValue(point, metricKind, metric.Unit()) + series = append(series, &monitoringpb.TimeSeries{ + Resource: resource, + Unit: metric.Unit(), + MetricKind: metricKind, + ValueType: valueType, + Points: []*monitoringpb.Point{{ + Interval: &monitoringpb.TimeInterval{ + EndTime: timestamppb.New(point.Timestamp().AsTime()), + }, + Value: value, + }}, + Metric: &metricpb.Metric{ + Type: t, + Labels: mergeLabels( + attributesToLabels(point.Attributes()), + extraLabels, + ), }, - Value: value, - }}, - Metric: &metricpb.Metric{ - Type: t, - Labels: mergeLabels( - attributesToLabels(point.Attributes()), - extraLabels, - ), - }, - }) + }) + } } return series diff --git a/exporter/collector/metrics_test.go b/exporter/collector/metrics_test.go index 07b4010de..72eef3738 100644 --- a/exporter/collector/metrics_test.go +++ b/exporter/collector/metrics_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/wal" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/pmetric" "go.uber.org/zap" @@ -1178,6 +1179,8 @@ func TestGaugePointToTimeSeries(t *testing.T) { // Add ops agent untyped prometheus metric attribute // Should double-export as gauge+cumulative and drop untyped metric label + err := featuregate.GlobalRegistry().Set("gcp.untyped_double_export", true) + assert.NoError(t, err) point.Attributes().PutStr(GCPOpsAgentUntypedMetricKey, "true") tsl = mapper.gaugePointToTimeSeries(mr, extraLabels, metric, gauge, point) assert.Len(t, tsl, 2)