Lumentrace is an eBPF-powered function-level profiler for Go binaries. It attaches to a running process with no code changes required, watches every call to its exported functions, and streams a live call graph to a browser UI — flagging functions the moment their latency drifts away from their own baseline.
- Trace —
agent/bpf/profiler.bpf.cattaches a uprobe/uretprobe pair to eachmain.*function in the target binary. On entry and exit it pushes timing events (pid/tgid, function address, duration) through a BPF ring buffer. - Collect —
backend/cmd/main.goloads the compiled eBPF program, resolves the target binary's symbols, and reads the ring buffer. For each function it keeps a rolling window of recent call durations and computes a p95 baseline. - Detect — once a baseline is established, every new call is compared
against it. A p95 drift of more than 20% is flagged as a
regression; otherwise the function reportsok. - Visualize — the backend broadcasts call-graph edges (caller → callee)
and per-function stats over a WebSocket (
:8080/ws). Thefrontend/ebpf-projectReact app consumes the stream and renders it as a live, per-trace call graph.
A second, independent probe — agent/bpf/monitor.bpf.c — hooks
sys_enter_execve to capture process creation (pid, ppid, process name).
It's a general-purpose exec monitor and isn't wired into the profiler
pipeline above.
agent/— the eBPF (kernel-side) programsbpf/profiler.bpf.c— uprobe/uretprobe latency tracer used by the profilerbpf/monitor.bpf.c—execvetracepoint, reports new processesbpf/ebpf_structures.h— shared event structs and BPF map definitionsbpf/Makefile— compiles the.bpf.cfiles to.bpf.oobjects with clang
backend/cmd/— the Go collector/servermain.go— loadsprofiler.bpf.o, attaches uprobes to the target binary, computes p95 baselines, detects regressionsbroadcast.go— WebSocket server that fans events out to connected clientstypes.go— shared event/message typestest.go— a synthetic target program that callsmain → handleRequestA → handleRequestB → handleRequestCin a loop and injects an artificial 100x latency spike partway through, for exercising the profiler end-to-end
frontend/ebpf-project/— React + Vite app that connects to the WebSocket and renders the live call graphtest/— a standalone build of the synthetic target binary used for manual testing
Requires Linux with BTF support (kernel headers/vmlinux), clang, and Go.
-
Build the eBPF objects
cd agent/bpf make -
Build (or reuse) a target binary to profile. For a quick smoke test, build the synthetic target in
test/:cd test go build -gcflags="all=-l" -o target_service . ./target_service(
-gcflags="all=-l"disables inlining so the uprobes actually fire.) -
Run the collector (needs root to load eBPF programs), pointing it at the binary you want to profile:
cd backend/cmd sudo go run . ../../test/target_serviceThis starts the WebSocket server on
:8080/wsand begins tracing. -
Run the frontend
cd frontend/ebpf-project npm install npm run devOpen the printed local URL and connect it to the collector's WebSocket to watch the call graph update live, including the regression flag when
handleRequestC's injected latency spike kicks in.
Actively evolving / work in progress. Expect rough edges (e.g. the WebSocket URL the frontend connects to is currently hardcoded and will need to point at wherever the collector is running).