Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/unit-test-on-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
# https://github.com/cilium/ci-kernels/pkgs/container/ci-kernels/versions?filters%5Bversion_type%5D=tagged

# AMD64
- { target_arch: amd64, kernel: 4.19.314 }
- { target_arch: amd64, kernel: 5.4.276 }
- { target_arch: amd64, kernel: 5.10.217 }
- { target_arch: amd64, kernel: 5.15.159 }
Expand Down
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ LDFLAGS := -X go.opentelemetry.io/ebpf-profiler/vc.version=$(VERSION) \
-extldflags=-static

GO_TAGS := osusergo,netgo
EBPF_FLAGS :=
EBPF_FLAGS :=

GO_FLAGS := -buildvcs=false -ldflags="$(LDFLAGS)"

Expand Down Expand Up @@ -105,9 +105,11 @@ test-deps:
($(MAKE) -C "$(testdata_dir)") || exit ; \
)

TEST_INTEGRATION_BINARY_DIRS := tracer processmanager/ebpf support
TEST_INTEGRATION_BINARY_DIRS := tracer processmanager/ebpf support go_labels

integration-test-binaries: generate ebpf
# Call it a ".test" even though it isn't to get included into bluebox initramfs
go build -o ./support/go_labels_canary.test ./go_labels
$(foreach test_name, $(TEST_INTEGRATION_BINARY_DIRS), \
(go test -ldflags='-extldflags=-static' -trimpath -c \
-tags $(GO_TAGS),static_build,integration \
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module go.opentelemetry.io/ebpf-profiler
go 1.22.2

require (
github.com/aws/aws-sdk-go-v2 v1.30.5
github.com/aws/aws-sdk-go-v2/config v1.27.35
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.21
github.com/aws/aws-sdk-go-v2/service/s3 v1.62.0
github.com/cespare/xxhash/v2 v2.3.0
github.com/cilium/ebpf v0.16.0
Expand Down Expand Up @@ -34,7 +34,6 @@ require (
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/aws/aws-sdk-go-v2 v1.30.5 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.33 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.33 h1:lBHAQQznENv0gLHAZ73ONiTSkCt
github.com/aws/aws-sdk-go-v2/credentials v1.17.33/go.mod h1:MBuqCUOT3ChfLuxNDGyra67eskx7ge9e3YKYBce7wpI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.21 h1:sV0doPPsRT7gMP0BnDPwSsysVTV/nKpB/nFmMnz8goE=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.21/go.mod h1:ictvfJWqE2gkUFDRJVp5VU/TrytuzK88DYcpan7UYuA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc=
Expand Down Expand Up @@ -71,8 +69,6 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/elastic/go-freelru v0.13.0 h1:TKKY6yCfNNNky7Pj9xZAOEpBcdNgZJfihEftOb55omg=
github.com/elastic/go-freelru v0.13.0/go.mod h1:bSdWT4M0lW79K8QbX6XY2heQYSCqD7THoYf82pT/H3I=
github.com/elastic/go-freelru v0.15.0 h1:Jo1aY8JAvpyxbTDJEudrsBfjFDaALpfVv8mxuh9sfvI=
github.com/elastic/go-freelru v0.15.0/go.mod h1:bSdWT4M0lW79K8QbX6XY2heQYSCqD7THoYf82pT/H3I=
github.com/elastic/go-perf v0.0.0-20241016160959-1342461adb4a h1:ymmtaN4bVCmKKeu4XEf6JEWNZKRXPMng1zjpKd+8rCU=
Expand Down
37 changes: 37 additions & 0 deletions go_labels/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package main

import (
"context"
"fmt"
"math/rand"
"runtime/pprof"
"time"
)

//nolint:gosec
func randomString(n int) string {
letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
s := make([]rune, n)
for i := range s {
s[i] = letters[rand.Intn(len(letters))]
}
return string(s)
}

// This is a normal main program that when go build will be statically linked, this is required
// to work with qemu/bluebox testing harness. A statically linked go test built binary doesn't
// work with the go labels extractor ebpf program, not sure yet if this is a bug.
func main() {
labels := pprof.Labels("l1", randomString(16), "l2", randomString(16))
lastUpdate := time.Now()
pprof.Do(context.TODO(), labels, func(context.Context) {
//nolint:revive
for time.Since(lastUpdate) < 10*time.Second {
// CPU go burr on purpose.
}
})
fmt.Println("PASS")
}
48 changes: 48 additions & 0 deletions go_labels/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package main

import (
"context"
"os"
"os/exec"
"testing"

"github.com/stretchr/testify/require"
"go.opentelemetry.io/ebpf-profiler/testutils"
tracertypes "go.opentelemetry.io/ebpf-profiler/tracer/types"
)

func TestGoCustomLabels(t *testing.T) {
if !testutils.IsRoot() {
t.Skip("root privileges required")
}

ctx, cancel := context.WithCancel(context.Background())

r := &testutils.MockReporter{}
enabledTracers, _ := tracertypes.Parse("")
enabledTracers.Enable(tracertypes.GoLabels)
traceCh, _ := testutils.StartTracer(ctx, t, enabledTracers, r)

// Use a separate exe for getting labels as the bpf code doesn't seem to work with
// go test static binaries at the moment, not clear if that's a problem with the bpf
// code or a bug/fact of life for static go binaries and getting g from TLS.
cmd := exec.Command("./go_labels_canary.test")
err := cmd.Start()
require.NoError(t, err)

// Wait 1 second for traces to arrive.
for trace := range traceCh {
t.Logf("got a trace %s", trace.Comm)
if len(trace.CustomLabels) > 0 {
for k, v := range trace.CustomLabels {
t.Logf("Custom label: %s=%s", k, v)
}
break
}
}
cancel()
_ = cmd.Process.Signal(os.Kill)
_ = cmd.Wait()
}
58 changes: 5 additions & 53 deletions interpreter/luajit/luajit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@ import (
"io"
"net"
"net/http"
"os"
"runtime"
"strconv"
"sync"
"testing"
"time"

log "github.com/sirupsen/logrus"

"github.com/docker/go-connections/nat"
"github.com/stretchr/testify/require"
testcontainers "github.com/testcontainers/testcontainers-go"
Expand All @@ -33,13 +30,14 @@ import (
"go.opentelemetry.io/ebpf-profiler/interpreter/luajit"
"go.opentelemetry.io/ebpf-profiler/libpf"
"go.opentelemetry.io/ebpf-profiler/reporter"
"go.opentelemetry.io/ebpf-profiler/testutils"
"go.opentelemetry.io/ebpf-profiler/tracer"
tracertypes "go.opentelemetry.io/ebpf-profiler/tracer/types"
)

// Run
func TestIntegration(t *testing.T) {
if !isRoot() {
if !testutils.IsRoot() {
t.Skip("root privileges required")
}
// TODO:
Expand Down Expand Up @@ -118,8 +116,10 @@ func TestIntegration(t *testing.T) {
port, err := cont.MappedPort(ctx, "8080")
require.NoError(t, err)

enabledTracers, _ := tracertypes.Parse("luajit")
enabledTracers.Enable(tracertypes.LuaJITTracer)
r := &mockReporter{symbols: make(symbolMap)}
traceCh, trc := startTracer(ctx, t, r)
traceCh, trc := testutils.StartTracer(ctx, t, enabledTracers, r)

var waitGroup sync.WaitGroup
defer waitGroup.Wait()
Expand Down Expand Up @@ -203,44 +203,6 @@ outer:
return true
}

// FIXME: refactor this to copy less code.
func startTracer(ctx context.Context, t *testing.T, r *mockReporter) (chan *host.Trace,
*tracer.Tracer) {
enabledTracers, _ := tracertypes.Parse("luajit")
enabledTracers.Enable(tracertypes.LuaJITTracer)
trc, err := tracer.NewTracer(ctx, &tracer.Config{
DebugTracer: true,
Reporter: r,
Intervals: &mockIntervals{},
IncludeTracers: enabledTracers,
SamplesPerSecond: 1000,
ProbabilisticInterval: 100,
ProbabilisticThreshold: 100,
})
require.NoError(t, err)

trc.StartPIDEventProcessor(ctx)

err = trc.AttachTracer()
require.NoError(t, err)

log.Info("Attached tracer program")

err = trc.EnableProfiling()
require.NoError(t, err)

err = trc.AttachSchedMonitor()
require.NoError(t, err)

traceCh := make(chan *host.Trace)

// Spawn monitors for the various result maps
err = trc.StartMapMonitors(ctx, traceCh)
require.NoError(t, err)

return traceCh, trc
}

func startContainer(ctx context.Context, t *testing.T, image string) testcontainers.Container {
t.Log("starting", image)
// The offset tests load both platform images so docker gets confused if we don't specify
Expand Down Expand Up @@ -316,12 +278,6 @@ func makeRequests(ctx context.Context, t *testing.T, wg *sync.WaitGroup,
}()
}

type mockIntervals struct{}

func (f mockIntervals) MonitorInterval() time.Duration { return 1 * time.Second }
func (f mockIntervals) TracePollInterval() time.Duration { return 250 * time.Millisecond }
func (f mockIntervals) PIDCleanupInterval() time.Duration { return 1 * time.Second }

type symbolMap map[libpf.FrameID]string

type mockReporter struct {
Expand Down Expand Up @@ -349,10 +305,6 @@ func (m *mockReporter) getFunctionName(frameID libpf.FrameID) string {
return m.symbols[frameID]
}

func isRoot() bool {
return os.Geteuid() == 0
}

func removeSentinel(frames []host.Frame) []host.Frame {
for i, f := range frames {
if f.File == 0 {
Expand Down
6 changes: 3 additions & 3 deletions support/ebpf/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
SHELL ?= bash
BPF_CLANG ?= clang-16
BPF_LINK ?= llvm-link-16
LLC ?= llc-16
BPF_CLANG ?= clang-17
BPF_LINK ?= llvm-link-17
LLC ?= llc-17

DEBUG_FLAGS = -DOPTI_DEBUG -g

Expand Down
10 changes: 0 additions & 10 deletions support/ebpf/bpfdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,4 @@ static long (*bpf_perf_prog_read_value)(struct pt_regs *ctx, struct bpf_perf_eve

#endif // !TESTING_COREDUMP

// HACK: On failure, bpf_perf_prog_read_value() zeroes the buffer. We ensure that this always
// fail with a compile time assert that ensures that the struct size is different to the size
// of the expected structure.
#define bpf_large_memzero(_d, _l) \
({ \
_Static_assert(_l != sizeof(struct bpf_perf_event_value), "stack size must be different to the valid argument"); \
bpf_perf_prog_read_value(ctx, _d, _l); \
})


#endif // OPTI_BPFDEFS_H
1 change: 1 addition & 0 deletions support/ebpf/extmaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extern bpf_map_def inhibit_events;
extern bpf_map_def interpreter_offsets;
extern bpf_map_def system_config;
extern bpf_map_def trace_events;
extern bpf_map_def go_procs;

#if defined(TESTING_COREDUMP)

Expand Down
Loading