Supported Runtimes for Dynamic Tracing in Code-Graph-RAG

Code-Graph-RAG supports dynamic tracing across eleven distinct runtimes, including Python 3.12+, Java/Scala JDK 24+, Node.js, .NET, PHP, Lua, Dart, Go, C/C++, Rust, and eBPF-based continuous profilers, each utilizing specialized instrumentation mechanisms to capture runtime-only call edges.

Code-Graph-RAG (vitali87/code-graph-rag) enhances static call graph analysis by integrating dynamic tracing capabilities that capture execution paths invisible to static analysis. Understanding which runtimes are supported for dynamic tracing enables developers to analyze reflection-based calls, plugin registries, and monkey-patching behaviors that only manifest during program execution.

Supported Runtimes and Instrumentation Methods

According to the documentation in docs/guide/dynamic-tracing.md, the project explicitly lists eleven supported runtime environments, each with specific version requirements and tracing mechanisms.

Python 3.12 and Newer

Python tracing requires version 3.12 or later to leverage the sys.monitoring infrastructure. The framework provides an in-process tracer accessible either as a pytest plugin (codebase_rag/trace/pytest_plugin.py) or via the CallGraphTracer class. This captures every function entry and exit within the Python runtime, annotating edges with dynamic: true and dynamic_call_count properties.

Java and Scala (JDK 24+)

For Java and Scala applications, the tool requires JDK 24 or newer and utilizes a zero-dependency java.lang.instrument agent. The JVM agent instruments method entry points without requiring external libraries. The agent JAR is built via make jvm-agent and resides in codebase_rag/trace/jvm_agent/, recording call edges as they occur in the JVM.

Node.js (V8 Engine)

Node.js tracing works with any modern Node version using the V8 engine's built-in CPU profiler. The system converts V8 CPU profiles (--cpu-prof) into the internal trace format. This captures JavaScript execution paths including dynamic requires and event-driven callbacks.

.NET Runtime

.NET support leverages the dotnet-trace tool with EventPipe sampling. The tracer converts EventPipe traces into speedscope format before ingestion. This approach works across all .NET runtime implementations, including .NET Core and .NET 5+.

PHP with Xdebug

PHP tracing requires a PHP installation with the Xdebug extension enabled. The system converts Xdebug's full-function trace logs into graph edges, capturing dynamic includes and autoloaded class instantiations.

Pure Lua

Lua tracing uses a pure-Lua agent (cgr_trace.lua) built upon debug.sethook. This lightweight implementation requires no external C modules, making it suitable for embedded Lua environments.

Dart VM

Dart support utilizes the VM Service protocol to collect samples from any Dart VM instance. The tracer is packaged as a dart-pub tool that interfaces with the running VM to extract call stacks.

Go Runtime

Go tracing works with any Go version using the standard testing package's CPU profiler. The workflow runs go test -cpuprofile to generate pprof data, which codebase_rag/trace/pprof.py converts into traceable call edges.

C and C++

C and C++ applications require compilation with -finstrument-functions support. The system provides a shim (codebase_rag/trace/c_agent/cgr_trace_shim.c) that records every function call entry and exit during program execution.

Rust

Rust tracing integrates with the pprof-rs sampler. The system converts pprof output from Rust applications into the internal graph format, capturing dynamic dispatch and trait object calls via codebase_rag/trace/pprof.py.

eBPF Continuous Profilers

For eBPF-based profilers (Parca, Pyroscope, OpenTelemetry, and perf), the system ingests profiles exported in pprof format via the --format ebpf flag. This language-agnostic approach captures kernel-level and userspace execution across any runtime emitting eBPF profiles.

Capturing Execution Traces by Runtime

Each runtime requires specific invocation patterns to generate trace data. The following examples demonstrate how to enable tracing for the most common platforms.

Python Tracing with Pytest

cd /path/to/your/repo
pytest --cgr-trace
cgr trace ingest cgr-trace.jsonl --repo-path /path/to/your/repo

The --cgr-trace flag activates the pytest plugin, writing call events to cgr-trace.jsonl for subsequent ingestion.

Java JVM Agent Instrumentation

make jvm-agent
java -javaagent:build/cgr-jvm-agent.jar="include=com.example;repo=/path/to/your/repo" …

The agent string accepts include patterns to filter packages and a repo path for source correlation.

Node.js V8 CPU Profiling

node --cpu-prof --cpu-prof-name=run.cpuprofile app.js
cgr trace convert run.cpuprofile --repo-path /path/to/your/repo --workload smoke
cgr trace ingest cgr-trace.jsonl --repo-path /path/to/your/repo

The conversion step translates V8's sampling profiler output into the canonical trace format.

Go pprof Collection

go test -cpuprofile cpu.out -gcflags=all=-l ./mypkg
cgr trace convert cpu.out --repo-path /path/to/your/repo --workload go-test
cgr trace ingest cgr-trace.jsonl --repo-path /path/to/your/repo

The -gcflags=all=-l flag disables inlining to ensure complete call stack capture.

eBPF Profiler Integration

cgr trace pull "https://parca.example/...&format=pprof" \
    --repo-path /path/to/your/repo --format ebpf --language go \
    --label endpoint
cgr trace ingest cgr-trace.jsonl --repo-path /path/to/your/repo

This pulls existing pprof data from eBPF-based collectors like Parca, treating the continuous profiler as a dynamic trace source.

Core Tracing Implementation Files

The dynamic tracing functionality is implemented across several specialized modules:

These components collectively enable the capture of dynamic_receiver_types and runtime call frequencies that enrich the static analysis graph.

Summary

  • Code-Graph-RAG supports eleven distinct runtimes for dynamic tracing, from high-level languages like Python and Java to systems languages like C++ and Rust.
  • Minimum versions are enforced for Python (3.12+) and Java (JDK 24+) to utilize modern instrumentation APIs (sys.monitoring and java.lang.instrument).
  • eBPF compatibility provides language-agnostic tracing via pprof ingestion from tools like Parca and Pyroscope.
  • All tracers output to cgr-trace.jsonl format, merging runtime edges into the static call graph with properties like dynamic: true and dynamic_call_count.

Frequently Asked Questions

What is the minimum Python version required for dynamic tracing?

Dynamic tracing for Python requires version 3.12 or newer, as the implementation relies on the sys.monitoring infrastructure introduced in that release. Earlier Python versions lack the low-overhead tracing hooks necessary for efficient call graph capture.

How does Code-Graph-RAG trace Java applications without external dependencies?

The Java tracer utilizes the java.lang.instrument API built into the JDK 24+ standard library. The agent is compiled with zero external dependencies, requiring only the -javaagent flag at JVM startup to instrument method entries and exits automatically.

Can I use dynamic tracing with compiled languages like C++ and Rust?

Yes. For C and C++, compile with -finstrument-functions and link against codebase_rag/trace/c_agent/cgr_trace_shim.c. For Rust, integrate the pprof-rs crate to generate pprof output, which the system converts using codebase_rag/trace/pprof.py. Both methods capture compiled binary execution paths accurately.

What output format do the tracers produce?

All tracers generate JSON Lines (jsonl) files named cgr-trace.jsonl containing structured call events. These files include fields such as caller, callee, dynamic_call_count, and dynamic_receiver_types. The cgr trace ingest command merges these into the repository's static call graph database.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →