Skip to content

Commit 02aea8c

Browse files
author
Mark Stumpf
committed
check if monitor accepts endpoints before setting host/port
Only select smart-agent monitors can be created via endpoints. This is defined as a struct tag on the monitor configs "acceptsEndpoints". In the case where we attempt to set Host/Port on a monitor that has it's "acceptsEndpoints" value set to false, an error occurs and we do not create the monitor. This change would create the monitor but avoid setting the Host/Port fields. This allows the receiver creator to create any smart-agent monitor.
1 parent 1f9a135 commit 02aea8c

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ This Splunk OpenTelemetry Collector release includes changes from the [opentelem
1313
- [`docker_observer`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/observer/dockerobserver) to detect and create container endpoints, to be used with the [`receiver_creator`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/receivercreator) (#1044)
1414
- [`ecs_task_observer`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/observer/ecstaskobserver) to detect and create ECS task container endpoints, to be used with the [`receiver_creator`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/receivercreator) (#1125)
1515

16+
### 🧰 Bug fixes 🧰
17+
18+
- [`smartagent` receiver](https://github.com/signalfx/splunk-otel-collector/tree/main/internal/receiver/smartagentreceiver) will now attempt to create _any_ monitor from a Receiver Creator instance, disregarding its provided `endpoint`. Previously would error out if a monitor did not accept endpoints ([#1107](https://github.com/signalfx/splunk-otel-collector/pull/1107))
19+
1620
## v0.41.0
1721

1822
This Splunk OpenTelemetry Collector release includes changes from the [opentelemetry-collector v0.41.0](https://github.com/open-telemetry/opentelemetry-collector/releases/tag/v0.41.0) and the [opentelemetry-collector-contrib v0.41.0](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases/tag/v0.41.0) releases.

internal/receiver/smartagentreceiver/config.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type Config struct {
4242
// Will expand to MonitorCustomConfig Host and Port values if unset.
4343
Endpoint string `mapstructure:"endpoint"`
4444
DimensionClients []string `mapstructure:"dimensionClients"`
45+
acceptsEndpoints bool
4546
}
4647

4748
func (cfg *Config) validate() error {
@@ -110,11 +111,18 @@ func (cfg *Config) Unmarshal(componentParser *config.Map) error {
110111
return fmt.Errorf("failed setting Smart Agent Monitor config defaults: %w", err)
111112
}
112113

113-
err = setHostAndPortViaEndpoint(cfg.Endpoint, monitorConfig)
114+
cfg.acceptsEndpoints, err = monitorAcceptsEndpoints(monitorConfig)
114115
if err != nil {
115116
return err
116117
}
117118

119+
if cfg.acceptsEndpoints {
120+
err = setHostAndPortViaEndpoint(cfg.Endpoint, monitorConfig)
121+
if err != nil {
122+
return err
123+
}
124+
}
125+
118126
cfg.monitorConfig = monitorConfig.(saconfig.MonitorCustomConfig)
119127
return nil
120128
}
@@ -178,3 +186,13 @@ func setHostAndPortViaEndpoint(endpoint string, monitorConfig interface{}) error
178186

179187
return nil
180188
}
189+
190+
// Monitors can only set the "Host" and "Port" fields if they accept endpoints,
191+
// which is defined as a struct tag for each monitor config.
192+
func monitorAcceptsEndpoints(monitorConfig interface{}) (bool, error) {
193+
field, ok := reflect.TypeOf(monitorConfig).Elem().FieldByName("MonitorConfig")
194+
if !ok {
195+
return false, fmt.Errorf("could not reflect monitor config, top level MonitorConfig does not exist")
196+
}
197+
return field.Tag.Get("acceptsEndpoints") == strconv.FormatBool(true), nil
198+
}

internal/receiver/smartagentreceiver/config_test.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/signalfx/signalfx-agent/pkg/monitors/filesystems"
3131
"github.com/signalfx/signalfx-agent/pkg/monitors/haproxy"
3232
"github.com/signalfx/signalfx-agent/pkg/monitors/kubernetes/volumes"
33+
"github.com/signalfx/signalfx-agent/pkg/monitors/nagios"
3334
"github.com/signalfx/signalfx-agent/pkg/monitors/prometheusexporter"
3435
"github.com/signalfx/signalfx-agent/pkg/monitors/telegraf/common/parser"
3536
"github.com/signalfx/signalfx-agent/pkg/monitors/telegraf/monitors/exec"
@@ -74,6 +75,7 @@ func TestLoadConfig(t *testing.T) {
7475
SSLVerify: true,
7576
Timeout: timeutil.Duration(5 * time.Second),
7677
},
78+
acceptsEndpoints: true,
7779
}, haproxyCfg)
7880
require.NoError(t, haproxyCfg.validate())
7981

@@ -90,6 +92,7 @@ func TestLoadConfig(t *testing.T) {
9092
Host: "localhost",
9193
Port: 6379,
9294
},
95+
acceptsEndpoints: true,
9396
}, redisCfg)
9497
require.NoError(t, redisCfg.validate())
9598

@@ -106,6 +109,7 @@ func TestLoadConfig(t *testing.T) {
106109
Host: "localhost",
107110
Port: 8088,
108111
},
112+
acceptsEndpoints: true,
109113
}, hadoopCfg)
110114
require.NoError(t, hadoopCfg.validate())
111115

@@ -125,6 +129,7 @@ func TestLoadConfig(t *testing.T) {
125129
Port: 5309,
126130
MetricPath: "/metrics",
127131
},
132+
acceptsEndpoints: true,
128133
}, etcdCfg)
129134
require.NoError(t, etcdCfg.validate())
130135

@@ -140,6 +145,7 @@ func TestLoadConfig(t *testing.T) {
140145
},
141146
DNSLookup: &tr,
142147
},
148+
acceptsEndpoints: true,
143149
}, ntpqCfg)
144150
require.NoError(t, ntpqCfg.validate())
145151
}
@@ -213,6 +219,7 @@ func TestLoadInvalidConfigs(t *testing.T) {
213219
DatapointsToExclude: []saconfig.MetricFilter{},
214220
},
215221
},
222+
acceptsEndpoints: true,
216223
}, negativeIntervalCfg)
217224
err = negativeIntervalCfg.validate()
218225
require.Error(t, err)
@@ -231,6 +238,7 @@ func TestLoadInvalidConfigs(t *testing.T) {
231238
TelemetryHost: "0.0.0.0",
232239
TelemetryPort: 8125,
233240
},
241+
acceptsEndpoints: true,
234242
}, missingRequiredCfg)
235243
err = missingRequiredCfg.validate()
236244
require.Error(t, err)
@@ -270,6 +278,7 @@ func TestLoadConfigWithEndpoints(t *testing.T) {
270278
SSLVerify: true,
271279
Timeout: timeutil.Duration(5 * time.Second),
272280
},
281+
acceptsEndpoints: true,
273282
}, haproxyCfg)
274283
require.NoError(t, haproxyCfg.validate())
275284

@@ -286,6 +295,7 @@ func TestLoadConfigWithEndpoints(t *testing.T) {
286295
Host: "redishost",
287296
Port: 6379,
288297
},
298+
acceptsEndpoints: true,
289299
}, redisCfg)
290300
require.NoError(t, redisCfg.validate())
291301

@@ -303,6 +313,7 @@ func TestLoadConfigWithEndpoints(t *testing.T) {
303313
Host: "localhost",
304314
Port: 8088,
305315
},
316+
acceptsEndpoints: true,
306317
}, hadoopCfg)
307318
require.NoError(t, hadoopCfg.validate())
308319

@@ -323,6 +334,7 @@ func TestLoadConfigWithEndpoints(t *testing.T) {
323334
Port: 5555,
324335
MetricPath: "/metrics",
325336
},
337+
acceptsEndpoints: true,
326338
}, etcdCfg)
327339
require.NoError(t, etcdCfg.validate())
328340
}
@@ -342,7 +354,9 @@ func TestLoadInvalidConfigWithInvalidEndpoint(t *testing.T) {
342354
require.Nil(t, cfg)
343355
}
344356

345-
func TestLoadInvalidConfigWithUnsupportedEndpoint(t *testing.T) {
357+
// Even though this smart-agent monitor does not accept endpoints,
358+
// we can create it without setting Host/Port fields.
359+
func TestLoadConfigWithUnsupportedEndpoint(t *testing.T) {
346360
factories, err := componenttest.NopFactories()
347361
assert.Nil(t, err)
348362

@@ -351,10 +365,25 @@ func TestLoadInvalidConfigWithUnsupportedEndpoint(t *testing.T) {
351365
cfg, err := servicetest.LoadConfig(
352366
path.Join(".", "testdata", "unsupported_endpoint.yaml"), factories,
353367
)
354-
require.Error(t, err)
355-
require.EqualError(t, err,
356-
`error reading receivers configuration for "smartagent/nagios": unable to set monitor Host field using Endpoint-derived value of localhost: no field Host of type string detected`)
357-
require.Nil(t, cfg)
368+
require.NoError(t, err)
369+
require.NotNil(t, cfg)
370+
371+
nagiosCfg := cfg.Receivers[config.NewComponentIDWithName(typeStr, "nagios")].(*Config)
372+
require.Equal(t, &Config{
373+
Endpoint: "localhost:12345",
374+
ReceiverSettings: config.NewReceiverSettings(config.NewComponentIDWithName(typeStr, "nagios")),
375+
monitorConfig: &nagios.Config{
376+
MonitorConfig: saconfig.MonitorConfig{
377+
Type: "nagios",
378+
DatapointsToExclude: []saconfig.MetricFilter{},
379+
},
380+
Command: "some_command",
381+
Service: "some_service",
382+
Timeout: 9,
383+
},
384+
acceptsEndpoints: false,
385+
}, nagiosCfg)
386+
require.NoError(t, nagiosCfg.validate())
358387
}
359388

360389
func TestLoadInvalidConfigWithNonArrayDimensionClients(t *testing.T) {

internal/receiver/smartagentreceiver/receiver.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ func (r *Receiver) Start(_ context.Context, host component.Host) error {
112112
monitorType: r.config.monitorConfig.MonitorConfigCore().Type,
113113
}, r.logger)
114114

115+
if !r.config.acceptsEndpoints {
116+
r.logger.Info("This Smart Agent monitor does not use Host/Port config fields. If either are set, they will be ignored.", zap.String("monitor_type", monitorType))
117+
}
115118
r.monitor, err = r.createMonitor(monitorType, host)
116119
if err != nil {
117120
return fmt.Errorf("failed creating monitor %q: %w", monitorType, err)

0 commit comments

Comments
 (0)