# Supported Runtimes for Dynamic Tracing in Code-Graph-RAG

> Explore supported runtimes for dynamic tracing in Code-Graph-RAG, including Python, Java, Node.js, .NET, PHP, Lua, Dart, Go, C/C++, Rust, and eBPF. Enhance your code analysis today.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: api-reference
- Published: 2026-09-04

---

**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`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/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

```bash
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

```bash
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

```bash
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

```bash
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

```bash
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:

- [`codebase_rag/trace/tracer.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/tracer.py) – Implements the core Python in-process tracer using `sys.monitoring`.
- `codebase_rag/trace/jvm_agent/` – Contains the Java agent source and built JAR for JDK 24+ instrumentation.
- [`codebase_rag/trace/pprof.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/pprof.py) – Utilities for converting Go and Rust pprof profiles into graph edges.
- [`codebase_rag/trace/ebpf_pprof.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/ebpf_pprof.py) – Handles ingestion and parsing of eBPF-exported pprof data.
- [`codebase_rag/trace/pytest_plugin.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/pytest_plugin.py) – pytest integration layer for zero-config Python tracing.
- [`codebase_rag/trace/c_agent/cgr_trace_shim.c`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/trace/c_agent/cgr_trace_shim.c) – C shim for `-finstrument-functions` trace collection.
- [`docs/guide/dynamic-tracing.md`](https://github.com/vitali87/code-graph-rag/blob/main/docs/guide/dynamic-tracing.md) – Complete runtime compatibility matrix and advanced configuration options.

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`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/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.