Skip to content

Commit 22c647a

Browse files
authored
[connector/signaltometrics]Add collector telemetry as resource attrib… (#37117)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Update signal to metrics connector to add resource attribute from telemetry settings. More information can be perused here: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/connector/signaltometricsconnector/README.md#single-writer <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Related to #35930 <!--Describe what testing was performed and which tests were added.--> #### Testing Unit tests added <!--Describe the documentation added.--> #### Documentation Documentation is already added in README as part of the initial PR: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/connector/signaltometricsconnector/README.md#single-writer <!--Please delete paragraphs that you did not use before submitting.-->
1 parent 09d4ae3 commit 22c647a

File tree

15 files changed

+353
-10
lines changed

15 files changed

+353
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: signaltometrics
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Adds resource attributes based on telemetry settings to the connector to ensure single writer
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [35930]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

connector/signaltometricsconnector/connector.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ import (
2323
)
2424

2525
type signalToMetrics struct {
26-
next consumer.Metrics
27-
logger *zap.Logger
26+
next consumer.Metrics
27+
collectorInstanceInfo *model.CollectorInstanceInfo
28+
logger *zap.Logger
2829

2930
spanMetricDefs []model.MetricDef[ottlspan.TransformContext]
3031
dpMetricDefs []model.MetricDef[ottldatapoint.TransformContext]
@@ -75,7 +76,7 @@ func (sm *signalToMetrics) ConsumeTraces(ctx context.Context, td ptrace.Traces)
7576
}
7677
}
7778

78-
filteredResAttrs := md.FilterResourceAttributes(resourceAttrs)
79+
filteredResAttrs := md.FilterResourceAttributes(resourceAttrs, sm.collectorInstanceInfo)
7980
if err := aggregator.Aggregate(ctx, tCtx, md, filteredResAttrs, filteredSpanAttrs, 1); err != nil {
8081
return err
8182
}
@@ -104,7 +105,7 @@ func (sm *signalToMetrics) ConsumeMetrics(ctx context.Context, m pmetric.Metrics
104105
metrics := scopeMetric.Metrics()
105106
metric := metrics.At(k)
106107
for _, md := range sm.dpMetricDefs {
107-
filteredResAttrs := md.FilterResourceAttributes(resourceAttrs)
108+
filteredResAttrs := md.FilterResourceAttributes(resourceAttrs, sm.collectorInstanceInfo)
108109
aggregate := func(dp any, dpAttrs pcommon.Map) error {
109110
// The transform context is created from original attributes so that the
110111
// OTTL expressions are also applied on the original attributes.
@@ -230,7 +231,7 @@ func (sm *signalToMetrics) ConsumeLogs(ctx context.Context, logs plog.Logs) erro
230231
continue
231232
}
232233
}
233-
filteredResAttrs := md.FilterResourceAttributes(resourceAttrs)
234+
filteredResAttrs := md.FilterResourceAttributes(resourceAttrs, sm.collectorInstanceInfo)
234235
if err := aggregator.Aggregate(ctx, tCtx, md, filteredResAttrs, filteredLogAttrs, 1); err != nil {
235236
return err
236237
}

connector/signaltometricsconnector/factory.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ func createTracesToMetrics(
5757
}
5858

5959
return &signalToMetrics{
60-
logger: set.Logger,
60+
logger: set.Logger,
61+
collectorInstanceInfo: model.NewCollectorInstanceInfo(
62+
set.TelemetrySettings,
63+
),
6164
next: nextConsumer,
6265
spanMetricDefs: metricDefs,
6366
}, nil
@@ -85,7 +88,10 @@ func createMetricsToMetrics(
8588
}
8689

8790
return &signalToMetrics{
88-
logger: set.Logger,
91+
logger: set.Logger,
92+
collectorInstanceInfo: model.NewCollectorInstanceInfo(
93+
set.TelemetrySettings,
94+
),
8995
next: nextConsumer,
9096
dpMetricDefs: metricDefs,
9197
}, nil
@@ -113,7 +119,10 @@ func createLogsToMetrics(
113119
}
114120

115121
return &signalToMetrics{
116-
logger: set.Logger,
122+
logger: set.Logger,
123+
collectorInstanceInfo: model.NewCollectorInstanceInfo(
124+
set.TelemetrySettings,
125+
),
117126
next: nextConsumer,
118127
logMetricDefs: metricDefs,
119128
}, nil
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package model // import "github.com/open-telemetry/opentelemetry-collector-contrib/connector/signaltometricsconnector/internal/model"
5+
6+
import (
7+
"go.opentelemetry.io/collector/component"
8+
"go.opentelemetry.io/collector/pdata/pcommon"
9+
semconv "go.opentelemetry.io/collector/semconv/v1.26.0"
10+
11+
"github.com/open-telemetry/opentelemetry-collector-contrib/connector/signaltometricsconnector/internal/metadata"
12+
)
13+
14+
var prefix = metadata.Type.String()
15+
16+
// CollectorInstanceInfo holds the attributes that could uniquely identify
17+
// the current collector instance. These attributes are initialized from the
18+
// telemetry settings. The CollectorInstanceInfo can copy these attributes,
19+
// with a given prefix, to a provided map.
20+
type CollectorInstanceInfo struct {
21+
size int
22+
serviceInstanceID string
23+
serviceName string
24+
serviceNamespace string
25+
}
26+
27+
func NewCollectorInstanceInfo(
28+
set component.TelemetrySettings,
29+
) *CollectorInstanceInfo {
30+
var info CollectorInstanceInfo
31+
set.Resource.Attributes().Range(func(k string, v pcommon.Value) bool {
32+
switch k {
33+
case semconv.AttributeServiceInstanceID:
34+
if str := v.Str(); str != "" {
35+
info.serviceInstanceID = str
36+
info.size++
37+
}
38+
case semconv.AttributeServiceName:
39+
if str := v.Str(); str != "" {
40+
info.serviceName = str
41+
info.size++
42+
}
43+
case semconv.AttributeServiceNamespace:
44+
if str := v.Str(); str != "" {
45+
info.serviceNamespace = str
46+
info.size++
47+
}
48+
}
49+
return true
50+
})
51+
return &info
52+
}
53+
54+
// Size returns the max number of attributes that defines a collector's
55+
// instance information. Can be used to presize the attributes.
56+
func (info CollectorInstanceInfo) Size() int {
57+
return info.size
58+
}
59+
60+
func (info CollectorInstanceInfo) Copy(to pcommon.Map) {
61+
to.EnsureCapacity(info.Size())
62+
if info.serviceInstanceID != "" {
63+
to.PutStr(keyWithPrefix(semconv.AttributeServiceInstanceID), info.serviceInstanceID)
64+
}
65+
if info.serviceName != "" {
66+
to.PutStr(keyWithPrefix(semconv.AttributeServiceName), info.serviceName)
67+
}
68+
if info.serviceNamespace != "" {
69+
to.PutStr(keyWithPrefix(semconv.AttributeServiceNamespace), info.serviceNamespace)
70+
}
71+
}
72+
73+
func keyWithPrefix(key string) string {
74+
return prefix + "." + key
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package model
5+
6+
import (
7+
"reflect"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
"go.opentelemetry.io/collector/component"
13+
"go.opentelemetry.io/collector/component/componenttest"
14+
"go.opentelemetry.io/collector/pdata/pcommon"
15+
semconv "go.opentelemetry.io/collector/semconv/v1.26.0"
16+
)
17+
18+
func TestCollectorInstanceInfo(t *testing.T) {
19+
for _, tc := range []struct {
20+
name string
21+
input component.TelemetrySettings
22+
expected pcommon.Map
23+
}{
24+
{
25+
name: "empty",
26+
input: componenttest.NewNopTelemetrySettings(),
27+
expected: pcommon.NewMap(),
28+
},
29+
{
30+
name: "with_service_instance_id",
31+
input: func() component.TelemetrySettings {
32+
ts := componenttest.NewNopTelemetrySettings()
33+
ts.Resource.Attributes().PutStr(semconv.AttributeServiceInstanceID, "627cc493-f310-47de-96bd-71410b7dec09")
34+
return ts
35+
}(),
36+
expected: func() pcommon.Map {
37+
m := pcommon.NewMap()
38+
m.PutStr(
39+
"signaltometrics."+semconv.AttributeServiceInstanceID,
40+
"627cc493-f310-47de-96bd-71410b7dec09",
41+
)
42+
return m
43+
}(),
44+
},
45+
{
46+
name: "with_all_values",
47+
input: func() component.TelemetrySettings {
48+
ts := componenttest.NewNopTelemetrySettings()
49+
ts.Resource.Attributes().PutStr(semconv.AttributeServiceInstanceID, "627cc493-f310-47de-96bd-71410b7dec09")
50+
ts.Resource.Attributes().PutStr(semconv.AttributeServiceName, "signaltometrics")
51+
ts.Resource.Attributes().PutStr(semconv.AttributeServiceNamespace, "test")
52+
return ts
53+
}(),
54+
expected: func() pcommon.Map {
55+
m := pcommon.NewMap()
56+
m.PutStr(
57+
"signaltometrics."+semconv.AttributeServiceInstanceID,
58+
"627cc493-f310-47de-96bd-71410b7dec09",
59+
)
60+
m.PutStr(
61+
"signaltometrics."+semconv.AttributeServiceName,
62+
"signaltometrics",
63+
)
64+
m.PutStr(
65+
"signaltometrics."+semconv.AttributeServiceNamespace,
66+
"test",
67+
)
68+
return m
69+
}(),
70+
},
71+
} {
72+
t.Run(tc.name, func(t *testing.T) {
73+
ci := NewCollectorInstanceInfo(tc.input)
74+
require.NotNil(t, ci)
75+
76+
actual := pcommon.NewMap()
77+
ci.Copy(actual)
78+
assert.Equal(t, ci.Size(), actual.Len())
79+
assertMapEquality(t, tc.expected, actual)
80+
})
81+
}
82+
}
83+
84+
func assertMapEquality(t *testing.T, expected, actual pcommon.Map) bool {
85+
t.Helper()
86+
87+
expectedRaw := expected.AsRaw()
88+
actualRaw := actual.AsRaw()
89+
return assert.True(
90+
t, reflect.DeepEqual(expectedRaw, actualRaw),
91+
"attributes don't match expected: %v, actual: %v",
92+
expectedRaw, actualRaw,
93+
)
94+
}

connector/signaltometricsconnector/internal/model/model.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,19 @@ func (md *MetricDef[K]) FromMetricInfo(
172172
// definition.
173173
func (md *MetricDef[K]) FilterResourceAttributes(
174174
attrs pcommon.Map,
175+
collectorInfo *CollectorInstanceInfo,
175176
) pcommon.Map {
176177
var filteredAttributes pcommon.Map
177178
switch {
178179
case len(md.IncludeResourceAttributes) == 0:
179180
filteredAttributes = pcommon.NewMap()
180-
filteredAttributes.EnsureCapacity(attrs.Len())
181+
filteredAttributes.EnsureCapacity(attrs.Len() + collectorInfo.Size())
181182
attrs.CopyTo(filteredAttributes)
182183
default:
183-
expectedLen := len(md.IncludeResourceAttributes)
184+
expectedLen := len(md.IncludeResourceAttributes) + collectorInfo.Size()
184185
filteredAttributes = filterAttributes(attrs, md.IncludeResourceAttributes, expectedLen)
185186
}
187+
collectorInfo.Copy(filteredAttributes)
186188
return filteredAttributes
187189
}
188190

connector/signaltometricsconnector/testdata/logs/exponential_histograms/output.yaml

+18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ resourceMetrics:
77
- key: resource.foo
88
value:
99
stringValue: foo
10+
- key: signaltometrics.service.instance.id
11+
value:
12+
stringValue: 627cc493-f310-47de-96bd-71410b7dec09
13+
- key: signaltometrics.service.name
14+
value:
15+
stringValue: signaltometrics
16+
- key: signaltometrics.service.namespace
17+
value:
18+
stringValue: test
1019
scopeMetrics:
1120
- metrics:
1221
- description: Logrecords as exponential histogram with log.duration from attributes
@@ -327,6 +336,15 @@ resourceMetrics:
327336
- key: resource.foo
328337
value:
329338
stringValue: foo
339+
- key: signaltometrics.service.instance.id
340+
value:
341+
stringValue: 627cc493-f310-47de-96bd-71410b7dec09
342+
- key: signaltometrics.service.name
343+
value:
344+
stringValue: signaltometrics
345+
- key: signaltometrics.service.namespace
346+
value:
347+
stringValue: test
330348
scopeMetrics:
331349
- metrics:
332350
- description: Logrecords with resource attribute foo as exponential histogram with log.duration from attributes

connector/signaltometricsconnector/testdata/logs/histograms/output.yaml

+18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ resourceMetrics:
77
- key: resource.foo
88
value:
99
stringValue: foo
10+
- key: signaltometrics.service.instance.id
11+
value:
12+
stringValue: 627cc493-f310-47de-96bd-71410b7dec09
13+
- key: signaltometrics.service.name
14+
value:
15+
stringValue: signaltometrics
16+
- key: signaltometrics.service.namespace
17+
value:
18+
stringValue: test
1019
scopeMetrics:
1120
- metrics:
1221
- description: Logrecords as histogram with log.duration from attributes
@@ -127,6 +136,15 @@ resourceMetrics:
127136
- key: resource.foo
128137
value:
129138
stringValue: foo
139+
- key: signaltometrics.service.instance.id
140+
value:
141+
stringValue: 627cc493-f310-47de-96bd-71410b7dec09
142+
- key: signaltometrics.service.name
143+
value:
144+
stringValue: signaltometrics
145+
- key: signaltometrics.service.namespace
146+
value:
147+
stringValue: test
130148
scopeMetrics:
131149
- metrics:
132150
- description: Logrecords with resource attribute foo as histogram with log.duration from attributes

connector/signaltometricsconnector/testdata/logs/sum/output.yaml

+18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ resourceMetrics:
77
- key: resource.foo
88
value:
99
stringValue: foo
10+
- key: signaltometrics.service.instance.id
11+
value:
12+
stringValue: 627cc493-f310-47de-96bd-71410b7dec09
13+
- key: signaltometrics.service.name
14+
value:
15+
stringValue: signaltometrics
16+
- key: signaltometrics.service.namespace
17+
value:
18+
stringValue: test
1019
scopeMetrics:
1120
- metrics:
1221
- description: Count total number of log records
@@ -57,6 +66,15 @@ resourceMetrics:
5766
- key: resource.foo
5867
value:
5968
stringValue: foo
69+
- key: signaltometrics.service.instance.id
70+
value:
71+
stringValue: 627cc493-f310-47de-96bd-71410b7dec09
72+
- key: signaltometrics.service.name
73+
value:
74+
stringValue: signaltometrics
75+
- key: signaltometrics.service.namespace
76+
value:
77+
stringValue: test
6078
scopeMetrics:
6179
- metrics:
6280
- description: Count total number of log records with resource attribute foo

0 commit comments

Comments
 (0)