Skip to content

feat(nvtx): app-integrated in-process NVTX capture - #402

Merged
rapids-bot[bot] merged 2 commits into
rapidsai:mainfrom
9prady9:nvtx-bridge-v2
Jul 22, 2026
Merged

feat(nvtx): app-integrated in-process NVTX capture#402
rapids-bot[bot] merged 2 commits into
rapidsai:mainfrom
9prady9:nvtx-bridge-v2

Conversation

@9prady9

@9prady9 9prady9 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Wires captured NVTX events into a Quent pipeline, completing the foundational NVTX stack (#386 quent-nvtx-events, #391 quent-nvtx-injection).

What it is

The application drives capture: it owns its Quent Context and exporter, annotates its code with the NVTX Rust API, and links quent-nvtx-injection with its static-injection feature so NVTX initializes injection in-process at the first NVTX call — no cdylib, no NVTX_INJECTION64_PATH.

  • quent-nvtx-bridgeNvtxEventEntity, a #[serde(transparent)] newtype over NvtxEvent implementing Quent's EntityEvent (the orphan-rule adapter; the only crate depending on Quent internals).
  • quent-instrumentation — adds Observer::sender(), a cloned EventSender so the 'static injection hook can emit into an app-owned observer that still flushes on drop.
  • quent-nvtx-injectionstatic-injection links the strong-symbol shim with +whole-archive, so the strong InitializeInjectionNvtx2 overrides NVTX's weak no-op.
  • quent-nvtx-example — runnable wiring plus its test.

Using it

let observer = ctx.block_on(async { ctx.observer::<NvtxEventEntity>(opts).await })?;
let sender = observer.sender();
quent_nvtx_injection::install_hook(move |e| {
    sender.send(Event::new_now(session, NvtxEventEntity::from(e)));
})?;
// ... nvtx::mark!(...), nvtx::range!(...) ...
drop(observer); // flush

Tests

cargo test -p quent-nvtx-example runs the example against a temp dir and asserts every core NVTX kind round-trips through ndjson. No GPU. Linux 64-bit only.

@9prady9 9prady9 added the feature request New feature or request label Jul 17, 2026
@9prady9 9prady9 changed the title feat(nvtx): add quent-nvtx bridge (capture pipeline + e2e) feat(nvtx): add quent-nvtx-instrumentation bridge (capture pipeline + e2e) Jul 17, 2026
@9prady9
9prady9 marked this pull request as ready for review July 20, 2026 10:51
@9prady9
9prady9 requested a review from johanpel July 20, 2026 10:52
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds NVTX bridge and example crates to the workspace, exposes observer senders, ensures static injection linkage, and documents and tests in-process NVTX capture.

Changes

NVTX capture integration

Layer / File(s) Summary
Event bridge and observer access
Cargo.toml, crates/instrumentation/src/observer.rs, integrations/nvtx/bridge/...
Registers the bridge crate, adds NvtxEventEntity, and exposes Observer::sender() for event producers.
Static injection linkage
integrations/nvtx/injection/...
Force-links the static injection shim and documents the strong-symbol override and attach modes.
Example capture and validation
integrations/nvtx/example/..., integrations/nvtx/README.md
Adds in-process NVTX capture, validates core event kinds, and documents setup, supported APIs, generated bindings, and testing.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • rapidsai/quent#386 — Provides the NVTX event vocabulary wrapped by the new bridge.
  • rapidsai/quent#391 — Introduces the static-injection path whose shim linkage is updated here.
  • rapidsai/quent#403 — Overlaps with the NVTX integration crate naming and README updates.

Suggested labels: improvement

Suggested reviewers: mbrobbel, dhruv9vats

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: app-integrated in-process NVTX capture.
Description check ✅ Passed The description explains the change, usage, and testing; only optional issue links/screenshots are missing.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
integrations/nvtx/instrumentation/build.rs (1)

41-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Preserve cc’s configured compiler args here.

compiler.path() drops the flags and wrappers cc already inferred from CXX/CXXFLAGS and cross-target setup. Use compiler.to_command() so the sample build keeps those settings and still appends the local flags.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/nvtx/instrumentation/build.rs` around lines 41 - 53, Update the
sample compilation command in the build script to start from cc’s configured
command via compiler.to_command() instead of creating a new Command from
compiler.path(). Preserve the existing local arguments for C++17, optimization,
pthreads, includes, source, output, and dl, while retaining all compiler flags,
wrappers, and cross-target settings inferred by cc.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@integrations/nvtx/instrumentation/build.rs`:
- Around line 41-53: Update the sample compilation command in the build script
to start from cc’s configured command via compiler.to_command() instead of
creating a new Command from compiler.path(). Preserve the existing local
arguments for C++17, optimization, pthreads, includes, source, output, and dl,
while retaining all compiler flags, wrappers, and cross-target settings inferred
by cc.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 72b20491-801a-45b9-a721-48d83f179b89

📥 Commits

Reviewing files that changed from the base of the PR and between c0d3781 and 77d83df.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !Cargo.lock
📒 Files selected for processing (7)
  • Cargo.toml
  • integrations/nvtx/README.md
  • integrations/nvtx/instrumentation/Cargo.toml
  • integrations/nvtx/instrumentation/build.rs
  • integrations/nvtx/instrumentation/c/sample_app.cpp
  • integrations/nvtx/instrumentation/src/lib.rs
  • integrations/nvtx/instrumentation/tests/capture_e2e.rs

@johanpel johanpel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work so far @9prady9. I have some comments which might require a significant change to the approach here, so before I proceed to review in detail:

Comment thread integrations/nvtx/instrumentation/c/sample_app.cpp Outdated
Comment thread integrations/nvtx/instrumentation/src/lib.rs Outdated
Comment thread integrations/nvtx/instrumentation/src/lib.rs Outdated
@9prady9
9prady9 marked this pull request as draft July 20, 2026 13:46
@9prady9

9prady9 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Had a quick call with @johanpel about the comment threads #402 (comment) and #402 (comment)

I had different use case that I was trying to cover as well - app and/or library without any code changes which complicated the bridge design.

I am addressing all of the above that simplifies the use case - quent instrumentation with additional nvtx range annotations.

@9prady9 9prady9 changed the title feat(nvtx): add quent-nvtx-instrumentation bridge (capture pipeline + e2e) feat(nvtx): app-integrated in-process NVTX capture Jul 22, 2026
@9prady9
9prady9 requested a review from johanpel July 22, 2026 11:06
@9prady9
9prady9 marked this pull request as ready for review July 22, 2026 11:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (3)
integrations/nvtx/README.md-66-71 (1)

66-71: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

End the range before flushing the observer.

_range is dropped after drop(observer), so its RangeEnd is discarded. Explicitly drop the guard first.

Proposed fix
-nvtx::mark!("startup");
-let _range = nvtx::range!("phase-1");
+nvtx::mark!("startup");
+let range = nvtx::range!("phase-1");
+drop(range);
 
 // 4. Flush by dropping the observer.
 drop(observer);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/nvtx/README.md` around lines 66 - 71, Update the NVTX example so
the range guard created by nvtx::range!("phase-1") is explicitly dropped before
drop(observer), ensuring the range ends before the observer is flushed.
integrations/nvtx/README.md-39-42 (1)

39-42: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Name the actual overridden symbol.

integrations/nvtx/injection/build.rs Line 89 identifies the strong symbol as InitializeInjectionNvtx2_fnptr, not InitializeInjectionNvtx2. Keep the mechanism documentation consistent.

-   feature, publishing a *strong* `InitializeInjectionNvtx2` that overrides the
+   feature, publishing a *strong* `InitializeInjectionNvtx2_fnptr` that overrides the
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/nvtx/README.md` around lines 39 - 42, Update the mechanism
description in the README to name the actual strong overridden symbol,
InitializeInjectionNvtx2_fnptr, instead of InitializeInjectionNvtx2; keep the
surrounding explanation of static injection and in-process initialization
unchanged.
integrations/nvtx/example/src/main.rs-31-36 (1)

31-36: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject invalid explicit session IDs.

A supplied non-UTF-8 or invalid UUID silently becomes a random session, so a harness cannot locate its output. Return an argument error instead.

Proposed fix
-    let session = std::env::args_os()
-        .nth(2)
-        .and_then(|arg| arg.to_str().and_then(|s| Uuid::parse_str(s).ok()))
-        .unwrap_or_else(Uuid::now_v7);
+    let session = match std::env::args_os().nth(2) {
+        Some(arg) => Uuid::parse_str(arg.to_str().ok_or_else(|| {
+            std::io::Error::new(
+                std::io::ErrorKind::InvalidInput,
+                "session must be a UTF-8 UUID",
+            )
+        })?)?,
+        None => Uuid::now_v7(),
+    };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/nvtx/example/src/main.rs` around lines 31 - 36, Update the
session parsing flow in main around std::env::args_os and Uuid::parse_str so an
explicitly supplied second argument must be valid UTF-8 and a valid UUID; return
an argument error for non-UTF-8 or invalid values instead of falling back to
Uuid::now_v7. Retain fresh UUID generation only when no session argument is
provided.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Other comments:
In `@integrations/nvtx/example/src/main.rs`:
- Around line 31-36: Update the session parsing flow in main around
std::env::args_os and Uuid::parse_str so an explicitly supplied second argument
must be valid UTF-8 and a valid UUID; return an argument error for non-UTF-8 or
invalid values instead of falling back to Uuid::now_v7. Retain fresh UUID
generation only when no session argument is provided.

In `@integrations/nvtx/README.md`:
- Around line 66-71: Update the NVTX example so the range guard created by
nvtx::range!("phase-1") is explicitly dropped before drop(observer), ensuring
the range ends before the observer is flushed.
- Around line 39-42: Update the mechanism description in the README to name the
actual strong overridden symbol, InitializeInjectionNvtx2_fnptr, instead of
InitializeInjectionNvtx2; keep the surrounding explanation of static injection
and in-process initialization unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 973bdf18-5fc2-4077-aae3-e8eb9f60af9b

📥 Commits

Reviewing files that changed from the base of the PR and between 77d83df and 87c05e2.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !Cargo.lock
📒 Files selected for processing (9)
  • Cargo.toml
  • crates/instrumentation/src/observer.rs
  • integrations/nvtx/README.md
  • integrations/nvtx/bridge/Cargo.toml
  • integrations/nvtx/bridge/src/lib.rs
  • integrations/nvtx/example/Cargo.toml
  • integrations/nvtx/example/src/main.rs
  • integrations/nvtx/example/tests/capture.rs
  • integrations/nvtx/injection/build.rs

@johanpel johanpel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, great work @9prady9. Some minor comments:

Comment thread integrations/nvtx/example/src/main.rs Outdated
Comment thread integrations/nvtx/example/tests/capture.rs
Comment thread integrations/nvtx/example/Cargo.toml Outdated
Comment thread crates/instrumentation/src/observer.rs Outdated
9prady9 added 2 commits July 22, 2026 18:47
Signed-off-by: Pradeep Garigipati <pgarigipati@nvidia.com>
- example: split into a lib + bin. The demo prints captured events through a
  callback exporter; the test reuses the same `run_capture` routine in-process
  with a collecting callback exporter and asserts coverage — no subprocess and
  no temp files.
- nvtx-injection: document the `static-injection` feature (manifest comment +
  crate "Attach modes" docs) rather than explaining it in the example manifest.
- instrumentation: `Observer::sender()` docs no longer call post-drop sends
  "silent" — the first is logged via `tracing`.

Signed-off-by: Pradeep Garigipati <pgarigipati@nvidia.com>
@9prady9
9prady9 requested a review from johanpel July 22, 2026 13:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (2)
integrations/nvtx/README.md-111-113 (1)

111-113: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace “no-oping” with standard wording.

Use “silently dropping the call” or “silently doing nothing” instead of “silently no-oping” at Line 113.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/nvtx/README.md` around lines 111 - 113, Update the wide-char
variants description in the README to replace “silently no-oping” with the
standard wording “silently dropping the call” or “silently doing nothing,”
without changing the surrounding behavior description.

Source: Linters/SAST tools

integrations/nvtx/injection/Cargo.toml-27-32 (1)

27-32: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the pointer symbol name consistently in the static-injection docs.

integrations/nvtx/injection/Cargo.toml and integrations/nvtx/injection/src/lib.rs mix InitializeInjectionNvtx2 with the strong symbol actually linked by static-injection, InitializeInjectionNvtx2_fnptr. Reserve InitializeInjectionNvtx2 for the exported entry point and use InitializeInjectionNvtx2_fnptr for the linked symbol.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/nvtx/injection/Cargo.toml` around lines 27 - 32, The
static-injection documentation in integrations/nvtx/injection/Cargo.toml (lines
27-32) and integrations/nvtx/injection/src/lib.rs (lines 17-20) uses the wrong
symbol name for the linked pointer. Update both sites to refer to
InitializeInjectionNvtx2_fnptr, reserving InitializeInjectionNvtx2 for the
exported entry point.
🧹 Nitpick comments (1)
crates/instrumentation/src/observer.rs (1)

121-126: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep Observer::sender documentation contract-focused.

Lines 121-126 lead with the concrete EventSender clone/pipeline mechanism and restate the type. Retain the ownership, flush, and post-drop behavior, but make that observable contract the opening. As per path instructions: “Docstrings state the contract, not the mechanism; do not restate types.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/instrumentation/src/observer.rs` around lines 121 - 126, Update the
documentation for Observer::sender to lead with its observable ownership,
flush-on-drop, and post-drop send behavior. Remove the implementation-focused
explanation about cloning, the pipeline, and restating EventSender, while
preserving the documented behavior that sends after observer drop are discarded
and only the first logs an error.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Other comments:
In `@integrations/nvtx/injection/Cargo.toml`:
- Around line 27-32: The static-injection documentation in
integrations/nvtx/injection/Cargo.toml (lines 27-32) and
integrations/nvtx/injection/src/lib.rs (lines 17-20) uses the wrong symbol name
for the linked pointer. Update both sites to refer to
InitializeInjectionNvtx2_fnptr, reserving InitializeInjectionNvtx2 for the
exported entry point.

In `@integrations/nvtx/README.md`:
- Around line 111-113: Update the wide-char variants description in the README
to replace “silently no-oping” with the standard wording “silently dropping the
call” or “silently doing nothing,” without changing the surrounding behavior
description.

---

Nitpick comments:
In `@crates/instrumentation/src/observer.rs`:
- Around line 121-126: Update the documentation for Observer::sender to lead
with its observable ownership, flush-on-drop, and post-drop send behavior.
Remove the implementation-focused explanation about cloning, the pipeline, and
restating EventSender, while preserving the documented behavior that sends after
observer drop are discarded and only the first logs an error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 989fdc6b-b08a-4bad-a13c-7c586518fd78

📥 Commits

Reviewing files that changed from the base of the PR and between 3b749d1 and 9fde486.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !Cargo.lock
📒 Files selected for processing (12)
  • Cargo.toml
  • crates/instrumentation/src/observer.rs
  • integrations/nvtx/README.md
  • integrations/nvtx/bridge/Cargo.toml
  • integrations/nvtx/bridge/src/lib.rs
  • integrations/nvtx/example/Cargo.toml
  • integrations/nvtx/example/src/lib.rs
  • integrations/nvtx/example/src/main.rs
  • integrations/nvtx/example/tests/capture.rs
  • integrations/nvtx/injection/Cargo.toml
  • integrations/nvtx/injection/build.rs
  • integrations/nvtx/injection/src/lib.rs

@johanpel johanpel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, happy to see this integration come alive!

@9prady9

9prady9 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Nice, happy to see this integration come alive!

a few more things here and there I think.

@9prady9

9prady9 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit 3598e94 into rapidsai:main Jul 22, 2026
12 checks passed
@9prady9
9prady9 deleted the nvtx-bridge-v2 branch July 22, 2026 13:53
@9prady9 9prady9 mentioned this pull request Jul 22, 2026
5 tasks
9prady9 added a commit to 9prady9/quent that referenced this pull request Jul 27, 2026
Full Phase-1 (NVTX capture foundation) planning and execution record: discuss/research/plan artifacts, per-plan SUMMARYs (events vocabulary, injection cdylib, bridge + capture e2e, full core coverage), tracking updates, code review and security verification, and reconciliation with the upstream merge (PR rapidsai#402).

Signed-off-by: Pradeep Garigipati <pgarigipati@nvidia.com>

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants