Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[usm] service discovery, fetch only target environment variables from /proc #29574

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
3039db8
[usm] service discovery, fetch only target environment variables from…
yuri-lipnesh Sep 25, 2024
8f6f4de
[usm] service discovery, improved event scanner performance
yuri-lipnesh Sep 27, 2024
09c8074
[usm] service discovery, use bufio.Scanner() to read /proc/<pid>/environ
yuri-lipnesh Sep 30, 2024
e34c68d
[usm] service discovery, comment exported variables to satisfy linter
yuri-lipnesh Sep 30, 2024
42b8cfe
[usm] service discovery, replace getEnvironPath() with kernel.HostPro…
yuri-lipnesh Oct 1, 2024
cdf477e
[usm] service discovery, add package targetenvs - source of truth for…
yuri-lipnesh Oct 3, 2024
5dcd755
[usm] service discovery, change name of const variable to satisfy linter
yuri-lipnesh Oct 3, 2024
b3acdb3
[usm] service discovery, set a build constraint 'go:build linux' in e…
yuri-lipnesh Oct 4, 2024
788c3b2
[usm] service discovery, rm ptracer.TextScannerIterator, do not impor…
yuri-lipnesh Oct 4, 2024
57dc567
[usm] service discovery, only non-linux in targetenvs pkg, add target…
yuri-lipnesh Oct 4, 2024
947e07a
[usm] service discovery, read env vars refactored, added EnvironmentV…
yuri-lipnesh Oct 8, 2024
b4b278c
[usm] service discovery, read env vars, fix linter error - remove unu…
yuri-lipnesh Oct 8, 2024
afcf84f
[usm] service discovery, read env vars, enhanced end of search in Env…
yuri-lipnesh Oct 9, 2024
6cafb58
[usm] service discovery, read env vars, remove optimization with stop…
yuri-lipnesh Oct 9, 2024
40e87c2
[usm] service discovery, read env vars, +envs/envs_testutils.go to se…
yuri-lipnesh Oct 10, 2024
44e65ff
[usm] service discovery, read env vars, pre-allocation of the map and…
yuri-lipnesh Oct 10, 2024
dcf19a7
[usm] service discovery, remove ret val in EnvReader.add(), +envs.Var…
yuri-lipnesh Oct 10, 2024
45cc90a
[usm] service discovery, read env vars, add comment to envs.Variables…
yuri-lipnesh Oct 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 23 additions & 63 deletions pkg/collector/corechecks/servicediscovery/apm/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"strings"

"github.com/DataDog/datadog-agent/pkg/collector/corechecks/servicediscovery/language"
"github.com/DataDog/datadog-agent/pkg/collector/corechecks/servicediscovery/targetenvs"
"github.com/DataDog/datadog-agent/pkg/collector/corechecks/servicediscovery/usm"
"github.com/DataDog/datadog-agent/pkg/network/go/bininspect"
"github.com/DataDog/datadog-agent/pkg/util/kernel"
Expand All @@ -37,6 +38,21 @@ const (
Injected Instrumentation = "injected"
)

const (
yuri-lipnesh marked this conversation as resolved.
Show resolved Hide resolved
// ddTraceGoPrefix is the prefix of the dd-trace-go symbols. The symbols we
// are looking for are for example
// "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.init". We use a prefix
// without the version number instead of a specific symbol name in an
// attempt to make it future-proof.
ddTraceGoPrefix = "gopkg.in/DataDog/dd-trace-go"
// ddTraceGoMaxLength is the maximum length of the dd-trace-go symbols which
// we look for. The max length is an optimization in bininspect to avoid
// reading unnecesssary symbols. As of writing, most non-internal symbols
// in dd-trace-go are under 100 chars. The tracer.init example above at 51
// chars is one of the shortest.
ddTraceGoMaxLength = 100
)

type detector func(pid int, args []string, envs map[string]string, contextMap usm.DetectorContextMap) Instrumentation

var (
Expand All @@ -51,36 +67,12 @@ var (
nodeAPMCheckRegex = regexp.MustCompile(`"dd-trace"`)
)

// JavaDetectorEnvs list of environment variables used for Java detection
var JavaDetectorEnvs = []string{
// These are the environment variables that are used to pass options to the JVM
"JAVA_TOOL_OPTIONS",
"_JAVA_OPTIONS",
"JDK_JAVA_OPTIONS",
// I'm pretty sure these won't be necessary, as they should be parsed before the JVM sees them
// but there's no harm in including them
"JAVA_OPTIONS",
"CATALINA_OPTS",
"JDPA_OPTS",
}

const (
// EnvCoreClrEnableProfiling - environment variable specific to .net application
EnvCoreClrEnableProfiling = "CORECLR_ENABLE_PROFILING"
)

// DotNetDetectorEnvs list of environment variables used for .net detection
var DotNetDetectorEnvs = []string{
EnvCoreClrEnableProfiling,
}

// Detect attempts to detect the type of APM instrumentation for the given service.
func Detect(pid int, args []string, envs map[string]string, lang language.Language, contextMap usm.DetectorContextMap) Instrumentation {
// first check to see if the DD_INJECTION_ENABLED is set to tracer
if isInjected(envs) {
if targetenvs.TracerInjectionEnabled(envs) {
return Injected
}

// different detection for provided instrumentation for each
if detect, ok := detectorMap[lang]; ok {
return detect(pid, args, envs, contextMap)
Expand All @@ -89,36 +81,9 @@ func Detect(pid int, args []string, envs map[string]string, lang language.Langua
return None
}

func isInjected(envs map[string]string) bool {
if val, ok := envs["DD_INJECTION_ENABLED"]; ok {
parts := strings.Split(val, ",")
for _, v := range parts {
if v == "tracer" {
return true
}
}
}
return false
}

const (
// ddTraceGoPrefix is the prefix of the dd-trace-go symbols. The symbols we
// are looking for are for example
// "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.init". We use a prefix
// without the version number instead of a specific symbol name in an
// attempt to make it future-proof.
ddTraceGoPrefix = "gopkg.in/DataDog/dd-trace-go"
// ddTraceGoMaxLength is the maximum length of the dd-trace-go symbols which
// we look for. The max length is an optimization in bininspect to avoid
// reading unnecesssary symbols. As of writing, most non-internal symbols
// in dd-trace-go are under 100 chars. The tracer.init example above at 51
// chars is one of the shortest.
ddTraceGoMaxLength = 100
)

// goDetector detects APM instrumentation for Go binaries by checking for
// the presence of the dd-trace-go symbols in the ELF. This only works for
// unstripped binaries.
// non stripped binaries.
yuri-lipnesh marked this conversation as resolved.
Show resolved Hide resolved
func goDetector(pid int, _ []string, _ map[string]string, _ usm.DetectorContextMap) Instrumentation {
exePath := kernel.HostProc(strconv.Itoa(pid), "exe")

Expand Down Expand Up @@ -240,13 +205,10 @@ func javaDetector(_ int, args []string, envs map[string]string, _ usm.DetectorCo
}
}
// also don't instrument if the javaagent is there in the environment variable JAVA_TOOL_OPTIONS and friends
for _, name := range JavaDetectorEnvs {
if val, ok := envs[name]; ok {
if strings.Contains(val, "-javaagent:") && strings.Contains(val, "dd-java-agent.jar") {
return Provided
}
}
if targetenvs.FindJava(envs) {
return Provided
}

return None
}

Expand Down Expand Up @@ -278,10 +240,8 @@ func dotNetDetectorFromMapsReader(reader io.Reader) Instrumentation {
//
// 785c8a400000-785c8aaeb000 r--s 00000000 fc:06 12762267 /home/foo/.../publish/Datadog.Trace.dll
func dotNetDetector(pid int, _ []string, envs map[string]string, _ usm.DetectorContextMap) Instrumentation {
for _, name := range DotNetDetectorEnvs {
if val, ok := envs[name]; ok && val == "1" {
return Provided
}
if targetenvs.DotNetEnabled(envs) {
return Provided
}

mapsPath := kernel.HostProc(strconv.Itoa(pid), "maps")
Expand Down
27 changes: 14 additions & 13 deletions pkg/collector/corechecks/servicediscovery/apm/detect_nix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"strings"
"testing"

"github.com/DataDog/datadog-agent/pkg/collector/corechecks/servicediscovery/targetenvs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand All @@ -31,21 +32,21 @@ func TestInjected(t *testing.T) {
{
name: "injected",
envs: map[string]string{
"DD_INJECTION_ENABLED": "tracer",
targetenvs.EnvInjectionEnabled: "tracer",
},
result: true,
},
{
name: "one of injected",
envs: map[string]string{
"DD_INJECTION_ENABLED": "service_name,tracer",
targetenvs.EnvInjectionEnabled: "service_name,tracer",
},
result: true,
},
{
name: "not injected but with env variable",
envs: map[string]string{
"DD_INJECTION_ENABLED": "service_name",
targetenvs.EnvInjectionEnabled: "service_name",
},
},
{
Expand All @@ -54,7 +55,7 @@ func TestInjected(t *testing.T) {
}
for _, d := range data {
t.Run(d.name, func(t *testing.T) {
result := isInjected(d.envs)
result := targetenvs.TracerInjectionEnabled(d.envs)
assert.Equal(t, d.result, result)
})
}
Expand Down Expand Up @@ -86,7 +87,7 @@ func Test_javaDetector(t *testing.T) {
name: "CATALINA_OPTS",
args: []string{"java"},
envs: map[string]string{
"CATALINA_OPTS": "-javaagent:dd-java-agent.jar",
targetenvs.EnvJavaDetectorCatalinaOpts: "-javaagent:dd-java-agent.jar",
},
result: Provided,
},
Expand Down Expand Up @@ -176,7 +177,7 @@ func Test_pythonDetector(t *testing.T) {
func TestDotNetDetector(t *testing.T) {
for _, test := range []struct {
name string
env map[string]string
envs map[string]string
maps string
result Instrumentation
}{
Expand All @@ -186,15 +187,15 @@ func TestDotNetDetector(t *testing.T) {
},
{
name: "profiling disabled",
env: map[string]string{
"CORECLR_ENABLE_PROFILING": "0",
envs: map[string]string{
targetenvs.EnvDotNetDetector: "0",
},
result: None,
},
{
name: "profiling enabled",
env: map[string]string{
"CORECLR_ENABLE_PROFILING": "1",
envs: map[string]string{
targetenvs.EnvDotNetDetector: "1",
},
result: Provided,
},
Expand All @@ -218,8 +219,8 @@ func TestDotNetDetector(t *testing.T) {
},
{
name: "in maps, env misleading",
env: map[string]string{
"CORECLR_ENABLE_PROFILING": "0",
envs: map[string]string{
targetenvs.EnvDotNetDetector: "0",
},
maps: `
785c8a400000-785c8aaeb000 r--s 00000000 fc:06 12762267 /home/foo/hello/bin/release/net8.0/linux-x64/publish/Datadog.Trace.dll
Expand All @@ -230,7 +231,7 @@ func TestDotNetDetector(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
var result Instrumentation
if test.maps == "" {
result = dotNetDetector(0, nil, test.env, nil)
result = dotNetDetector(0, nil, test.envs, nil)
} else {
result = dotNetDetectorFromMapsReader(strings.NewReader(test.maps))
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/collector/corechecks/servicediscovery/impl_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"testing"
"time"

"github.com/DataDog/datadog-agent/pkg/collector/corechecks/servicediscovery/targetenvs"
"github.com/golang/mock/gomock"
gocmp "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
Expand Down Expand Up @@ -165,7 +166,7 @@ func cmpEvents(a, b *event) bool {
func Test_linuxImpl(t *testing.T) {
host := "test-host"
cfgYaml := `ignore_processes: ["ignore-1", "ignore-2"]`
t.Setenv("DD_DISCOVERY_ENABLED", "true")
t.Setenv(targetenvs.EnvDiscoveryEnabled, "true")

type checkRun struct {
servicesResp *model.ServicesResponse
Expand Down
Loading
Loading