Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ linters:
- linters:
- forbidigo
path: connector/servicegraphconnector/
- linters:
- forbidigo
path: connector/spanmetricsconnector/
Comment on lines -128 to -130

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule was added as part of #47506 which was done in preparation for #46116, see also last line of issue description

The list of components that still have manually written feature gates are: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/.golangci.yml#L124

Linting would fail (on main) without this rule because the connector still uses manually written feature gate code. The PR migrates the FGs to metadata, making the rule unnecessary.

- linters:
- forbidigo
path: exporter/awsemfexporter/
Expand Down
3 changes: 2 additions & 1 deletion connector/spanmetricsconnector/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go.opentelemetry.io/collector/confmap/xconfmap"
"go.opentelemetry.io/collector/pdata/pmetric"

"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metrics"
)

Expand Down Expand Up @@ -205,7 +206,7 @@ func (c Config) GetDeltaTimestampCacheSize() int {
func validateDimensions(dimensions []Dimension) error {
labelNames := make(map[string]struct{})
intervalLabels := []string{serviceNameKey, spanKindKey, statusCodeKey, spanNameKey}
if includeCollectorInstanceID.IsEnabled() {
if metadata.ConnectorSpanmetricsIncludeCollectorInstanceIDFeatureGate.IsEnabled() {
intervalLabels = append(intervalLabels, collectorInstanceKey)
}

Expand Down
2 changes: 1 addition & 1 deletion connector/spanmetricsconnector/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
func TestLoadConfig(t *testing.T) {
t.Parallel()

require.NoError(t, featuregate.GlobalRegistry().Set(useSecondAsDefaultMetricsUnit.ID(), true))
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.ConnectorSpanmetricsUseSecondAsDefaultMetricsUnitFeatureGate.ID(), true))
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)

Expand Down
11 changes: 6 additions & 5 deletions connector/spanmetricsconnector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"go.uber.org/zap"

"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/cache"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metrics"
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/traceutil"
utilattri "github.com/open-telemetry/opentelemetry-collector-contrib/internal/pdatautil"
Expand Down Expand Up @@ -282,7 +283,7 @@ func (p *connectorImp) buildMetrics() pmetric.Metrics {

p.resourceMetrics.ForEach(func(_ resourceKey, rawMetrics *resourceMetrics) {
rm := m.ResourceMetrics().AppendEmpty()
if !excludeResourceMetrics.IsEnabled() || p.config.AddResourceAttributes {
if !metadata.ConnectorSpanmetricsExcludeResourceMetricsFeatureGate.IsEnabled() || p.config.AddResourceAttributes {
rawMetrics.attributes.CopyTo(rm.Resource().Attributes())
}

Expand All @@ -307,7 +308,7 @@ func (p *connectorImp) buildMetrics() pmetric.Metrics {
}

metricsNamespace := p.config.Namespace
if legacyMetricNamesFeatureGate.IsEnabled() && metricsNamespace == DefaultNamespace {
if metadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.IsEnabled() && metricsNamespace == DefaultNamespace {
metricsNamespace = ""
}

Expand Down Expand Up @@ -550,7 +551,7 @@ func (p *connectorImp) buildAttributes(
if !slices.Contains(p.config.ExcludeDimensions, spanKindKey) {
attr.PutStr(spanKindKey, traceutil.SpanKindStr(span.Kind()))
}
if useOtelStatusCodeAttribute.IsEnabled() {
if metadata.SpanmetricsStatusCodeConventionUseOtelPrefixFeatureGate.IsEnabled() {
if !slices.Contains(p.config.ExcludeDimensions, otelStatusCodeKey) {
if span.Status().Code() == ptrace.StatusCodeError {
attr.PutStr(otelStatusCodeKey, "ERROR")
Expand All @@ -563,7 +564,7 @@ func (p *connectorImp) buildAttributes(
attr.PutStr(statusCodeKey, traceutil.StatusCodeStr(span.Status().Code()))
}
}
if includeCollectorInstanceID.IsEnabled() {
if metadata.ConnectorSpanmetricsIncludeCollectorInstanceIDFeatureGate.IsEnabled() {
if !slices.Contains(p.config.ExcludeDimensions, collectorInstanceKey) {
attr.PutStr(collectorInstanceKey, p.instanceID)
}
Expand Down Expand Up @@ -624,7 +625,7 @@ func (p *connectorImp) buildKey(serviceName string, span ptrace.Span, optionalDi
if !slices.Contains(p.config.ExcludeDimensions, spanKindKey) {
concatDimensionValue(p.keyBuf, traceutil.SpanKindStr(span.Kind()), true)
}
if useOtelStatusCodeAttribute.IsEnabled() {
if metadata.SpanmetricsStatusCodeConventionUseOtelPrefixFeatureGate.IsEnabled() {
if !slices.Contains(p.config.ExcludeDimensions, otelStatusCodeKey) {
concatDimensionValue(p.keyBuf, traceutil.StatusCodeStr(span.Status().Code()), true)
}
Expand Down
33 changes: 17 additions & 16 deletions connector/spanmetricsconnector/connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"go.uber.org/zap/zaptest/observer"
"google.golang.org/grpc/metadata"

spanmetricsmetadata "github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metrics"
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/pdatautil"
)
Expand Down Expand Up @@ -868,9 +869,9 @@ func TestConsumeMetricsErrors(t *testing.T) {

func TestConsumeTraces(t *testing.T) {
// enable it
require.NoError(t, featuregate.GlobalRegistry().Set(excludeResourceMetrics.ID(), true))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsExcludeResourceMetricsFeatureGate.ID(), true))
defer func() {
require.NoError(t, featuregate.GlobalRegistry().Set(legacyMetricNamesFeatureGate.ID(), false))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.ID(), false))
}()

t.Parallel()
Expand Down Expand Up @@ -1014,9 +1015,9 @@ func TestConsumeTraces(t *testing.T) {
// Override the default no-op consumer with metrics sink for testing.
p.metricsConsumer = mcon
if tc.statusCodeFeatureGate {
require.NoError(t, featuregate.GlobalRegistry().Set(useOtelStatusCodeAttribute.ID(), true))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.SpanmetricsStatusCodeConventionUseOtelPrefixFeatureGate.ID(), true))
defer func() {
require.NoError(t, featuregate.GlobalRegistry().Set(useOtelStatusCodeAttribute.ID(), false))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.SpanmetricsStatusCodeConventionUseOtelPrefixFeatureGate.ID(), false))
}()
}

Expand Down Expand Up @@ -1214,10 +1215,10 @@ func TestAddResourceAttributesConfig(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Save and restore the feature gate state
previousValue := excludeResourceMetrics.IsEnabled()
require.NoError(t, featuregate.GlobalRegistry().Set(excludeResourceMetrics.ID(), tt.featureGateEnabled))
previousValue := spanmetricsmetadata.ConnectorSpanmetricsExcludeResourceMetricsFeatureGate.IsEnabled()
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsExcludeResourceMetricsFeatureGate.ID(), tt.featureGateEnabled))
defer func() {
require.NoError(t, featuregate.GlobalRegistry().Set(excludeResourceMetrics.ID(), previousValue))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsExcludeResourceMetricsFeatureGate.ID(), previousValue))
}()

// Create a custom config with AddResourceAttributes
Expand Down Expand Up @@ -1302,11 +1303,11 @@ func TestExcludeDimensionsConsumeTraces(t *testing.T) {
featureGateEnabled bool
}{
{
dsc: fmt.Sprintf("%s enabled", legacyMetricNamesFeatureGateID),
dsc: fmt.Sprintf("%s enabled", spanmetricsmetadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.ID()),
featureGateEnabled: true,
},
{
dsc: fmt.Sprintf("%s disabled", legacyMetricNamesFeatureGateID),
dsc: fmt.Sprintf("%s disabled", spanmetricsmetadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.ID()),
featureGateEnabled: false,
},
}
Expand All @@ -1315,10 +1316,10 @@ func TestExcludeDimensionsConsumeTraces(t *testing.T) {
for _, tc := range testcases {
t.Run(tc.dsc, func(t *testing.T) {
// Set feature gate value
previousValue := legacyMetricNamesFeatureGate.IsEnabled()
require.NoError(t, featuregate.GlobalRegistry().Set(legacyMetricNamesFeatureGate.ID(), tc.featureGateEnabled))
previousValue := spanmetricsmetadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.IsEnabled()
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.ID(), tc.featureGateEnabled))
defer func() {
require.NoError(t, featuregate.GlobalRegistry().Set(legacyMetricNamesFeatureGate.ID(), previousValue))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.ID(), previousValue))
}()

p, err := newConnectorImp(stringp("defaultNullValue"), explicitHistogramsConfig, disabledExemplarsConfig, disabledEventsConfig, cumulative, 0, []string{}, 1000, clockwork.NewFakeClock(), false, excludeDimensions...)
Expand Down Expand Up @@ -1910,9 +1911,9 @@ func assertDataPointsHaveExactlyOneExemplarForTrace(t *testing.T, metrics pmetri

func TestTimestampsForUninterruptedStream(t *testing.T) {
// enable it
require.NoError(t, featuregate.GlobalRegistry().Set(excludeResourceMetrics.ID(), true))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsExcludeResourceMetricsFeatureGate.ID(), true))
defer func() {
require.NoError(t, featuregate.GlobalRegistry().Set(legacyMetricNamesFeatureGate.ID(), false))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsLegacyMetricNamesFeatureGate.ID(), false))
}()

tests := []struct {
Expand Down Expand Up @@ -2562,10 +2563,10 @@ func TestBuildAttributesWithFeatureGate(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
p := &connectorImp{config: tt.config, instanceID: instanceID}
if !tt.includeCollectorInstanceID {
require.NoError(t, featuregate.GlobalRegistry().Set(includeCollectorInstanceID.ID(), false))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsIncludeCollectorInstanceIDFeatureGate.ID(), false))
}
defer func() {
require.NoError(t, featuregate.GlobalRegistry().Set(includeCollectorInstanceID.ID(), true))
require.NoError(t, featuregate.GlobalRegistry().Set(spanmetricsmetadata.ConnectorSpanmetricsIncludeCollectorInstanceIDFeatureGate.ID(), true))
}()

span := ptrace.NewSpan()
Expand Down
17 changes: 17 additions & 0 deletions connector/spanmetricsconnector/documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[comment]: <> (Code generated by mdatagen. DO NOT EDIT.)

# span_metrics

## Feature Gates

This component has the following feature gates:

| Feature Gate | Stage | Description | From Version | To Version | Reference |
| ------------ | ----- | ----------- | ------------ | ---------- | --------- |
| `connector.spanmetrics.excludeResourceMetrics` | alpha | When enabled, connector will exclude all resource attributes. | v0.137.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/42103) |
| `connector.spanmetrics.includeCollectorInstanceID` | beta | When enabled, connector add collector.instance.id to default dimensions. | v0.136.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/40400) |
| `connector.spanmetrics.legacyMetricNames` | alpha | When enabled, connector uses legacy metric names. | v0.109.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/33227) |
| `connector.spanmetrics.useSecondAsDefaultMetricsUnit` | alpha | When enabled, connector use second as default unit for duration metrics. | v0.137.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/42462) |
| `spanmetrics.statusCodeConvention.useOtelPrefix` | alpha | When enabled, generated metrics will use `otel.status_code=ERROR` instead of `status.code=STATUS_CODE_ERROR` | v0.141.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/43000) |

For more information about feature gates, see the [Feature Gates](https://github.com/open-telemetry/opentelemetry-collector/blob/main/featuregate/README.md) documentation.
50 changes: 2 additions & 48 deletions connector/spanmetricsconnector/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,16 @@ import (
"go.opentelemetry.io/collector/connector"
"go.opentelemetry.io/collector/connector/xconnector"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/featuregate"
"go.opentelemetry.io/collector/pdata/pcommon"

"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metrics"
)

const (
DefaultNamespace = "traces.span.metrics"
legacyMetricNamesFeatureGateID = "connector.spanmetrics.legacyMetricNames"
includeCollectorInstanceIDFeatureGateID = "connector.spanmetrics.includeCollectorInstanceID"
useSecondAsDefaultMetricsUnitFeatureGateID = "connector.spanmetrics.useSecondAsDefaultMetricsUnit"
excludeResourceMetricsFeatureGate = "connector.spanmetrics.excludeResourceMetrics"
DefaultNamespace = "traces.span.metrics"
)

var (
legacyMetricNamesFeatureGate *featuregate.Gate
includeCollectorInstanceID *featuregate.Gate
useSecondAsDefaultMetricsUnit *featuregate.Gate
excludeResourceMetrics *featuregate.Gate
useOtelStatusCodeAttribute *featuregate.Gate
)

func init() {
// TODO: Remove this feature gate when the legacy metric names are removed.
legacyMetricNamesFeatureGate = featuregate.GlobalRegistry().MustRegister(
legacyMetricNamesFeatureGateID,
featuregate.StageAlpha, // Alpha because we want it disabled by default.
featuregate.WithRegisterDescription("When enabled, connector uses legacy metric names."),
featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/33227"),
)
includeCollectorInstanceID = featuregate.GlobalRegistry().MustRegister(
includeCollectorInstanceIDFeatureGateID,
featuregate.StageBeta,
featuregate.WithRegisterDescription("When enabled, connector add collector.instance.id to default dimensions."),
featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/40400"),
)
useSecondAsDefaultMetricsUnit = featuregate.GlobalRegistry().MustRegister(
useSecondAsDefaultMetricsUnitFeatureGateID,
featuregate.StageAlpha,
featuregate.WithRegisterDescription("When enabled, connector use second as default unit for duration metrics."),
featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/42462"),
)
excludeResourceMetrics = featuregate.GlobalRegistry().MustRegister(
excludeResourceMetricsFeatureGate,
featuregate.StageAlpha,
featuregate.WithRegisterDescription("When enabled, connector will exclude all resource attributes."),
featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/42103"),
)
useOtelStatusCodeAttribute = featuregate.GlobalRegistry().MustRegister(
"spanmetrics.statusCodeConvention.useOtelPrefix",
featuregate.StageAlpha,
featuregate.WithRegisterDescription("When enabled, generated metrics will use `otel.status_code=ERROR` instead of `status.code=STATUS_CODE_ERROR`"),
)
}

// NewFactory creates a factory for the spanmetrics connector.
func NewFactory() connector.Factory {
return xconnector.NewFactory(
Expand All @@ -87,7 +41,7 @@ func createDefaultConfig() component.Config {
ResourceMetricsCacheSize: defaultResourceMetricsCacheSize,
MetricsFlushInterval: 60 * time.Second,
Histogram: HistogramConfig{Disable: false, Unit: func() metrics.Unit {
if useSecondAsDefaultMetricsUnit.IsEnabled() {
if metadata.ConnectorSpanmetricsUseSecondAsDefaultMetricsUnitFeatureGate.IsEnabled() {
return metrics.Seconds
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions connector/spanmetricsconnector/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,37 @@ status:
emeritus: [albertteoh]
seeking_new: true

feature_gates:
- id: connector.spanmetrics.excludeResourceMetrics
description: When enabled, connector will exclude all resource attributes.
stage: alpha
from_version: v0.137.0
reference_url: https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/42103

- id: connector.spanmetrics.includeCollectorInstanceID
description: When enabled, connector add collector.instance.id to default dimensions.
stage: beta
from_version: v0.136.0
reference_url: https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/40400

- id: connector.spanmetrics.legacyMetricNames
description: When enabled, connector uses legacy metric names.
# Alpha because we want it disabled by default.
stage: alpha
from_version: v0.109.0
reference_url: https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/33227

- id: connector.spanmetrics.useSecondAsDefaultMetricsUnit
description: When enabled, connector use second as default unit for duration metrics.
stage: alpha
from_version: v0.137.0
reference_url: https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/42462

- id: spanmetrics.statusCodeConvention.useOtelPrefix
description: When enabled, generated metrics will use `otel.status_code=ERROR` instead of `status.code=STATUS_CODE_ERROR`
stage: alpha
from_version: v0.141.0
reference_url: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/43000

tests:
config:
Loading