Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't import go.opentelemetry.io/ebpf-profiler/libpf with CGO_ENABLED=false #331

Closed
dmathieu opened this issue Jan 29, 2025 · 6 comments · Fixed by #332
Closed

Can't import go.opentelemetry.io/ebpf-profiler/libpf with CGO_ENABLED=false #331

dmathieu opened this issue Jan 29, 2025 · 6 comments · Fixed by #332

Comments

@dmathieu
Copy link
Member

dmathieu commented Jan 29, 2025

I need to import go.opentelemetry.io/ebpf-profiler/libpf with CGO_ENABLED=0 (in the context of a collector-contrib exporter).
However, the frametype file defines constants from the go.opentelemetry.io/ebpf-profiler/support package, which relies on CGO.

const (
// unknownFrame indicates a frame of an unknown interpreter.
// If this appears, it's likely a bug somewhere.
unknownFrame FrameType = support.FrameMarkerUnknown
// PHPFrame identifies PHP interpreter frames.
PHPFrame FrameType = support.FrameMarkerPHP
// PHPJITFrame identifies PHP JIT interpreter frames.
PHPJITFrame FrameType = support.FrameMarkerPHPJIT
// PythonFrame identifies the Python interpreter frames.
PythonFrame FrameType = support.FrameMarkerPython
// NativeFrame identifies native frames.
NativeFrame FrameType = support.FrameMarkerNative
// KernelFrame identifies kernel frames.
KernelFrame FrameType = support.FrameMarkerKernel
// HotSpotFrame identifies Java HotSpot VM frames.
HotSpotFrame FrameType = support.FrameMarkerHotSpot
// RubyFrame identifies the Ruby interpreter frames.
RubyFrame FrameType = support.FrameMarkerRuby
// PerlFrame identifies the Perl interpreter frames.
PerlFrame FrameType = support.FrameMarkerPerl
// V8Frame identifies the V8 interpreter frames.
V8Frame FrameType = support.FrameMarkerV8
// DotnetFrame identifies the Dotnet interpreter frames.
DotnetFrame FrameType = support.FrameMarkerDotnet
// AbortFrame identifies frames that report that further unwinding was aborted due to an error.
AbortFrame FrameType = support.FrameMarkerAbort
)

Could we either not rely on support, or move those constants into another package?
libpf has a lot of utility structs (such as FrameID or FileID) that make it hard not to rely on it when manipulating data that comes from profiles.

@dmathieu dmathieu changed the title Can't import libpf with CGO_ENABLED=false Can't import go.opentelemetry.io/ebpf-profiler/libpf with CGO_ENABLED=false Jan 29, 2025
@florianl
Copy link
Contributor

Just some background information:

At the moment, the source of truth around frame types is in the eBPF part:

// Indicates that the interpreter/runtime this frame belongs to is unknown.
#define FRAME_MARKER_UNKNOWN 0x0
// Indicates a Python frame
#define FRAME_MARKER_PYTHON 0x1
// Indicates a PHP frame
#define FRAME_MARKER_PHP 0x2
// Indicates a native frame
#define FRAME_MARKER_NATIVE 0x3
// Indicates a kernel frame
#define FRAME_MARKER_KERNEL 0x4
// Indicates a HotSpot frame
#define FRAME_MARKER_HOTSPOT 0x5
// Indicates a Ruby frame
#define FRAME_MARKER_RUBY 0x6
// Indicates a Perl frame
#define FRAME_MARKER_PERL 0x7
// Indicates a V8 frame
#define FRAME_MARKER_V8 0x8
// Indicates a PHP JIT frame
#define FRAME_MARKER_PHP_JIT 0x9
// Indicates a Dotnet frame
#define FRAME_MARKER_DOTNET 0xA

These C/eBPF constants and types are made available to the user space part/Go via package support:

const (
FrameMarkerUnknown = C.FRAME_MARKER_UNKNOWN
FrameMarkerErrorBit = C.FRAME_MARKER_ERROR_BIT
FrameMarkerPython = C.FRAME_MARKER_PYTHON
FrameMarkerNative = C.FRAME_MARKER_NATIVE
FrameMarkerPHP = C.FRAME_MARKER_PHP
FrameMarkerPHPJIT = C.FRAME_MARKER_PHP_JIT
FrameMarkerKernel = C.FRAME_MARKER_KERNEL
FrameMarkerHotSpot = C.FRAME_MARKER_HOTSPOT
FrameMarkerRuby = C.FRAME_MARKER_RUBY
FrameMarkerPerl = C.FRAME_MARKER_PERL
FrameMarkerV8 = C.FRAME_MARKER_V8
FrameMarkerDotnet = C.FRAME_MARKER_DOTNET
FrameMarkerAbort = C.FRAME_MARKER_ABORT
)

So in general package support acts as glue between the eBPF part and the user space part.

@christos68k
Copy link
Member

christos68k commented Jan 29, 2025

The good news is that the libpf dependency to support seems to be solely for frame marker types (though I could have missed a transitive dependency). So one solution would be to lift the single source of truth for those values from eBPF C to (for example) JSON and programmatically generate the C and Go code (similarly to what we do for metrics).

@dmathieu if we continue with the CGO requirement, what are the implications of not having the exporter available in contrib?

@dmathieu
Copy link
Member Author

It won't be included in the default collector distributions

@christos68k
Copy link
Member

christos68k commented Jan 29, 2025

It won't be included in the default collector distributions

But those distributions will also not be able to include the profiling agent functionality which depends on CGO, which essentially reduces down to distributions that want to export profiling data to ES that's coming in over OTLP (not captured by same collector distribution). That sounds like a common deployment scenario (edge collectors with direct profile capture that send profiling data to centralized collectors without direct profile capture capability) that we'd want to support.

@dmathieu
Copy link
Member Author

With the architecture where a collector runs as a daemonset with the profiling agent, and sends the data using OTLP to a cluster-wide collector.

Then, this collector receives the data and uses the ES exporter.
Then, the ES exporter needs to run without cgo.

The need for this issue comes from this PR:
open-telemetry/opentelemetry-collector-contrib#37567

I'll look into removing libpf from that exporter.

@florianl
Copy link
Contributor

With #332 I have opened a draft for a possible solution. The cgo part will be moved to the go generate stage before building. And so the package support can become CGO free (excluding the subpackage support/ebpf).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants