Skip to content

Commit fa620f1

Browse files
Allow opamp extension to include resource attributes automatically (#38994)
#### Description Introduces a new config struct element `IncludeResourceAttributes` which when enabled (default is false) copies the set resource attributes from the agent into the non-identifying attributes in the agent description message. #### Link to tracking issue Fixes #37487 #### Testing Unit #### Documentation n/a --------- Co-authored-by: Evan Bradley <[email protected]>
1 parent 2d91302 commit fa620f1

File tree

6 files changed

+82
-3
lines changed

6 files changed

+82
-3
lines changed
Lines changed: 27 additions & 0 deletions
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: opampextension
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Introduces a new config field `include_resource_attributes` which allows the extension to copy the agent's resource attributes to the non-identifying attributes in the agent description.
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: [37487]
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]

extension/opampextension/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ The following settings are optional for both transports:
4747
- `reports_health`: Whether to enable the OpAMP ReportsHealth capability. Default is `true`.
4848
- `reports_available_components`: Whether to enable the OpAMP ReportsAvailableComponents capability. Default is `true`.
4949
- `agent_description`: Setting that modifies the agent description reported to the OpAMP server.
50+
- `include_resource_attributes`: Copy the Collector's resource attributes into the set of non-identifying attributes in the agent description.
5051
- `non_identifying_attributes`: A map of key value pairs that will be added to the [non-identifying attributes](https://github.com/open-telemetry/opamp-spec/blob/main/specification.md#agentdescriptionnon_identifying_attributes) reported to the OpAMP server. If an attribute collides with the default non-identifying attributes that are automatically added, the ones specified here take precedence.
5152
- `ppid`: An optional process ID to monitor. When this process is no longer running, the extension will emit a fatal error, causing the collector to exit. This is meant to be set by the Supervisor or some other parent process, and should not be configured manually.
5253
- `ppid_poll_interval`: The poll interval between check for whether `ppid` is still alive or not. Defaults to 5 seconds.

extension/opampextension/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ type AgentDescription struct {
4949
// NonIdentifyingAttributes are a map of key-value pairs that may be specified to provide
5050
// extra information about the agent to the OpAMP server.
5151
NonIdentifyingAttributes map[string]string `mapstructure:"non_identifying_attributes"`
52+
// IncludeResourceAttributes determines whether the agent should copy its resource attributes
53+
// to the non identifying attributes. (default: false)
54+
IncludeResourceAttributes bool `mapstructure:"include_resource_attributes"`
5255
}
5356

5457
type Capabilities struct {

extension/opampextension/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ require (
111111
github.com/tklauser/go-sysconf v0.3.14 // indirect
112112
github.com/tklauser/numcpus v0.8.0 // indirect
113113
github.com/yusufpapurcu/wmi v1.2.4 // indirect
114-
go.opentelemetry.io/collector/pdata v1.30.0 // indirect
114+
go.opentelemetry.io/collector/pdata v1.30.0
115115
go.opentelemetry.io/collector/pipeline v0.124.0 // indirect
116116
go.opentelemetry.io/otel v1.35.0 // indirect
117117
go.opentelemetry.io/otel/metric v1.35.0 // indirect

extension/opampextension/opamp_agent.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"go.opentelemetry.io/collector/confmap"
2727
"go.opentelemetry.io/collector/extension"
2828
"go.opentelemetry.io/collector/extension/extensioncapabilities"
29+
"go.opentelemetry.io/collector/pdata/pcommon"
2930
semconv "go.opentelemetry.io/collector/semconv/v1.27.0"
3031
"go.opentelemetry.io/collector/service"
3132
"go.uber.org/zap"
@@ -52,8 +53,9 @@ type opampAgent struct {
5253
cfg *Config
5354
logger *zap.Logger
5455

55-
agentType string
56-
agentVersion string
56+
agentType string
57+
agentVersion string
58+
resourceAttrs map[string]string
5759

5860
instanceID uuid.UUID
5961

@@ -89,6 +91,14 @@ var (
8991
_ extensioncapabilities.ConfigWatcher = (*opampAgent)(nil)
9092
_ extensioncapabilities.PipelineWatcher = (*opampAgent)(nil)
9193
_ componentstatus.Watcher = (*opampAgent)(nil)
94+
95+
// identifyingAttributes is the list of semantic convention keys that are used
96+
// for the agent description's identifying attributes.
97+
identifyingAttributes = map[string]struct{}{
98+
semconv.AttributeServiceName: {},
99+
semconv.AttributeServiceVersion: {},
100+
semconv.AttributeServiceInstanceID: {},
101+
}
92102
)
93103

94104
// moduleInfo exposes the internal collector moduleInfo interface
@@ -303,6 +313,11 @@ func newOpampAgent(cfg *Config, set extension.Settings) (*opampAgent, error) {
303313
}
304314
}
305315
}
316+
resourceAttrs := make(map[string]string, set.Resource.Attributes().Len())
317+
set.Resource.Attributes().Range(func(k string, v pcommon.Value) bool {
318+
resourceAttrs[k] = v.Str()
319+
return true
320+
})
306321

307322
opampClient := cfg.Server.GetClient(set.Logger)
308323
agent := &opampAgent{
@@ -313,6 +328,7 @@ func newOpampAgent(cfg *Config, set extension.Settings) (*opampAgent, error) {
313328
instanceID: uid,
314329
capabilities: cfg.Capabilities,
315330
opampClient: opampClient,
331+
resourceAttrs: resourceAttrs,
316332
statusSubscriptionWg: &sync.WaitGroup{},
317333
componentHealthWg: &sync.WaitGroup{},
318334
readyCh: make(chan struct{}),
@@ -375,6 +391,15 @@ func (o *opampAgent) createAgentDescription() error {
375391
for k, v := range o.cfg.AgentDescription.NonIdentifyingAttributes {
376392
nonIdentifyingAttributeMap[k] = v
377393
}
394+
if o.cfg.AgentDescription.IncludeResourceAttributes {
395+
for k, v := range o.resourceAttrs {
396+
// skip the attributes that are being used in the identifying attributes.
397+
if _, ok := identifyingAttributes[k]; ok {
398+
continue
399+
}
400+
nonIdentifyingAttributeMap[k] = v
401+
}
402+
}
378403

379404
// Sort the non identifying attributes to give them a stable order for tests
380405
keys := maps.Keys(nonIdentifyingAttributeMap)

extension/opampextension/opamp_agent_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func TestCreateAgentDescription(t *testing.T) {
7171
serviceName := "otelcol-distrot"
7272
serviceVersion := "distro.0"
7373
serviceInstanceUUID := "f8999bc1-4c9b-4619-9bae-7f009d2411ec"
74+
extraResourceAttrKey := "hello"
75+
extraResourceAttrValue := "world"
7476

7577
testCases := []struct {
7678
name string
@@ -140,6 +142,26 @@ func TestCreateAgentDescription(t *testing.T) {
140142
},
141143
},
142144
},
145+
{
146+
name: "Set IncludeResourceAttributes",
147+
cfg: func(c *Config) {
148+
c.AgentDescription.IncludeResourceAttributes = true
149+
},
150+
expected: &protobufs.AgentDescription{
151+
IdentifyingAttributes: []*protobufs.KeyValue{
152+
stringKeyValue(semconv.AttributeServiceInstanceID, serviceInstanceUUID),
153+
stringKeyValue(semconv.AttributeServiceName, serviceName),
154+
stringKeyValue(semconv.AttributeServiceVersion, serviceVersion),
155+
},
156+
NonIdentifyingAttributes: []*protobufs.KeyValue{
157+
stringKeyValue(extraResourceAttrKey, extraResourceAttrValue),
158+
stringKeyValue(semconv.AttributeHostArch, runtime.GOARCH),
159+
stringKeyValue(semconv.AttributeHostName, hostname),
160+
stringKeyValue(semconv.AttributeOSDescription, description),
161+
stringKeyValue(semconv.AttributeOSType, runtime.GOOS),
162+
},
163+
},
164+
},
143165
}
144166

145167
for _, tc := range testCases {
@@ -151,6 +173,7 @@ func TestCreateAgentDescription(t *testing.T) {
151173
set.Resource.Attributes().PutStr(semconv.AttributeServiceName, serviceName)
152174
set.Resource.Attributes().PutStr(semconv.AttributeServiceVersion, serviceVersion)
153175
set.Resource.Attributes().PutStr(semconv.AttributeServiceInstanceID, serviceInstanceUUID)
176+
set.Resource.Attributes().PutStr(extraResourceAttrKey, extraResourceAttrValue)
154177

155178
o, err := newOpampAgent(cfg, set)
156179
require.NoError(t, err)

0 commit comments

Comments
 (0)