Skip to content

Commit 9f6e48a

Browse files
committed
WIP: CPU spikes and service name for docker services
1 parent 9cf57b7 commit 9f6e48a

File tree

9 files changed

+96
-80
lines changed

9 files changed

+96
-80
lines changed

pkg/cli/commands/instruement_node_containers.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ func NewConfigNodeContainerCommand(
3434
}
3535

3636
func (c *ConfigNodeContainerCommand) Execute() error {
37-
pp.Println("EXECUTE------------------------")
3837
ctx := context.Background()
3938

4039
// Check if running as root
@@ -124,7 +123,6 @@ func (c *ConfigNodeContainerCommand) Execute() error {
124123
cfg.MWAgentService = "" // Reserved hack
125124
cfg.OtelServiceName = container.GetServiceName()
126125
cfg.NodeAgentPath = docker.DefaultContainerAgentNodePath
127-
pp.Println("cfg: ", cfg)
128126

129127
// Instrument container
130128
err := dockerOps.InstrumentContainer(container.ContainerName, &cfg)

pkg/cli/commands/list.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ func (c *ListAllCommand) Execute() error {
154154
// return fmt.Errorf("error: %v", err)
155155
// }
156156

157-
// pp.Println(nodeProcs)
158-
159157
// Get Docker containers
160158
dockerDiscoverer := discovery.NewDockerDiscoverer(ctx)
161159
javaContainers, javaDockerErr := dockerDiscoverer.DiscoverJavaContainers()

pkg/cli/commands/uninstrument.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"os"
88
"strings"
99

10-
"github.com/k0kubun/pp"
1110
"github.com/middleware-labs/java-injector/pkg/cli/types"
1211
"github.com/middleware-labs/java-injector/pkg/discovery"
1312
"github.com/middleware-labs/java-injector/pkg/docker"
@@ -220,7 +219,6 @@ func (c *UninstrumentDockerCommand) Execute() error {
220219

221220
// List instrumented containers
222221
instrumented, err := dockerOps.ListInstrumentedContainers()
223-
pp.Println("Instrumented Containers: ", instrumented)
224222
if err != nil {
225223
return fmt.Errorf("❌ Error listing instrumented containers: %v", err)
226224
}

pkg/discovery/container.go

Lines changed: 70 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -64,66 +64,84 @@ func (cd *ContainerDetector) IsProcessInContainer(pid int32) (*ContainerInfo, er
6464
// checkCgroup examines the process cgroup to detect container runtimes
6565
func (cd *ContainerDetector) checkCgroup(pid int32) (*ContainerInfo, error) {
6666
cgroupPath := fmt.Sprintf("/proc/%d/cgroup", pid)
67-
file, err := os.Open(cgroupPath)
67+
data, err := os.ReadFile(cgroupPath)
6868
if err != nil {
69-
return nil, err
69+
return &ContainerInfo{IsContainer: false}, err
7070
}
71-
defer file.Close()
7271

73-
scanner := bufio.NewScanner(file)
74-
for scanner.Scan() {
75-
line := scanner.Text()
72+
content := string(data)
73+
if content == "" {
74+
return &ContainerInfo{IsContainer: false}, nil
75+
}
7676

77-
// Docker patterns
78-
if strings.Contains(line, "/docker/") {
79-
containerID := cd.extractDockerIDFromCgroup(line)
80-
return &ContainerInfo{
81-
IsContainer: true,
82-
ContainerID: containerID,
83-
Runtime: "docker",
84-
}, nil
85-
}
77+
// 1. DOCKER & CONTAINERD
78+
// v1: /docker/<ID> or /containerd/<ID>
79+
// v2: /system.slice/docker-<ID>.scope or /system.slice/containerd-<ID>.scope
80+
dockerRegex := regexp.MustCompile(`(?:docker-|containerd-|/docker/|/containerd/)([a-fA-F0-9]{64})`)
81+
if matches := dockerRegex.FindStringSubmatch(content); len(matches) > 1 {
82+
return &ContainerInfo{
83+
IsContainer: true,
84+
ContainerID: matches[1],
85+
Runtime: "docker/containerd",
86+
}, nil
87+
}
8688

87-
// Podman patterns
88-
if strings.Contains(line, "/libpod-") || strings.Contains(line, "machine.slice/libpod-") {
89-
containerID := cd.extractPodmanIDFromCgroup(line)
90-
return &ContainerInfo{
91-
IsContainer: true,
92-
ContainerID: containerID,
93-
Runtime: "podman",
94-
}, nil
95-
}
89+
// 2. KUBERNETES (CRI-O / Containerd)
90+
// Matches: cri-containerd-<ID>.scope, crio-<ID>.scope, or kubepods paths
91+
k8sRegex := regexp.MustCompile(`(?:cri-containerd-|crio-|/kubepods.*/pod.*/)([a-fA-F0-9]{64})`)
92+
if matches := k8sRegex.FindStringSubmatch(content); len(matches) > 1 {
93+
return &ContainerInfo{
94+
IsContainer: true,
95+
ContainerID: matches[1],
96+
Runtime: "kubernetes",
97+
}, nil
98+
}
9699

97-
// Containerd patterns
98-
if strings.Contains(line, "/containerd/") {
99-
containerID := cd.extractContainerdIDFromCgroup(line)
100-
return &ContainerInfo{
101-
IsContainer: true,
102-
ContainerID: containerID,
103-
Runtime: "containerd",
104-
}, nil
105-
}
100+
// 3. PODMAN
101+
// Matches: libpod-<ID>.scope or /libpod-<ID>
102+
podmanRegex := regexp.MustCompile(`(?:libpod-|/libpod-)([a-fA-F0-9]{64})`)
103+
if matches := podmanRegex.FindStringSubmatch(content); len(matches) > 1 {
104+
return &ContainerInfo{
105+
IsContainer: true,
106+
ContainerID: matches[1],
107+
Runtime: "podman",
108+
}, nil
109+
}
106110

107-
// systemd-nspawn patterns
108-
if strings.Contains(line, "machine-") && strings.Contains(line, ".scope") {
109-
return &ContainerInfo{
110-
IsContainer: true,
111-
Runtime: "systemd-nspawn",
112-
}, nil
113-
}
111+
// 4. LXC
112+
lxcRegex := regexp.MustCompile(`/lxc/([^/\n]+)`)
113+
if matches := lxcRegex.FindStringSubmatch(content); len(matches) > 1 {
114+
return &ContainerInfo{
115+
IsContainer: true,
116+
ContainerID: matches[1],
117+
Runtime: "lxc",
118+
}, nil
119+
}
114120

115-
// LXC patterns
116-
if strings.Contains(line, "/lxc/") {
117-
containerID := cd.extractLXCIDFromCgroup(line)
118-
return &ContainerInfo{
119-
IsContainer: true,
120-
ContainerID: containerID,
121-
Runtime: "lxc",
122-
}, nil
123-
}
121+
// 5. GENERIC FALLBACK (Systemd Scopes)
122+
// If it's in a .scope but not the init.scope or user.slice, it's likely a container
123+
if strings.Contains(content, ".scope") && !strings.Contains(content, "init.scope") {
124+
return &ContainerInfo{
125+
IsContainer: true,
126+
Runtime: "generic-container",
127+
}, nil
124128
}
125129

126-
return &ContainerInfo{IsContainer: false}, scanner.Err()
130+
return &ContainerInfo{IsContainer: false}, nil
131+
}
132+
133+
func (cd *ContainerDetector) checkNamespaceFallback(pid int32, info *ContainerInfo) {
134+
if info.IsContainer {
135+
return // Already detected
136+
}
137+
138+
hostNs, _ := os.Readlink("/proc/1/ns/mnt")
139+
procNs, _ := os.Readlink(fmt.Sprintf("/proc/%d/ns/mnt", pid))
140+
141+
if hostNs != "" && procNs != "" && hostNs != procNs {
142+
info.IsContainer = true
143+
info.Runtime = "namespace-isolated" // Container detected via isolation
144+
}
127145
}
128146

129147
// checkMountNamespace checks if the process is in a different mount namespace
@@ -351,6 +369,8 @@ func (cd *ContainerDetector) GetContainerNameByID(containerID, runtime string) s
351369
switch runtime {
352370
case "docker":
353371
return cd.getDockerContainerName(containerID)
372+
case "docker/containerd":
373+
return cd.getDockerContainerName(containerID)
354374
case "podman":
355375
return cd.getPodmanContainerName(containerID)
356376
default:

pkg/discovery/docker.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ type DockerContainer struct {
6666
InstrumentedAt time.Time `json:"instrumented_at,omitempty"`
6767
}
6868

69+
type ContainerCandidate struct {
70+
ID string
71+
Image string
72+
Names string
73+
}
74+
6975
// DockerMount represents a Docker volume mount
7076
type DockerMount struct {
7177
Type string `json:"type"`

pkg/discovery/process.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ func (d *discoverer) DiscoverWithOptions(ctx context.Context, opts DiscoveryOpti
5858
// Filter for Java processes first to reduce workload
5959
// javaDiscoverCandidates := d.filterJavaProcesses(allProcesses)
6060

61-
// pp.Println(javaDiscoverCandidates)
6261
// Process concurrently with worker pool
6362
return d.processWithWorkerPool(ctx, allProcesses, opts)
6463
}
@@ -116,8 +115,6 @@ func (d *discoverer) filterJavaProcesses(processes []*process.Process) []*Discov
116115

117116
for _, proc := range processes {
118117
if discoveryCandidate := d.getJavaDiscoveryCandidateForProcesss(proc); discoveryCandidate.IsJavaProcess {
119-
// pp.Println("Lol here with, ", proc)
120-
// pp.Println("And the candidate, ", discoveryCandidate)
121118
javaProcesses = append(javaProcesses, &discoveryCandidate)
122119
}
123120
}
@@ -306,7 +303,6 @@ func (d *discoverer) processNodeWithWorkerPool(ctx context.Context, processes []
306303
if len(processes) == 0 {
307304
return []NodeProcess{}, nil
308305
}
309-
// pp.Println(opts)
310306

311307
// Create channels for work distribution
312308
jobs := make(chan *process.Process, len(processes))
@@ -369,7 +365,6 @@ func (d *discoverer) processNodeWithWorkerPool(ctx context.Context, processes []
369365
if len(errors) > 0 && !opts.SkipPermissionErrors {
370366
return nodeProcesses, fmt.Errorf("encountered %d errors during Node.js discovery: %v", len(errors), errors[0])
371367
}
372-
// pp.Println("Post PROCESESSING: ", nodeProcesses)
373368
return nodeProcesses, nil
374369
}
375370

@@ -882,11 +877,8 @@ func (d *discoverer) worker(
882877
if !candidate.IsJavaProcess {
883878
continue
884879
}
885-
pp.Println("WorKing for Java Process")
886-
pp.Println("proc: ", proc)
887-
pp.Println("discovery candidate: ", candidate)
880+
888881
javaProc, err := d.processOne(ctx, &candidate, opts)
889-
pp.Println("Java Proc: ", javaProc)
890882
results <- processResult{javaProc, err}
891883
}
892884
}
@@ -933,6 +925,7 @@ func (d *discoverer) processOne(ctx context.Context, proc *DiscoveryCandidate, o
933925
} else {
934926
javaProc.ContainerInfo = containerInfo
935927

928+
pp.Println("Found container info", javaProc.ContainerInfo)
936929
// If we're excluding containers and this is in a container, return nil
937930
if opts.ExcludeContainers && containerInfo.IsContainer {
938931
return nil, fmt.Errorf("process %d is running in container, skipping", javaProc.ProcessPID)
@@ -952,9 +945,6 @@ func (d *discoverer) processOne(ctx context.Context, proc *DiscoveryCandidate, o
952945
}
953946

954947
// Extract Java-specific information
955-
pp.Println("trying to extract the java info")
956-
pp.Println("Javaproc: ", javaProc)
957-
pp.Println("cmdArgs: ", cmdArgs)
958948
d.extractJavaInfo(javaProc, cmdArgs)
959949

960950
// Extract service name

pkg/discovery/report.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ func GetAgentReportValue() (AgentReportValue, error) {
7272
// Decide if this should be a fatal error or just logged (assuming logged for now)
7373
}
7474

75-
nodeProcs, err := FindAllNodeProcesses(ctx)
75+
// nodeProcs, err := FindAllNodeProcesses(ctx)
7676

77-
// b) Docker Containers (Java/Node)
77+
// b) Docker Containers (java/Node)
7878
// dockerDiscoverer := NewDockerDiscoverer(ctx)
79-
// javaContainers, _ := dockerDiscoverer.DiscoverJavaContainers() // Error handling omitted for brevity
79+
// javaContainers, _ := dockContainerDetectorerDiscoverer.DiscoverJavaContainers() // Error handling omitted for brevity
8080
// nodeContainers, _ := dockerDiscoverer.DiscoverNodeContainers() // Error handling omitted for brevity
8181

8282
// --- 2. Convert to AgentReportValue (ServiceSetting) ---
@@ -86,7 +86,10 @@ func GetAgentReportValue() (AgentReportValue, error) {
8686
// Convert host processes
8787
for _, proc := range processes {
8888
// Only report processes we care about (non-Tomcat, non-Container for simplicity)
89-
if !proc.IsTomcat() && !proc.ContainerInfo.IsContainer {
89+
// if !proc.IsTomcat() && !proc.ContainerInfo.IsContainer {
90+
if !proc.IsTomcat() {
91+
if proc.IsInContainer() {
92+
}
9093
setting := convertJavaProcessToServiceSetting(proc)
9194
settings[setting.Key] = setting
9295
}
@@ -105,13 +108,10 @@ func GetAgentReportValue() (AgentReportValue, error) {
105108
// settings[setting.Key] = setting
106109
// }
107110

108-
for _, proc := range nodeProcs {
109-
// pp.Println("---------------------------------------------------------")
110-
// pp.Println(proc)
111-
setting := convertNodeProcessToServiceSetting(proc)
112-
// pp.Println("Found node setting: ", setting)
113-
settings[setting.Key] = setting
114-
}
111+
// for _, proc := range nodeProcs {
112+
// setting := convertNodeProcessToServiceSetting(proc)
113+
// settings[setting.Key] = setting
114+
// }
115115

116116
reportValue := AgentReportValue{
117117
osKey: OSConfig{
@@ -235,6 +235,9 @@ func detectDeploymentType(proc *JavaProcess) string {
235235
if proc.ProcessOwner != "root" && proc.ProcessOwner != os.Getenv("USER") {
236236
return "systemd"
237237
}
238+
if proc.IsInContainer() {
239+
return "docker"
240+
}
238241
return "standalone"
239242
}
240243

pkg/discovery/service.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import (
99
// extractServiceName extracts a meaningful service name from command arguments
1010
func (d *discoverer) extractServiceName(javaProc *JavaProcess, cmdArgs []string) {
1111
serviceName := ""
12+
if javaProc.IsInContainer() {
13+
javaProc.ServiceName = javaProc.ContainerInfo.ContainerName
14+
return
15+
}
1216

1317
// Strategy 1: System Properties (highest priority)
1418
serviceName = d.extractFromSystemProperties(cmdArgs)

pkg/docker/operations.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ type ContainerState struct {
168168
// InstrumentContainer instruments a specific Docker container
169169
func (do *DockerOperations) InstrumentContainer(containerName string, cfg *config.ProcessConfiguration) error {
170170
// Discover the container
171-
pp.Println("here lols")
172171
pp.Println("Container name: ", containerName)
173172
container, err := do.discoverer.GetContainerByName(containerName)
174173
if err != nil {

0 commit comments

Comments
 (0)