Skip to content

Commit b3e3816

Browse files
authored
[PROF-13649] host-profiler: remove dependency on dd-otel-host-profiler (#45884)
### What does this PR do? This PR removes the external dependency on dd-otel-host-profiler by importing the symboluploader code directly into the datadog-agent repository under `comp/host-profiler/symboluploader`. ### Motivation dd-otel-host-profiler is going to be deprecated and all development for host-profiler is now going to happen in datadog-agent and opentelemetry-ebpf-profiler. ### Describe how you validated your changes Ran the profiler and verified that symbol files are uploaded successfully. Co-authored-by: nicolas.savoire <nicolas.savoire@datadoghq.com>
1 parent 59326a9 commit b3e3816

File tree

30 files changed

+4467
-63
lines changed

30 files changed

+4467
-63
lines changed

LICENSE-3rdparty.csv

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,6 @@ core,github.com/DataDog/datadog-traceroute/tcp,Apache-2.0,"Copyright 2016-presen
162162
core,github.com/DataDog/datadog-traceroute/traceroute,Apache-2.0,"Copyright 2016-present Datadog, Inc"
163163
core,github.com/DataDog/datadog-traceroute/udp,Apache-2.0,"Copyright 2016-present Datadog, Inc"
164164
core,github.com/DataDog/datadog-traceroute/winconn,Apache-2.0,"Copyright 2016-present Datadog, Inc"
165-
core,github.com/DataDog/dd-otel-host-profiler/config,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
166-
core,github.com/DataDog/dd-otel-host-profiler/containermetadata,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
167-
core,github.com/DataDog/dd-otel-host-profiler/pclntab,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
168-
core,github.com/DataDog/dd-otel-host-profiler/reporter,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
169-
core,github.com/DataDog/dd-otel-host-profiler/reporter/cgroup,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
170-
core,github.com/DataDog/dd-otel-host-profiler/reporter/oom,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
171-
core,github.com/DataDog/dd-otel-host-profiler/reporter/pipeline,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
172-
core,github.com/DataDog/dd-otel-host-profiler/reporter/pprof,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
173-
core,github.com/DataDog/dd-otel-host-profiler/reporter/samples,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
174-
core,github.com/DataDog/dd-otel-host-profiler/reporter/symbol,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
175-
core,github.com/DataDog/dd-otel-host-profiler/version,Apache-2.0,"Copyright 2017 Datadog, Inc | Copyright 2024 Datadog, Inc"
176165
core,github.com/DataDog/ddtrivy,Apache-2.0,"Copyright 2025-Present Datadog, Inc"
177166
core,github.com/DataDog/ddtrivy/walker,Apache-2.0,"Copyright 2025-Present Datadog, Inc"
178167
core,github.com/DataDog/ebpf-manager,MIT,Copyright (c) 2021 Authors of Datadog
@@ -2302,7 +2291,6 @@ core,github.com/uptrace/bun/internal/tagparser,BSD-2-Clause,Copyright (c) 2021 V
23022291
core,github.com/uptrace/bun/migrate,BSD-2-Clause,Copyright (c) 2021 Vladimir Mihailenco. All rights reserved
23032292
core,github.com/uptrace/bun/migrate/sqlschema,BSD-2-Clause,Copyright (c) 2021 Vladimir Mihailenco. All rights reserved
23042293
core,github.com/uptrace/bun/schema,BSD-2-Clause,Copyright (c) 2021 Vladimir Mihailenco. All rights reserved
2305-
core,github.com/urfave/cli/v3,MIT,Copyright (c) 2023 urfave/cli maintainers
23062294
core,github.com/urfave/negroni,MIT,Copyright (c) 2014 Jeremy Saenz
23072295
core,github.com/valyala/fastjson,MIT,Copyright (c) 2018 Aliaksandr Valialkin
23082296
core,github.com/valyala/fastjson/fastfloat,MIT,Copyright (c) 2018 Aliaksandr Valialkin

comp/host-profiler/collector/impl/receiver/config.go

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,27 @@ import (
1212
"strings"
1313
"time"
1414

15-
"github.com/DataDog/datadog-agent/pkg/version"
16-
"github.com/DataDog/dd-otel-host-profiler/config"
17-
"github.com/DataDog/dd-otel-host-profiler/reporter"
1815
"go.opentelemetry.io/collector/component"
1916
"go.opentelemetry.io/collector/confmap/xconfmap"
2017
ebpfcollector "go.opentelemetry.io/ebpf-profiler/collector"
2118
ebpfconfig "go.opentelemetry.io/ebpf-profiler/collector/config"
2219
"go.opentelemetry.io/ebpf-profiler/tracer/types"
23-
)
2420

25-
// ReporterConfig is the configuration for the reporter.
26-
type ReporterConfig struct {
27-
CollectContext bool `mapstructure:"collect_context"`
28-
}
21+
"github.com/DataDog/datadog-agent/comp/host-profiler/symboluploader"
22+
)
2923

3024
// Config is the configuration for the profiles receiver.
3125
type Config struct {
32-
EbpfCollectorConfig *ebpfconfig.Config `mapstructure:"ebpf_collector"`
33-
SymbolUploader reporter.SymbolUploaderConfig `mapstructure:"symbol_uploader"`
34-
ReporterConfig ReporterConfig `mapstructure:"reporter"`
35-
EnableSplitByService bool `mapstructure:"enable_split_by_service"`
26+
EbpfCollectorConfig *ebpfconfig.Config `mapstructure:"ebpf_collector"`
27+
SymbolUploader symboluploader.SymbolUploaderConfig `mapstructure:"symbol_uploader"`
28+
CollectContext bool `mapstructure:"collect_context"`
29+
EnableSplitByService bool `mapstructure:"enable_split_by_service"`
3630
}
3731

32+
// ServiceNameEnvVars is the list of environment variables used to determine the service name.
33+
// The order indicates which environment variable takes precedence.
34+
var serviceNameEnvVars = []string{"DD_SERVICE", "OTEL_SERVICE_NAME"}
35+
3836
var _ xconfmap.Validator = (*Config)(nil)
3937

4038
func errSymbolEndpointsRequired() error {
@@ -53,7 +51,7 @@ func (c *Config) Validate() error {
5351
if err := c.EbpfCollectorConfig.Validate(); err != nil {
5452
return err
5553
}
56-
if c.ReporterConfig.CollectContext {
54+
if c.CollectContext {
5755
includeTracers, err := types.Parse(c.EbpfCollectorConfig.Tracers)
5856
if err != nil {
5957
return err
@@ -62,7 +60,7 @@ func (c *Config) Validate() error {
6260
c.EbpfCollectorConfig.Tracers = includeTracers.String()
6361
}
6462
if c.EnableSplitByService {
65-
includeEnvVars := reporter.ServiceNameEnvVars
63+
includeEnvVars := append([]string{}, serviceNameEnvVars...)
6664
if c.EbpfCollectorConfig.IncludeEnvVars != "" {
6765
includeEnvVars = append(includeEnvVars, c.EbpfCollectorConfig.IncludeEnvVars)
6866
}
@@ -95,26 +93,12 @@ func defaultConfig() component.Config {
9593
// With 60s intervals, 20% would mean ~12s variation, so we reduce to 5% (~3s).
9694
cfg.ReporterJitter = 0.05
9795

96+
symbolUploaderConfig := symboluploader.DefaultSymbolUploaderConfig()
9897
return Config{
99-
EbpfCollectorConfig: cfg,
100-
SymbolUploader: reporter.SymbolUploaderConfig{
101-
SymbolUploaderOptions: reporter.SymbolUploaderOptions{
102-
Enabled: config.DefaultUploadSymbols,
103-
UploadDynamicSymbols: config.DefaultUploadDynamicSymbols,
104-
UploadGoPCLnTab: config.DefaultUploadGoPCLnTab,
105-
UseHTTP2: config.DefaultUploadSymbolsHTTP2,
106-
SymbolQueryInterval: config.DefaultSymbolQueryInterval,
107-
DryRun: config.DefaultUploadSymbolsDryRun,
108-
SymbolEndpoints: nil,
109-
},
110-
Version: version.AgentVersion,
111-
DisableDebugSectionCompression: false,
112-
},
113-
114-
EnableSplitByService: config.DefaultSplitByService,
115-
ReporterConfig: ReporterConfig{
116-
CollectContext: config.DefaultCollectContext,
117-
},
98+
EbpfCollectorConfig: cfg,
99+
SymbolUploader: symbolUploaderConfig,
100+
EnableSplitByService: true,
101+
CollectContext: false,
118102
}
119103
}
120104

comp/host-profiler/collector/impl/receiver/config_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"testing"
1313
"time"
1414

15-
"github.com/DataDog/dd-otel-host-profiler/reporter"
15+
"github.com/DataDog/datadog-agent/comp/host-profiler/symboluploader"
1616
"github.com/stretchr/testify/require"
1717
)
1818

@@ -30,12 +30,12 @@ func TestTracers(t *testing.T) {
3030
require.NotContains(t, cfg.EbpfCollectorConfig.Tracers, "go")
3131
require.NotContains(t, cfg.EbpfCollectorConfig.Tracers, "labels")
3232

33-
cfg.ReporterConfig.CollectContext = false
33+
cfg.CollectContext = false
3434
cfg.SymbolUploader.Enabled = false
3535
require.NoError(t, cfg.Validate())
3636
require.NotContains(t, cfg.EbpfCollectorConfig.Tracers, "labels")
3737

38-
cfg.ReporterConfig.CollectContext = true
38+
cfg.CollectContext = true
3939
require.NoError(t, cfg.Validate())
4040
require.Contains(t, cfg.EbpfCollectorConfig.Tracers, "labels")
4141
}
@@ -50,7 +50,7 @@ func TestServiceNameEnvVars(t *testing.T) {
5050

5151
cfg.EnableSplitByService = true
5252
require.NoError(t, cfg.Validate())
53-
require.Equal(t, strings.Join(reporter.ServiceNameEnvVars, ","), cfg.EbpfCollectorConfig.IncludeEnvVars)
53+
require.Equal(t, strings.Join(serviceNameEnvVars, ","), cfg.EbpfCollectorConfig.IncludeEnvVars)
5454
}
5555

5656
func TestSymbolUploader(t *testing.T) {
@@ -62,7 +62,7 @@ func TestSymbolUploader(t *testing.T) {
6262
cfg.SymbolUploader.Enabled = true
6363
require.Error(t, errSymbolEndpointsRequired(), cfg.Validate())
6464

65-
cfg.SymbolUploader.SymbolEndpoints = []reporter.SymbolEndpoint{{}}
65+
cfg.SymbolUploader.SymbolEndpoints = []symboluploader.SymbolEndpoint{{}}
6666
require.Error(t, errSymbolEndpointsSiteRequired(), cfg.Validate())
6767
cfg.SymbolUploader.SymbolEndpoints[0].Site = "datadoghq.com"
6868
require.Error(t, errSymbolEndpointsAPIKeyRequired(), cfg.Validate())

comp/host-profiler/collector/impl/receiver/executable_reporter.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ import (
1313

1414
"go.uber.org/zap"
1515

16-
"github.com/DataDog/dd-otel-host-profiler/reporter"
17-
1816
ebpfreporter "go.opentelemetry.io/ebpf-profiler/reporter"
17+
18+
"github.com/DataDog/datadog-agent/comp/host-profiler/symboluploader"
1919
)
2020

2121
var _ ebpfreporter.ExecutableReporter = (*executableReporter)(nil)
2222

2323
type executableReporter struct {
24-
symbolUploader *reporter.DatadogSymbolUploader
24+
symbolUploader *symboluploader.DatadogSymbolUploader
2525
}
2626

27-
func newExecutableReporter(config *reporter.SymbolUploaderConfig, _ *zap.Logger) (*executableReporter, error) {
27+
func newExecutableReporter(config *symboluploader.SymbolUploaderConfig, _ *zap.Logger) (*executableReporter, error) {
2828
ctx := context.Background()
29-
symbolUploader, err := reporter.NewDatadogSymbolUploader(ctx, config)
29+
symbolUploader, err := symboluploader.NewDatadogSymbolUploader(ctx, config)
3030
if err != nil {
3131
return nil, err
3232
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Unless explicitly stated otherwise all files in this repository are licensed
2+
// under the Apache License Version 2.0.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
// Copyright 2025-present Datadog, Inc.
5+
6+
//go:build linux
7+
8+
// Package cgroup provides utilities for returning usable memory from cgroups.
9+
package cgroup
10+
11+
import (
12+
"path/filepath"
13+
"strconv"
14+
)
15+
16+
const (
17+
cgroupRoot = "/sys/fs/cgroup"
18+
v1MaxMemory = "memory.limit_in_bytes"
19+
v2MaxMemory = "memory.max"
20+
memoryMaxUnset = 0x7FFFFFFFFFFFF000
21+
budgetRatio = 8
22+
)
23+
24+
func v1GetMaxUsableMemory() (int64, error) {
25+
cgroupPath, err := v1GetCurrentCgroupPath()
26+
if err != nil {
27+
return -1, err
28+
}
29+
30+
str, err := readFromFile(filepath.Join(cgroupPath, v1MaxMemory))
31+
if err != nil {
32+
return -1, err
33+
}
34+
35+
limit, err := strconv.ParseInt(str, 10, 64)
36+
37+
if err != nil {
38+
return -1, err
39+
}
40+
41+
if limit < 0 || limit == memoryMaxUnset {
42+
return -1, nil
43+
}
44+
45+
return limit, nil
46+
}
47+
48+
func v2GetMaxUsableMemory() (int64, error) {
49+
currCgroupPath, err := v2GetCurrentCgroupPath()
50+
if err != nil {
51+
return -1, err
52+
}
53+
54+
str, err := readFromFile(filepath.Join(currCgroupPath, v2MaxMemory))
55+
56+
if err != nil {
57+
return -1, err
58+
}
59+
60+
// not error -> no memory constraints
61+
if str == "max" {
62+
return -1, nil
63+
}
64+
65+
limit, err := strconv.ParseInt(str, 10, 64)
66+
67+
if err != nil {
68+
return -1, err
69+
}
70+
71+
return limit, nil
72+
}
73+
74+
func GetMaxUsableMemory() (int64, error) {
75+
if !isCgroup2UnifiedMode() {
76+
return v1GetMaxUsableMemory()
77+
}
78+
return v2GetMaxUsableMemory()
79+
}
80+
81+
// GetMemoryBudget returns a percentage of the overall memory limit found in
82+
// cgroup. If there are no limits, it returns -1.
83+
func GetMemoryBudget() (int64, error) {
84+
maxMemory, err := GetMaxUsableMemory()
85+
if err != nil {
86+
return -1, err
87+
}
88+
if maxMemory == -1 {
89+
return maxMemory, nil
90+
}
91+
92+
return maxMemory * budgetRatio / 10, nil
93+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Unless explicitly stated otherwise all files in this repository are licensed
2+
// under the Apache License Version 2.0.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
// Copyright 2025-present Datadog, Inc.
5+
6+
//go:build linux
7+
8+
package cgroup
9+
10+
import (
11+
"errors"
12+
"os"
13+
"path/filepath"
14+
"strings"
15+
16+
"golang.org/x/sys/unix"
17+
)
18+
19+
func isCgroup2UnifiedMode() bool {
20+
var st unix.Statfs_t
21+
err := unix.Statfs(cgroupRoot, &st)
22+
if err != nil {
23+
return false
24+
}
25+
return st.Type == unix.CGROUP2_SUPER_MAGIC
26+
}
27+
28+
func readFromFile(path string) (string, error) {
29+
data, err := os.ReadFile(path)
30+
if err != nil {
31+
return "", err
32+
}
33+
return strings.TrimSpace(string(data)), nil
34+
}
35+
36+
func v1GetCurrentCgroupPath() (string, error) {
37+
data, err := os.ReadFile("/proc/self/cgroup")
38+
if err != nil {
39+
return "", err
40+
}
41+
42+
for line := range strings.SplitSeq(string(data), "\n") {
43+
// hierarchy:controller(s):path
44+
parts := strings.SplitN(line, ":", 3)
45+
if len(parts) < 3 {
46+
continue
47+
}
48+
49+
for controller := range strings.SplitSeq(parts[1], ",") {
50+
if controller == "memory" {
51+
return filepath.Join(cgroupRoot, "memory", parts[2]), nil
52+
}
53+
}
54+
}
55+
56+
return "", errors.New("cgroup path not found in /proc/self/cgroup")
57+
}
58+
59+
func v2GetCurrentCgroupPath() (string, error) {
60+
data, err := os.ReadFile("/proc/self/cgroup")
61+
if err != nil {
62+
return "", err
63+
}
64+
65+
for line := range strings.SplitSeq(string(data), "\n") {
66+
if path, ok := strings.CutPrefix(line, "0::"); ok {
67+
return filepath.Join(cgroupRoot, path), nil
68+
}
69+
}
70+
71+
return "", errors.New("cgroup path not found in /proc/self/cgroup")
72+
}

0 commit comments

Comments
 (0)