Skip to content

Commit 18be1ab

Browse files
authored
Discovery configuration: replace regular expressions by "globs" (#31)
* Move regexp config to Globs * Fix some integration test service selectors * Fix the configuration of exe_path in integration tests * Test Php-fpm integration tests * fix some k8s tests
1 parent 6ce9493 commit 18be1ab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+181
-179
lines changed

pkg/beyla/config.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"fmt"
55
"io"
66
"log/slog"
7-
"regexp"
87
"time"
98

109
"github.com/caarlos0/env/v9"
10+
"github.com/gobwas/glob"
1111
"gopkg.in/yaml.v3"
1212

1313
"github.com/open-telemetry/opentelemetry-ebpf-instrumentation/pkg/config"
@@ -129,8 +129,8 @@ var DefaultConfig = Config{
129129
ExcludeOTelInstrumentedServices: true,
130130
DefaultExcludeServices: services.DefinitionCriteria{
131131
services.Attributes{
132-
// TODO: add final name for opentelemetry-ebpf-instrument executable name
133-
Path: services.NewPathRegexp(regexp.MustCompile("(?:^|/)(beyla$|alloy$|otelcol[^/]*$)")),
132+
// excluding telemetry components from being instrumented
133+
Path: services.NewGlob(glob.MustCompile("{*beyla,*alloy,*ebpf-instrument,*otelcol,*otelcol-contrib,*otelcol-contrib[!/]*}")),
134134
},
135135
},
136136
},
@@ -159,9 +159,11 @@ type Config struct {
159159
TracePrinter debug.TracePrinter `yaml:"trace_printer" env:"OTEL_EBPF_TRACE_PRINTER"`
160160

161161
// Exec allows selecting the instrumented executable whose complete path contains the Exec value.
162-
Exec services.RegexpAttr `yaml:"executable_name" env:"OTEL_EBPF_EXECUTABLE_NAME"`
162+
// TODO: setup an EXECUTABLE_NAME property that only cares about the executable name, ignoring the path
163+
Exec services.GlobAttr `yaml:"executable_path" env:"OTEL_EBPF_EXECUTABLE_PATH"`
164+
163165
//nolint:undoc
164-
ExecOtelGo services.RegexpAttr `env:"OTEL_GO_AUTO_TARGET_EXE"`
166+
ExecOtelGo services.GlobAttr `env:"OTEL_GO_AUTO_TARGET_EXE"`
165167
// Port allows selecting the instrumented executable that owns the Port value. If this value is set (and
166168
// different to zero), the value of the Exec property won't take effect.
167169
// It's important to emphasize that if your process opens multiple HTTP/GRPC ports, the auto-instrumenter
@@ -234,7 +236,7 @@ func (c *Config) Validate() error {
234236
return ConfigError("missing to enable application discovery or network metrics. Check documentation")
235237
}
236238
if (c.Port.Len() > 0 || c.Exec.IsSet() || len(c.Discovery.Services) > 0) && c.Discovery.SystemWide {
237-
return ConfigError("you can't use OTEL_EBPF_SYSTEM_WIDE if any of OTEL_EBPF_EXECUTABLE_NAME, OTEL_EBPF_OPEN_PORT or services (YAML) are set")
239+
return ConfigError("you can't use OTEL_EBPF_SYSTEM_WIDE if any of OTEL_EBPF_EXECUTABLE_PATH, OTEL_EBPF_OPEN_PORT or services (YAML) are set")
238240
}
239241
if c.EBPF.BatchLength == 0 {
240242
return ConfigError("OTEL_EBPF_BPF_BATCH_LENGTH must be at least 1")
@@ -364,7 +366,7 @@ func LoadConfig(file io.Reader) (*Config, error) {
364366
return nil, fmt.Errorf("reading env vars: %w", err)
365367
}
366368

367-
// We support OTEL_GO_AUTO_TARGET_EXE as an alias to OTEL_EBPF_EXECUTABLE_NAME
369+
// We support OTEL_GO_AUTO_TARGET_EXE as an alias to OTEL_EBPF_EXECUTABLE_PATH
368370
if !cfg.Exec.IsSet() && cfg.ExecOtelGo.IsSet() {
369371
cfg.Exec = cfg.ExecOtelGo
370372
}

pkg/beyla/config_test.go

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"testing"
1212
"time"
1313

14+
"github.com/gobwas/glob"
1415
"github.com/stretchr/testify/assert"
1516
"github.com/stretchr/testify/require"
1617

@@ -71,8 +72,11 @@ network:
7172
enable: true
7273
cidrs:
7374
- 10.244.0.0/16
75+
discovery:
76+
default_exclude_services:
77+
- exe_path: "*foo*"
7478
`)
75-
t.Setenv("OTEL_EBPF_EXECUTABLE_NAME", "tras")
79+
t.Setenv("OTEL_EBPF_EXECUTABLE_PATH", "*tras*")
7680
t.Setenv("OTEL_EBPF_NETWORK_AGENT_IP", "1.2.3.4")
7781
t.Setenv("OTEL_EBPF_OPEN_PORT", "8080-8089")
7882
t.Setenv("OTEL_SERVICE_NAME", "svc-name")
@@ -212,7 +216,7 @@ network:
212216
ExcludeOTelInstrumentedServices: true,
213217
DefaultExcludeServices: services.DefinitionCriteria{
214218
services.Attributes{
215-
Path: services.NewPathRegexp(regexp.MustCompile("(?:^|/)(beyla$|alloy$|otelcol[^/]*$)")),
219+
Path: services.NewGlob(glob.MustCompile("*foo*")),
216220
},
217221
},
218222
},
@@ -237,15 +241,15 @@ func TestConfig_ShutdownTimeout(t *testing.T) {
237241

238242
func TestConfigValidate(t *testing.T) {
239243
testCases := []envMap{
240-
{"OTEL_EXPORTER_OTLP_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_NAME": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
241-
{"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_NAME": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
242-
{"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_NAME": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
243-
{"OTEL_EBPF_TRACE_PRINTER": "text", "OTEL_EBPF_SHUTDOWN_TIMEOUT": "1m", "OTEL_EBPF_EXECUTABLE_NAME": "foo"},
244-
{"OTEL_EBPF_TRACE_PRINTER": "json", "OTEL_EBPF_EXECUTABLE_NAME": "foo"},
245-
{"OTEL_EBPF_TRACE_PRINTER": "json_indent", "OTEL_EBPF_EXECUTABLE_NAME": "foo"},
246-
{"OTEL_EBPF_TRACE_PRINTER": "counter", "OTEL_EBPF_EXECUTABLE_NAME": "foo"},
247-
{"OTEL_EBPF_PROMETHEUS_PORT": "8080", "OTEL_EBPF_EXECUTABLE_NAME": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
248-
{"OTEL_EBPF_INTERNAL_OTEL_METRICS": "true", "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_NAME": "foo"},
244+
{"OTEL_EXPORTER_OTLP_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_PATH": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
245+
{"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_PATH": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
246+
{"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_PATH": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
247+
{"OTEL_EBPF_TRACE_PRINTER": "text", "OTEL_EBPF_SHUTDOWN_TIMEOUT": "1m", "OTEL_EBPF_EXECUTABLE_PATH": "foo"},
248+
{"OTEL_EBPF_TRACE_PRINTER": "json", "OTEL_EBPF_EXECUTABLE_PATH": "foo"},
249+
{"OTEL_EBPF_TRACE_PRINTER": "json_indent", "OTEL_EBPF_EXECUTABLE_PATH": "foo"},
250+
{"OTEL_EBPF_TRACE_PRINTER": "counter", "OTEL_EBPF_EXECUTABLE_PATH": "foo"},
251+
{"OTEL_EBPF_PROMETHEUS_PORT": "8080", "OTEL_EBPF_EXECUTABLE_PATH": "foo", "INSTRUMENT_FUNC_NAME": "bar"},
252+
{"OTEL_EBPF_INTERNAL_OTEL_METRICS": "true", "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": "localhost:1234", "OTEL_EBPF_EXECUTABLE_PATH": "foo"},
249253
}
250254
for n, tc := range testCases {
251255
t.Run(fmt.Sprint("case", n), func(t *testing.T) {
@@ -257,9 +261,9 @@ func TestConfigValidate(t *testing.T) {
257261
func TestConfigValidate_error(t *testing.T) {
258262
testCases := []envMap{
259263
{"OTEL_EXPORTER_OTLP_ENDPOINT": "localhost:1234", "INSTRUMENT_FUNC_NAME": "bar"},
260-
{"OTEL_EBPF_EXECUTABLE_NAME": "foo", "INSTRUMENT_FUNC_NAME": "bar", "OTEL_EBPF_TRACE_PRINTER": "disabled"},
261-
{"OTEL_EBPF_EXECUTABLE_NAME": "foo", "INSTRUMENT_FUNC_NAME": "bar", "OTEL_EBPF_TRACE_PRINTER": ""},
262-
{"OTEL_EBPF_EXECUTABLE_NAME": "foo", "INSTRUMENT_FUNC_NAME": "bar", "OTEL_EBPF_TRACE_PRINTER": "invalid"},
264+
{"OTEL_EBPF_EXECUTABLE_PATH": "foo", "INSTRUMENT_FUNC_NAME": "bar", "OTEL_EBPF_TRACE_PRINTER": "disabled"},
265+
{"OTEL_EBPF_EXECUTABLE_PATH": "foo", "INSTRUMENT_FUNC_NAME": "bar", "OTEL_EBPF_TRACE_PRINTER": ""},
266+
{"OTEL_EBPF_EXECUTABLE_PATH": "foo", "INSTRUMENT_FUNC_NAME": "bar", "OTEL_EBPF_TRACE_PRINTER": "invalid"},
263267
}
264268
for n, tc := range testCases {
265269
t.Run(fmt.Sprint("case", n), func(t *testing.T) {
@@ -331,11 +335,11 @@ func TestConfigValidate_TracePrinter(t *testing.T) {
331335

332336
testCases := []test{
333337
{
334-
env: envMap{"OTEL_EBPF_EXECUTABLE_NAME": "foo", "OTEL_EBPF_TRACE_PRINTER": "invalid_printer"},
338+
env: envMap{"OTEL_EBPF_EXECUTABLE_PATH": "foo", "OTEL_EBPF_TRACE_PRINTER": "invalid_printer"},
335339
errorMsg: "invalid value for trace_printer: 'invalid_printer'",
336340
},
337341
{
338-
env: envMap{"OTEL_EBPF_EXECUTABLE_NAME": "foo"},
342+
env: envMap{"OTEL_EBPF_EXECUTABLE_PATH": "foo"},
339343
errorMsg: "you need to define at least one exporter: trace_printer, grafana, otel_metrics_export, otel_traces_export or prometheus_export",
340344
},
341345
}
@@ -352,7 +356,7 @@ func TestConfigValidate_TracePrinter(t *testing.T) {
352356
}
353357

354358
func TestConfigValidate_TracePrinterFallback(t *testing.T) {
355-
env := envMap{"OTEL_EBPF_EXECUTABLE_NAME": "foo", "OTEL_EBPF_TRACE_PRINTER": "text"}
359+
env := envMap{"OTEL_EBPF_EXECUTABLE_PATH": "foo", "OTEL_EBPF_TRACE_PRINTER": "text"}
356360

357361
cfg := loadConfig(t, env)
358362
err := cfg.Validate()
@@ -361,7 +365,7 @@ func TestConfigValidate_TracePrinterFallback(t *testing.T) {
361365
}
362366

363367
func TestConfigValidateRoutes(t *testing.T) {
364-
userConfig := bytes.NewBufferString(`executable_name: foo
368+
userConfig := bytes.NewBufferString(`executable_path: foo
365369
trace_printer: text
366370
routes:
367371
unmatched: heuristic
@@ -374,12 +378,12 @@ routes:
374378

375379
func TestConfigValidateRoutes_Errors(t *testing.T) {
376380
for _, tc := range []string{
377-
`executable_name: foo
381+
`executable_path: foo
378382
trace_printer: text
379383
routes:
380384
unmatched: heuristic
381385
wildcard_char: "##"
382-
`, `executable_name: foo
386+
`, `executable_path: foo
383387
trace_printer: text
384388
routes:
385389
unmatched: heuristic
@@ -397,16 +401,16 @@ routes:
397401
}
398402

399403
func TestConfig_OtelGoAutoEnv(t *testing.T) {
400-
// OTEL_GO_AUTO_TARGET_EXE is an alias to OTEL_EBPF_EXECUTABLE_NAME
404+
// OTEL_GO_AUTO_TARGET_EXE is an alias to OTEL_EBPF_EXECUTABLE_PATH
401405
// (Compatibility with OpenTelemetry)
402406
t.Setenv("OTEL_GO_AUTO_TARGET_EXE", "testserver")
403407
cfg, err := LoadConfig(bytes.NewReader(nil))
404408
require.NoError(t, err)
405-
assert.True(t, cfg.Exec.IsSet()) // Exec maps to OTEL_EBPF_EXECUTABLE_NAME
409+
assert.True(t, cfg.Exec.IsSet()) // Exec maps to OTEL_EBPF_EXECUTABLE_PATH
406410
}
407411

408412
func TestConfig_NetworkImplicit(t *testing.T) {
409-
// OTEL_GO_AUTO_TARGET_EXE is an alias to OTEL_EBPF_EXECUTABLE_NAME
413+
// OTEL_GO_AUTO_TARGET_EXE is an alias to OTEL_EBPF_EXECUTABLE_PATH
410414
// (Compatibility with OpenTelemetry)
411415
t.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4318")
412416
t.Setenv("OTEL_EBPF_OTEL_METRIC_FEATURES", "network")
@@ -416,7 +420,7 @@ func TestConfig_NetworkImplicit(t *testing.T) {
416420
}
417421

418422
func TestConfig_NetworkImplicitProm(t *testing.T) {
419-
// OTEL_GO_AUTO_TARGET_EXE is an alias to OTEL_EBPF_EXECUTABLE_NAME
423+
// OTEL_GO_AUTO_TARGET_EXE is an alias to OTEL_EBPF_EXECUTABLE_PATH
420424
// (Compatibility with OpenTelemetry)
421425
t.Setenv("OTEL_EBPF_PROMETHEUS_PORT", "9090")
422426
t.Setenv("OTEL_EBPF_PROMETHEUS_FEATURES", "network")

pkg/internal/discover/matcher.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66
"fmt"
77
"log/slog"
88
"os"
9-
"regexp"
109
"slices"
1110

11+
"github.com/gobwas/glob"
1212
"github.com/shirou/gopsutil/v3/process"
1313

1414
"github.com/open-telemetry/opentelemetry-ebpf-instrumentation/pkg/beyla"
@@ -145,8 +145,8 @@ func (m *matcher) matchProcess(obj *processAttrs, p *services.ProcessInfo, a *se
145145
log.Debug("no Kube metadata, no local selection criteria. Ignoring")
146146
return false
147147
}
148-
if (a.Path.IsSet() || a.PathRegexp.IsSet()) && !m.matchByExecutable(p, a) {
149-
log.Debug("executable path does not match", "path", a.Path, "pathregexp", a.PathRegexp)
148+
if a.Path.IsSet() && !m.matchByExecutable(p, a) {
149+
log.Debug("executable path does not match", "path", a.Path)
150150
return false
151151
}
152152
if a.OpenPorts.Len() > 0 && !m.matchByPort(p, a) {
@@ -169,10 +169,7 @@ func (m *matcher) matchByPort(p *services.ProcessInfo, a *services.Attributes) b
169169
}
170170

171171
func (m *matcher) matchByExecutable(p *services.ProcessInfo, a *services.Attributes) bool {
172-
if a.Path.IsSet() {
173-
return a.Path.MatchString(p.ExePath)
174-
}
175-
return a.PathRegexp.MatchString(p.ExePath)
172+
return a.Path.MatchString(p.ExePath)
176173
}
177174

178175
func (m *matcher) matchByAttributes(actual *processAttrs, required *services.Attributes) bool {
@@ -215,7 +212,7 @@ func FindingCriteria(cfg *beyla.Config) services.DefinitionCriteria {
215212
return services.DefinitionCriteria{
216213
services.Attributes{
217214
Namespace: cfg.ServiceNamespace,
218-
Path: services.NewPathRegexp(regexp.MustCompile(".")),
215+
Path: services.NewGlob(glob.MustCompile("**")),
219216
},
220217
}
221218
}
@@ -238,7 +235,7 @@ func FindingCriteria(cfg *beyla.Config) services.DefinitionCriteria {
238235
fc := &finderCriteria[i]
239236
if !fc.Path.IsSet() && fc.OpenPorts.Len() == 0 && (len(fc.Metadata) > 0 || len(fc.PodLabels) > 0 || len(fc.PodAnnotations) > 0) {
240237
// match any executable path
241-
if err := fc.Path.UnmarshalText([]byte(".")); err != nil {
238+
if err := fc.Path.UnmarshalText([]byte("**")); err != nil {
242239
panic("bug! " + err.Error())
243240
}
244241
}

pkg/internal/discover/matcher_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ func TestCriteriaMatcher(t *testing.T) {
2121
namespace: foo
2222
open_ports: 80,8080-8089
2323
- name: exec-only
24-
exe_path: weird\d
24+
exe_path: "*weird[0-9]*"
2525
- name: both
2626
open_ports: 443
27-
exe_path_regexp: "server"
27+
exe_path: "*server*"
2828
`), &pipeConfig))
2929

3030
discoveredProcesses := msg.NewQueue[[]Event[processAttrs]](msg.ChannelBufferLen(10))
@@ -84,12 +84,12 @@ func TestCriteriaMatcher_Exclude(t *testing.T) {
8484
namespace: foo
8585
open_ports: 80,8080-8089
8686
- name: exec-only
87-
exe_path: weird\d
87+
exe_path: "*weird*"
8888
- name: both
8989
open_ports: 443
90-
exe_path_regexp: "server"
90+
exe_path: "*server*"
9191
exclude_services:
92-
- exe_path: s
92+
- exe_path: "*s*"
9393
`), &pipeConfig))
9494

9595
discoveredProcesses := msg.NewQueue[[]Event[processAttrs]](msg.ChannelBufferLen(10))
@@ -135,7 +135,7 @@ func TestCriteriaMatcher_Exclude_Metadata(t *testing.T) {
135135
pipeConfig := beyla.Config{}
136136
require.NoError(t, yaml.Unmarshal([]byte(`discovery:
137137
services:
138-
- k8s_node_name: .
138+
- k8s_node_name: "*"
139139
exclude_services:
140140
- k8s_node_name: bar
141141
`), &pipeConfig))
@@ -184,11 +184,11 @@ func TestCriteriaMatcher_MustMatchAllAttributes(t *testing.T) {
184184
- name: all-attributes-must-match
185185
namespace: foons
186186
open_ports: 80,8080-8089
187-
exe_path: foo
188-
k8s_namespace: thens
189-
k8s_pod_name: thepod
190-
k8s_deployment_name: thedepl
191-
k8s_replicaset_name: thers
187+
exe_path: "*foo*"
188+
k8s_namespace: "*thens*"
189+
k8s_pod_name: "*thepod*"
190+
k8s_deployment_name: "*thedepl*"
191+
k8s_replicaset_name: "*thers*"
192192
`), &pipeConfig))
193193

194194
discoveredProcesses := msg.NewQueue[[]Event[processAttrs]](msg.ChannelBufferLen(10))

pkg/internal/discover/watcher_kube_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,21 +132,21 @@ func TestWatcherKubeEnricherWithMatcher(t *testing.T) {
132132
k8s_pod_name: chichi
133133
- name: both
134134
open_ports: 443
135-
k8s_deployment_name: chacha
135+
k8s_deployment_name: chacha*
136136
- name: pod-label-only
137137
k8s_pod_labels:
138138
instrument: "beyla"
139139
- name: pod-multi-label-only
140140
k8s_pod_labels:
141141
instrument: "ebpf"
142-
lang: "go.*"
142+
lang: "go*"
143143
- name: pod-annotation-only
144144
k8s_pod_annotations:
145145
deploy.type: "canary"
146146
- name: pod-multi-annotation-only
147147
k8s_pod_annotations:
148148
deploy.type: "prod"
149-
version: "v\\d+"
149+
version: "v[0-9]*"
150150
`), &pipeConfig))
151151

152152
swi.Add(CriteriaMatcherProvider(&pipeConfig, connectQueue, outputQueue))

0 commit comments

Comments
 (0)