# How to Enable Dynamic Tracing for Node.js with Code-Graph-RAG

> Enable dynamic tracing for Node.js applications with Code-Graph-RAG. Convert V8 CPU profiles into dynamic CALLS relationships using CLI commands for enhanced code analysis.

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

---

**Code-Graph-RAG (CG-RAG) augments its static call-graph with runtime-observed edges by converting V8 CPU profiles into dynamic `CALLS` relationships using the `cgr trace convert` and `cgr trace ingest` CLI commands.**

Dynamic tracing bridges the gap between static analysis and actual runtime behavior in the `vitali87/code-graph-rag` repository. For Node.js applications, this process leverages the built-in V8 sampling profiler to capture real-world execution paths, then enriches the knowledge graph with edges and statistics that static parsing alone cannot detect, such as dynamic dispatch patterns and event-driven call chains.

## Understanding Dynamic Tracing in CG-RAG

Static analysis often misses runtime-generated code paths, including dynamic imports, event emitters, and polymorphic method dispatches. CG-RAG solves this by ingesting **V8 CPU profiles** (`*.cpuprofile`) collected from live Node.js workloads. According to the source code, the system creates `CALLS` edges marked with `dynamic: true` and populates metrics like `dynamic_call_count` and `dynamic_workload` to distinguish these runtime observations from statically derived relationships.

The conversion logic resides in `codebase_rag/trace/node_tracer/`, which parses the V8 JSON format and translates stack frames into the CG-RAG interchange format (`cgr-trace.jsonl`). The CLI entry point at `src/bin/cgr` implements the two-step workflow: conversion followed by ingestion.

## Prerequisites

Before capturing traces, ensure your environment meets these requirements:

- **Node.js** with V8 profiling support (Node.js 12.0.0+ includes the `--cpu-prof` flag)
- **CG-RAG CLI** installed and available as `cgr` in your shell
- Access to the target repository root path for symbol resolution

## Step-by-Step: Capturing and Ingesting Node.js Traces

### Step 1: Record a V8 CPU Profile

Run your Node.js application or test suite with the V8 sampling profiler enabled. This generates a `.cpuprofile` file containing sampled stack traces.

```bash
node --cpu-prof --cpu-prof-name=run.cpuprofile app.js

```

- `--cpu-prof` enables V8’s sampling profiler
- `--cpu-prof-name` specifies the output filename (default pattern: `isolate-*.cpuprofile`)

### Step 2: Convert the Profile to CG-RAG Format

Use the `cgr trace convert` command to transform the V8 profile into `cgr-trace.jsonl`. You must provide the repository root path and a workload label for filtering.

```bash
cgr trace convert run.cpuprofile \
    --repo-path /path/to/your-repo \
    --workload smoke

```

- `--repo-path` tells the converter where the source tree lives for frame-to-symbol resolution
- `--workload` assigns a label (e.g., "smoke", "unit-tests") used later for filtering dynamic edges

This command outputs a `cgr-trace.jsonl` file containing resolved call records in the CG-RAG interchange format.

### Step 3: Ingest the Trace into the Graph

Feed the generated JSON-Lines file into the CG-RAG graph database to create dynamic edges.

```bash
cgr trace ingest cgr-trace.jsonl \
    --repo-path /path/to/your-repo

```

During ingestion, the system resolves recorded frames back to source nodes, creates `CALLS` edges annotated with `dynamic: true`, and aggregates statistics including `dynamic_call_count` and `dynamic_workload` properties on the relationships.

## Working with Multiple Profiles

When running parallel Node.js workers or distributed test suites (such as with `pytest-xdist` equivalents), you will generate multiple `*.cpuprofile` files. Convert each profile individually, then ingest all resulting `cgr-trace.jsonl` files in a single batch operation:

```bash

# Convert multiple profiles

cgr trace convert worker-1.cpuprofile --repo-path ./repo --workload parallel-suite
cgr trace convert worker-2.cpuprofile --repo-path ./repo --workload parallel-suite

# Ingest all traces

cgr trace ingest cgr-trace.jsonl --repo-path ./repo

```

## Key Implementation Files

The dynamic tracing pipeline relies on these specific components in the `vitali87/code-graph-rag` repository:

- **[`docs/guide/dynamic-tracing.md`](https://github.com/vitali87/code-graph-rag/blob/main/docs/guide/dynamic-tracing.md)** – The comprehensive user guide explaining the full workflow for all supported runtimes, including Node.js-specific details
- **`codebase_rag/trace/node_tracer/`** – Contains the conversion logic that parses V8 `cpuprofile` JSON and emits standardized trace records
- **`src/bin/cgr`** – The CLI entry point implementing `cgr trace convert` and `cgr trace ingest` commands

## Summary

- **Dynamic tracing** in CG-RAG enriches static analysis with runtime `CALLS` edges derived from V8 CPU profiles.
- The **three-step workflow** involves recording with `--cpu-prof`, converting via `cgr trace convert`, and ingesting via `cgr trace ingest`.
- Converted traces produce `cgr-trace.jsonl` files containing resolved call records with workload labels.
- Ingested edges carry the property `dynamic: true` and statistics like `dynamic_call_count` to distinguish them from static analysis results.
- The **`codebase_rag/trace/node_tracer/`** module handles V8-specific parsing, while **`src/bin/cgr`** provides the user-facing CLI interface.

## Frequently Asked Questions

### What Node.js versions support dynamic tracing with CG-RAG?

Any Node.js version 12.0.0 or later supports dynamic tracing, as these versions include the `--cpu-prof` flag for the V8 sampling profiler. The CG-RAG converter handles the standard V8 CPU profile format consistently across Node.js releases.

### How does CG-RAG resolve minified or transpiled code in profiles?

The `cgr trace convert` command uses the `--repo-path` parameter to map profile frames back to original source locations. When you point to the repository root, the system attempts to resolve frames against the local source tree, though accuracy depends on having source maps or original source files available alongside the executed code.

### Can I merge multiple CPU profiles into a single graph?

Yes. Convert each individual `*.cpuprofile` to its own `cgr-trace.jsonl` file, then run `cgr trace ingest` on all generated trace files. The ingestion process aggregates statistics across all provided traces, incrementing `dynamic_call_count` for edges that appear in multiple profiles while maintaining the `dynamic_workload` labels for filtering.

### What is the difference between static and dynamic CALLS edges in CG-RAG?

Static `CALLS` edges are derived from parsing source code (e.g., AST analysis) and represent syntactic function invocations. Dynamic `CALLS` edges are created from runtime CPU profiles and capture actual executed paths, including those involving dynamic dispatch, closures, and event-driven architectures that static analysis cannot predict. Dynamic edges carry the `dynamic: true` property and workload-specific metadata.