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
21 changes: 8 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,6 @@ test-junit: generate ebpf test-deps
go install gotest.tools/gotestsum@latest
CGO_ENABLED=1 gotestsum --junitfile $(JUNIT_OUT_DIR)/junit.xml -- $(GO_FLAGS) -tags $(GO_TAGS) ./...

# This target isn't called from CI, it doesn't work for cross compile (ie TARGET_ARCH=arm64 on
# amd64) and the CI kernel tests run them already. Useful for local testing.
sudo-golabels-test: integration-test-binaries
(cd support && sudo ./interpreter_golabels_test.test -test.v)

TESTDATA_DIRS:= \
nativeunwind/elfunwindinfo/testdata \
libpf/pfelf/testdata \
Expand All @@ -125,19 +120,19 @@ test-deps:
($(MAKE) -C "$(testdata_dir)") || exit ; \
)

TEST_INTEGRATION_BINARY_DIRS := tracer processmanager/ebpf support interpreter/golabels/test
TEST_INTEGRATION_BINARY_DIRS := tracer processmanager/ebpf support

# These binaries are named ".test" to get included into bluebox initramfs
support/golbls_1_23.test: ./interpreter/golabels/test/main.go
CGO_ENABLED=0 GOTOOLCHAIN=go1.23.7 go build -tags $(GO_TAGS),nocgo -o $@ $<
support/golbls_1_23.test: generate ebpf
CGO_ENABLED=0 GOTOOLCHAIN=go1.23.7 go test -C ./interpreter/golabels/integrationtests -c -trimpath -tags $(GO_TAGS),nocgo,integration -o $@

support/golbls_1_24.test: ./interpreter/golabels/test/main.go
CGO_ENABLED=0 GOTOOLCHAIN=go1.24.1 go build -tags $(GO_TAGS),nocgo -o $@ $<
support/golbls_1_24.test: generate ebpf
CGO_ENABLED=0 GOTOOLCHAIN=go1.24.1 go test -C ./interpreter/golabels/integrationtests -c -trimpath -tags $(GO_TAGS),nocgo,integration -o $@

support/golbls_cgo.test: ./interpreter/golabels/test/main-cgo.go
CGO_ENABLED=1 GOTOOLCHAIN=go1.24.1 go build -ldflags '-extldflags "-static"' -tags $(GO_TAGS),usecgo -o $@ $<
support/golbls_cgo.test: generate ebpf
CGO_ENABLED=1 GOTOOLCHAIN=go1.24.1 go test -C ./interpreter/golabels/integrationtests -c -ldflags '-extldflags "-static"' -trimpath -tags $(GO_TAGS),withcgo,integration -o $@

integration-test-binaries: generate ebpf support/golbls_1_23.test support/golbls_1_24.test support/golbls_cgo.test
integration-test-binaries: support/golbls_1_23.test support/golbls_1_24.test support/golbls_cgo.test
$(foreach test_name, $(TEST_INTEGRATION_BINARY_DIRS), \
(go test -ldflags='-extldflags=-static' -trimpath -c \
-tags $(GO_TAGS),static_build,integration \
Expand Down
10 changes: 10 additions & 0 deletions interpreter/golabels/integrationtests/busy_nocgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build nocgo && linux

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package integrationtests // import "go.opentelemetry.io/ebpf-profiler/interpreter/golabels/integrationtests"

//go:noinline
func busyFunc() {
}
11 changes: 11 additions & 0 deletions interpreter/golabels/integrationtests/busy_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build !nocgo && !withcgo

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

//nolint:lll
package integrationtests // import "go.opentelemetry.io/ebpf-profiler/interpreter/golabels/integrationtests"

//go:noinline
func busyFunc() {
}
23 changes: 23 additions & 0 deletions interpreter/golabels/integrationtests/busy_withcgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build withcgo && linux

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package integrationtests // import "go.opentelemetry.io/ebpf-profiler/interpreter/golabels/integrationtests"

/*
#include <stdio.h>

void cgofunc() {
volatile int counter = 0;
while (counter < 1000000) {
counter++;
}
}
*/
import "C"

//go:noinline
func busyFunc() {
C.cgofunc()
}
158 changes: 158 additions & 0 deletions interpreter/golabels/integrationtests/golabels_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
//go:build integration

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package integrationtests

import (
"context"
"math"
"math/rand"
"os"
"runtime/debug"
"runtime/pprof"
"strings"
"testing"
"time"

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

type mockIntervals struct{}

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

type mockReporter struct{}

func (mockReporter) ExecutableKnown(_ libpf.FileID) bool { return true }
func (mockReporter) ExecutableMetadata(_ *reporter.ExecutableMetadataArgs) {}

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

//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)
}

func setPprofLabels(t *testing.T, ctx context.Context, cookie string, busyFunc func()) {
t.Helper()
labels := pprof.Labels(
"l1"+cookie, "label1"+randomString(16),
"l2"+cookie, "label2"+randomString(24),
"l3"+cookie, "label3"+randomString(48))
lastUpdate := time.Now()
pprof.Do(context.TODO(), labels, func(context.Context) {
for time.Since(lastUpdate) < 10*time.Second {
// CPU go burr on purpose.
busyFunc()
if ctx.Err() != nil {
return
}
}
})
}

func Test_Golabels(t *testing.T) {
if !isRoot() {
t.Skip("root privileges required")
}

buildInfo, ok := debug.ReadBuildInfo()
if !ok {
t.Fatalf("Failed to get build info")
}

withCGO := false
for _, setting := range buildInfo.Settings {
if setting.Key == "CGO_ENABLED" {
withCGO = true
}
}
t.Logf("CGo is enabled: %t", withCGO)

cookie := buildInfo.GoVersion

t.Run(cookie, func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

enabledTracers, _ := tracertypes.Parse("")
enabledTracers.Enable(tracertypes.Labels)

trc, err := tracer.NewTracer(ctx, &tracer.Config{
Reporter: &mockReporter{},
Intervals: &mockIntervals{},
IncludeTracers: enabledTracers,
SamplesPerSecond: 20,
ProbabilisticInterval: 100,
ProbabilisticThreshold: 100,
OffCPUThreshold: uint32(math.MaxUint32 / 100),
VerboseMode: true,
})
require.NoError(t, err)

trc.StartPIDEventProcessor(ctx)

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

t.Log("Attached tracer program")

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

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

traceCh := make(chan *host.Trace)

err = trc.StartMapMonitors(ctx, traceCh)
require.NoError(t, err)

go setPprofLabels(t, ctx, cookie, busyFunc)

for trace := range traceCh {
if trace == nil {
continue
}
if len(trace.CustomLabels) > 0 {
hits := 0
for k, v := range trace.CustomLabels {
switch k {
case "l1" + cookie:
require.Len(t, v, 22)
require.True(t, strings.HasPrefix(v, "label1"))
hits |= (1 << 0)
case "l2" + cookie:
require.Len(t, v, 30)
require.True(t, strings.HasPrefix(v, "label2"))
hits |= (1 << 1)
case "l3" + cookie:
require.Len(t, v, 47)
require.True(t, strings.HasPrefix(v, "label3"))
hits |= (1 << 2)
}
}
if hits == (1<<0 | 1<<1 | 1<<2) {
cancel()
break
}
}
}
})
}
62 changes: 0 additions & 62 deletions interpreter/golabels/test/main-cgo.go

This file was deleted.

50 changes: 0 additions & 50 deletions interpreter/golabels/test/main.go

This file was deleted.

Loading