Skip to content
Merged
36 changes: 36 additions & 0 deletions .chloggen/fix-42462.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: breaking

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: spanmetricsconnector

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Change default duration metrics unit from `ms` to `s`

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [42462]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: |
This change introduces a breaking change, which is now guarded by the feature gate `connector.spanmetrics.useSCDefaultMetricsUnit`.
Currently, the feature gate is disabled by default, so the unit will remain `ms`. After one release cycle, the unit will switch to `s` and the feature gate will also be enabled by default.
To revert this change manually, users can either enable the feature gate or modify the configuration as follows:
```
connectors
spanmetrics:
histogram:
unit: "ms"
```
# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
12 changes: 12 additions & 0 deletions connector/spanmetricsconnector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@
[Stability Level]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#stability-levels
<!-- end autogenerated section -->

⚠️ Breaking Change Warning:
The default duration metrics unit will change from `ms` to `s` to adhere to the OpenTelemetry semantic conventions and a feature gate `connector.spanmetrics.useSCDefaultMetricsUnit` is also added.

Currently, the feature gate is disabled by default, so the unit will remain `ms`. After one release cycle, the unit will switch to `s` and the feature gate will also be enabled by default.
To revert this change manually, users can either disabled the feature gate or modify the configuration as follows:
```
connectors
spanmetrics:
histogram:
unit: "ms"
```

## Overview

Aggregates Request, Error and Duration (R.E.D) OpenTelemetry metrics from span data.
Expand Down
4 changes: 3 additions & 1 deletion connector/spanmetricsconnector/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"go.opentelemetry.io/collector/config/configoptional"
"go.opentelemetry.io/collector/confmap/confmaptest"
"go.opentelemetry.io/collector/confmap/xconfmap"
"go.opentelemetry.io/collector/featuregate"
"go.opentelemetry.io/collector/pdata/pmetric"

"github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector/internal/metadata"
Expand All @@ -25,6 +26,7 @@ import (
func TestLoadConfig(t *testing.T) {
t.Parallel()

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

Expand Down Expand Up @@ -87,7 +89,7 @@ func TestLoadConfig(t *testing.T) {
MaxPerDataPoint: defaultMaxPerDatapoint,
},
Histogram: HistogramConfig{
Unit: metrics.Milliseconds,
Unit: metrics.Seconds,
Exponential: configoptional.Some(ExponentialHistogramConfig{
MaxSize: 10,
}),
Expand Down
2 changes: 1 addition & 1 deletion connector/spanmetricsconnector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const (
metricNameCalls = "calls"
metricNameEvents = "events"

defaultUnit = metrics.Milliseconds
defaultUnit = metrics.Seconds

// https://github.com/open-telemetry/opentelemetry-go/blob/3ae002c3caf3e44387f0554dfcbbde2c5aab7909/sdk/metric/internal/aggregate/limit.go#L11C36-L11C50
overflowKey = "otel.metric.overflow"
Expand Down
14 changes: 7 additions & 7 deletions connector/spanmetricsconnector/connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const (
resourceMetricsCacheSize = 5

sampleRegion = "us-east-1"
sampleDuration = float64(11)
sampleDuration = 11 * time.Millisecond

instanceID = "0044953a-2946-449f-a5c8-2971f2a63928"
)
Expand Down Expand Up @@ -231,7 +231,7 @@ func verifyExplicitHistogramDataPoints(tb testing.TB, dps pmetric.HistogramDataP
dp := dps.At(dpi)
assert.Equal(
tb,
sampleDuration*float64(numCumulativeConsumptions),
sampleDuration.Seconds()*float64(numCumulativeConsumptions),
dp.Sum(),
"Should be a 11ms duration measurement, multiplied by the number of stateful accumulations.")
assert.NotZero(tb, dp.Timestamp(), "Timestamp should be set")
Expand All @@ -245,7 +245,7 @@ func verifyExplicitHistogramDataPoints(tb testing.TB, dps pmetric.HistogramDataP
// Find the bucket index where the 11ms duration should belong in.
var foundDurationIndex int
for foundDurationIndex = 0; foundDurationIndex < dp.ExplicitBounds().Len(); foundDurationIndex++ {
if dp.ExplicitBounds().At(foundDurationIndex) > sampleDuration {
if dp.ExplicitBounds().At(foundDurationIndex) > sampleDuration.Seconds() {
break
}
}
Expand All @@ -270,7 +270,7 @@ func verifyExponentialHistogramDataPoints(tb testing.TB, dps pmetric.Exponential
dp := dps.At(dpi)
assert.Equal(
tb,
sampleDuration*float64(numCumulativeConsumptions),
sampleDuration.Seconds()*float64(numCumulativeConsumptions),
dp.Sum(),
"Should be a 11ms duration measurement, multiplied by the number of stateful accumulations.")
assert.Equal(tb, uint64(numCumulativeConsumptions), dp.Count())
Expand Down Expand Up @@ -325,7 +325,7 @@ func buildBadSampleTrace() ptrace.Traces {
// Flipping timestamp for a bad duration
span.SetEndTimestamp(pcommon.NewTimestampFromTime(now))
span.SetStartTimestamp(
pcommon.NewTimestampFromTime(now.Add(time.Duration(sampleDuration) * time.Millisecond)))
pcommon.NewTimestampFromTime(now.Add(sampleDuration)))
return badTrace
}

Expand Down Expand Up @@ -394,7 +394,7 @@ func initSpan(span span, s ptrace.Span) {
now := time.Now()
s.SetStartTimestamp(pcommon.NewTimestampFromTime(now))
s.SetEndTimestamp(
pcommon.NewTimestampFromTime(now.Add(time.Duration(sampleDuration) * time.Millisecond)))
pcommon.NewTimestampFromTime(now.Add(sampleDuration)))

s.Attributes().PutStr(stringAttrName, "stringAttrValue")
s.Attributes().PutInt(intAttrName, 99)
Expand Down Expand Up @@ -1371,7 +1371,7 @@ func TestConnector_durationsToUnits(t *testing.T) {
3 * time.Second,
},
unit: defaultUnit,
want: []float64{0.000003, 0.003, 3, 3000},
want: []float64{3e-09, 3e-06, 0.003, 3},
},
{
input: []time.Duration{
Expand Down
31 changes: 23 additions & 8 deletions connector/spanmetricsconnector/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ import (
"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"
includeCollectorInstanceIDGateID = "connector.spanmetrics.includeCollectorInstanceID"
DefaultNamespace = "traces.span.metrics"
legacyMetricNamesFeatureGateID = "connector.spanmetrics.legacyMetricNames"
includeCollectorInstanceIDFeatureGateID = "connector.spanmetrics.includeCollectorInstanceID"
useSCDefaultMetricsUnitFeatureGateID = "connector.spanmetrics.useSCDefaultMetricsUnit"
)

var (
legacyMetricNamesFeatureGate *featuregate.Gate
includeCollectorInstanceID *featuregate.Gate
useSCDefaultMetricsUnit *featuregate.Gate
)

func init() {
Expand All @@ -40,11 +43,17 @@ func init() {
featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/33227"),
)
includeCollectorInstanceID = featuregate.GlobalRegistry().MustRegister(
includeCollectorInstanceIDGateID,
includeCollectorInstanceIDFeatureGateID,
featuregate.StageAlpha,
featuregate.WithRegisterDescription("When enabled, connector add collector.instance.id to default dimensions."),
featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/40400"),
)
useSCDefaultMetricsUnit = featuregate.GlobalRegistry().MustRegister(
useSCDefaultMetricsUnitFeatureGateID,
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/42103"),
)
}

// NewFactory creates a factory for the spanmetrics connector.
Expand All @@ -58,10 +67,16 @@ func NewFactory() connector.Factory {

func createDefaultConfig() component.Config {
return &Config{
AggregationTemporality: "AGGREGATION_TEMPORALITY_CUMULATIVE",
ResourceMetricsCacheSize: defaultResourceMetricsCacheSize,
MetricsFlushInterval: 60 * time.Second,
Histogram: HistogramConfig{Disable: false, Unit: defaultUnit},
AggregationTemporality: "AGGREGATION_TEMPORALITY_CUMULATIVE",
ResourceMetricsCacheSize: defaultResourceMetricsCacheSize,
MetricsFlushInterval: 60 * time.Second,
Histogram: HistogramConfig{Disable: false, Unit: func() metrics.Unit {
if useSCDefaultMetricsUnit.IsEnabled() {
return metrics.Seconds
}

return metrics.Milliseconds
}()},
Namespace: DefaultNamespace,
AggregationCardinalityLimit: 0,
Exemplars: ExemplarsConfig{
Expand Down
Loading