How to Pull eBPF Profiles for Code‑Graph‑RAG Analysis: A Complete 3‑Step Pipeline
Pull eBPF profiles using cgr trace pull, convert them to JSONL with cgr trace convert, then ingest dynamic CALLS edges into your knowledge graph via cgr trace ingest.
Code‑Graph‑RAG bridges static source analysis with runtime behavior by ingesting eBPF‑derived continuous profiles from systems like Parca, Pyroscope, OpenTelemetry, and perf. This integration adds dynamic call edges to your knowledge graph, annotating them with actual production dispatch patterns that static parsing cannot detect. The workflow relies on three CLI commands that fetch pprof‑encoded profiles, transform them into the project's interchange format, and merge the results into Memgraph.
The Three‑Stage eBPF Ingestion Pipeline
Code‑Graph‑RAG treats eBPF profiles identically to test‑run traces, with one key distinction: you must specify --format ebpf to ensure proper parsing of the gzipped protobuf format shared by Go's pprof tooling.
Stage 1: Fetch the Profile with cgr trace pull
The pull sub‑command downloads a profile from an HTTP(S) endpoint and persists it locally. In [codebase_rag/trace/cli.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/cli.py), the pull_cmd function orchestrates this fetch, handling optional authentication headers and writing the binary to a temporary file.
cgr trace pull "https://parca.example/api/v1/profile?format=pprof" \
--repo-path /path/to/your/repo \
--build-id 8f3a1234abcd \
--path-map /build/src/=/path/to/your/repo/src/ \
--label endpoint \
--header "Authorization=Bearer $TOKEN"
Key parameters for cgr trace pull:
--build-id— Filters the profile to symbols matching your target binary, discarding noise from other containers.--path-map— Rewrites build‑time absolute paths to your local repository structure, ensuring frame‑to‑source alignment.--header— Injects arbitrary HTTP headers for authenticated endpoints.--label— Attaches workload metadata that propagates through conversion and ingestion.
Stage 2: Convert to JSONL with cgr trace convert
The convert sub‑command transforms the raw pprof blob into cgr‑trace.jsonl, a line‑delimited JSON format the graph loader consumes. This step performs symbol demangling, path re‑anchoring, and language‑specific processing based on your --format and --language selections.
cgr trace convert prod.pb.gz \
--format ebpf \
--repo-path /path/to/your/repo \
--language go \
--build-id 8f3a1234abcd \
--path-map /build/src/=/path/to/your/repo/src/ \
--label endpoint \
--service service_name=checkout
The implementation in [codebase_rag/trace/trace_convert.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/trace_convert.py) handles:
- Parsing gzipped protobuf profiles
- Demangling C++ or Rust symbols when detected
- Applying path mappings to reconcile build and source locations
- Emitting structured call records with metadata payloads
Stage 3: Ingest Dynamic Edges with cgr trace ingest
The final stage merges runtime observations into your existing knowledge graph. The ingest sub‑command creates CALLS edges marked with dynamic: true and dynamic_sampled: true, annotated with properties like dynamic_call_count, dynamic_workloads, and dynamic_receiver_types.
# Ensure static graph exists first
cgr start --repo-path /path/to/your/repo --update-graph
# Ingest the converted trace
cgr trace ingest cgr-trace.jsonl --repo-path /path/to/your/repo
The ingestion logic in [codebase_rag/trace/trace_ingest.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/trace_ingest.py) performs upsert operations: existing static edges gain dynamic properties, while new edges are created for calls never observed in static analysis.
Automating Continuous Profile Ingestion
Production deployments benefit from automated, recurring ingestion. The following cron‑compatible script refreshes your dynamic overlay every five minutes:
#!/bin/bash
set -euo pipefail
PROFILE_URL="https://parca.example/api/v1/profile?format=pprof"
REPO="/path/to/your/repo"
BUILD_ID="8f3a1234abcd"
PATH_MAP="/build/src/=/path/to/your/repo/src/"
TOKEN="${PARCA_TOKEN}"
while true; do
cgr trace pull "$PROFILE_URL" \
--repo-path "$REPO" \
--build-id "$BUILD_ID" \
--path-map "$PATH_MAP" \
--header "Authorization=Bearer $TOKEN"
cgr trace convert prod.pb.gz \
--format ebpf \
--repo-path "$REPO" \
--language go \
--build-id "$BUILD_ID" \
--path-map "$PATH_MAP" \
--label endpoint \
--service service_name=checkout
cgr trace ingest cgr-trace.jsonl --repo-path "$REPO"
sleep 300
done
Key Implementation Files
Summary
- Pull eBPF profiles from profilers using
cgr trace pullwith--build-idand--path-mapfor precise symbol alignment. - Convert pprof data to JSONL via
cgr trace convert --format ebpf, enabling language‑aware processing. - Ingest dynamic call edges into Memgraph with
cgr trace ingest, enriching static analysis with production runtime behavior. - Automate the three‑stage pipeline for continuous observability integration.
Frequently Asked Questions
What eBPF profilers are compatible with Code‑Graph‑RAG?
Any profiler emitting pprof‑encoded profiles works, including Parca, Pyroscope, OpenTelemetry's profiling signal, and raw perf output converted to pprof. The --format ebpf flag indicates the shared protobuf format, not a specific tool.
Why is --build-id critical for accurate ingestion?
The build ID filters the profile to symbols from your exact binary. Without it, containerized deployments often include shared libraries and runtime frames from base images that pollute the call graph with irrelevant edges.
Can I ingest multiple services simultaneously?
Yes. Run separate convert and ingest commands per service with distinct --service labels, or aggregate profiles at the pull stage. The graph stores dynamic_workloads as an array property, supporting multi‑service analysis.
How does path mapping handle container build paths?
The --path-map argument accepts source=destination pairs. For Docker builds where source lives at /build/src/, map to your local checkout: --path-map /build/src/=/home/user/project/src/. This ensures stack frames resolve to correct repository files.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →