Skip to content

Commit

Permalink
Extract lookupcgroupv2 out of the otlp reporter (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmathieu authored Nov 20, 2024
1 parent 4f405f2 commit 2c6d1ac
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 50 deletions.
59 changes: 59 additions & 0 deletions libpf/cgroupv2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package libpf // import "go.opentelemetry.io/ebpf-profiler/libpf"

import (
"bufio"
"fmt"
"os"
"regexp"

lru "github.com/elastic/go-freelru"
log "github.com/sirupsen/logrus"
)

var (
cgroupv2PathPattern = regexp.MustCompile(`0:.*?:(.*)`)
)

// LookupCgroupv2 returns the cgroupv2 ID for pid.
func LookupCgroupv2(cgrouplru *lru.SyncedLRU[PID, string], pid PID) (string, error) {
id, ok := cgrouplru.Get(pid)
if ok {
return id, nil
}

// Slow path
f, err := os.Open(fmt.Sprintf("/proc/%d/cgroup", pid))
if err != nil {
return "", err
}
defer f.Close()

var genericCgroupv2 string
scanner := bufio.NewScanner(f)
buf := make([]byte, 512)
// Providing a predefined buffer overrides the internal buffer that Scanner uses (4096 bytes).
// We can do that and also set a maximum allocation size on the following call.
// With a maximum of 4096 characters path in the kernel, 8192 should be fine here. We don't
// expect lines in /proc/<PID>/cgroup to be longer than that.
scanner.Buffer(buf, 8192)
var pathParts []string
for scanner.Scan() {
line := scanner.Text()
pathParts = cgroupv2PathPattern.FindStringSubmatch(line)
if pathParts == nil {
log.Debugf("Could not extract cgroupv2 path from line: %s", line)
continue
}
genericCgroupv2 = pathParts[1]
break
}

// Cache the cgroupv2 information.
// To avoid busy lookups, also empty cgroupv2 information is cached.
cgrouplru.Add(pid, genericCgroupv2)

return genericCgroupv2, nil
}
51 changes: 1 addition & 50 deletions reporter/otlp_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@
package reporter // import "go.opentelemetry.io/ebpf-profiler/reporter"

import (
"bufio"
"context"
"crypto/rand"
"crypto/tls"
"fmt"
"maps"
"os"
"regexp"
"slices"
"strconv"
"time"
Expand All @@ -33,10 +29,6 @@ import (
"go.opentelemetry.io/ebpf-profiler/libpf/xsync"
)

var (
cgroupv2PathPattern = regexp.MustCompile(`0:.*?:(.*)`)
)

// Assert that we implement the full Reporter interface.
var _ Reporter = (*OTLPReporter)(nil)

Expand Down Expand Up @@ -218,7 +210,7 @@ func (r *OTLPReporter) ReportTraceEvent(trace *libpf.Trace, meta *TraceEventMeta
traceEventsMap := r.traceEvents.WLock()
defer r.traceEvents.WUnlock(&traceEventsMap)

containerID, err := r.lookupCgroupv2(meta.PID)
containerID, err := libpf.LookupCgroupv2(r.cgroupv2ID, meta.PID)
if err != nil {
log.Debugf("Failed to get a cgroupv2 ID as container ID for PID %d: %v",
meta.PID, err)
Expand Down Expand Up @@ -859,44 +851,3 @@ func setupGrpcConnection(parent context.Context, cfg *Config,
//nolint:staticcheck
return grpc.DialContext(ctx, cfg.CollAgentAddr, opts...)
}

// lookupCgroupv2 returns the cgroupv2 ID for pid.
func (r *OTLPReporter) lookupCgroupv2(pid libpf.PID) (string, error) {
id, ok := r.cgroupv2ID.Get(pid)
if ok {
return id, nil
}

// Slow path
f, err := os.Open(fmt.Sprintf("/proc/%d/cgroup", pid))
if err != nil {
return "", err
}
defer f.Close()

var genericCgroupv2 string
scanner := bufio.NewScanner(f)
buf := make([]byte, 512)
// Providing a predefined buffer overrides the internal buffer that Scanner uses (4096 bytes).
// We can do that and also set a maximum allocation size on the following call.
// With a maximum of 4096 characters path in the kernel, 8192 should be fine here. We don't
// expect lines in /proc/<PID>/cgroup to be longer than that.
scanner.Buffer(buf, 8192)
var pathParts []string
for scanner.Scan() {
line := scanner.Text()
pathParts = cgroupv2PathPattern.FindStringSubmatch(line)
if pathParts == nil {
log.Debugf("Could not extract cgroupv2 path from line: %s", line)
continue
}
genericCgroupv2 = pathParts[1]
break
}

// Cache the cgroupv2 information.
// To avoid busy lookups, also empty cgroupv2 information is cached.
r.cgroupv2ID.Add(pid, genericCgroupv2)

return genericCgroupv2, nil
}

0 comments on commit 2c6d1ac

Please sign in to comment.