Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ members = [
"crates/stdlib",
"crates/time",
"crates/ui",
# NVTX integration crates
"integrations/nvtx/events",
# Domain-specific crates
"domains/query_engine/analyzer",
"domains/query_engine/model",
Expand Down Expand Up @@ -93,6 +95,8 @@ default-members = [
"crates/stdlib",
"crates/time",
"crates/ui",
# NVTX integration crates
"integrations/nvtx/events",
"domains/query_engine/analyzer",
"domains/query_engine/model",
"domains/query_engine/server",
Expand Down
15 changes: 15 additions & 0 deletions integrations/nvtx/events/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "quent-nvtx-events"
version.workspace = true
edition.workspace = true
publish.workspace = true

[dependencies]
serde = { workspace = true, optional = true }

[features]
default = ["serde"]
# Derive serde `Serialize`/`Deserialize` for the vocabulary types. Optional
# because a consumer that only needs the in-memory types (e.g. a callback sink)
# does not require serde.
serde = ["dep:serde"]
57 changes: 57 additions & 0 deletions integrations/nvtx/events/src/attributes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

//! Captured subset of `nvtxEventAttributes_t`.
//!
//! These types mirror the raw NVTX attribute members verbatim (message, color,
//! category, payload). Handles are never resolved at capture time — the analyzer
//! resolves registered strings, domains, and categories from the event stream in
//! a later phase.

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

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.

We might want to feature gate serde support since not all exporters require it since #250 was solved


use crate::payload::NvtxPayload;

/// A message attached to an NVTX event.
///
/// Registered messages keep only their raw handle, never resolved at capture
/// time. The analyzer maps [`NvtxMessage::RegisteredHandle`] back to its string
/// from the captured [`RegisterString`](crate::NvtxEvent::RegisterString) events.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum NvtxMessage {
/// An immediate string message, copied verbatim at capture.
String(String),
/// A handle to a previously registered string; resolved in the analyzer.
RegisteredHandle(u64),
}

/// A verbatim NVTX color attribute: the raw `nvtxColorType_t` tag paired with
/// the raw color value (e.g. `NVTX_COLOR_ARGB`).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct NvtxColor {
/// Raw `nvtxColorType_t` tag.
pub color_type: i32,
/// Raw color value (e.g. packed ARGB).
pub value: u32,
}

/// Captured subset of `nvtxEventAttributes_t`.
///
/// Only the members Quent reconstructs from are retained (`category`, `color`,
/// `message`, `payload`); all are stored verbatim with no capture-time
/// resolution or decoding.
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct NvtxEventAttributes {
/// Raw category id (`0` = none). Namespaced by domain in the analyzer.
pub category: u32,
/// Optional color attribute.
pub color: Option<NvtxColor>,
/// Optional message (immediate string or registered handle).
pub message: Option<NvtxMessage>,
/// Optional payload union value from the core `nvtxEventAttributes`.
pub payload: Option<NvtxPayload>,
}
126 changes: 126 additions & 0 deletions integrations/nvtx/events/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

//! Verbatim, Quent-agnostic NVTX event vocabulary.
//!
//! Every downstream NVTX crate speaks this shared contract: the injection cdylib
//! produces [`NvtxEvent`]s and the bridge forwards them into Quent. Events are
//! captured **verbatim** — every handle (domain / category / resource /
//! registered-string id) is a raw integer, and no name resolution or payload
//! decoding happens at capture time. Handles are resolved from the event stream
//! by a later analysis stage.
//!
//! The crate deliberately depends on nothing Quent-internal (optionally only
//! `serde`, behind the default `serde` feature) so it stays cleanly separable and
//! could be offered upstream to the NVTX Rust crates later. Adapting these events
//! into Quent's pipeline — entity naming, the event wrapper — is the bridge
//! crate's responsibility, not this crate's.

mod attributes;
mod payload;

pub use attributes::{NvtxColor, NvtxEventAttributes, NvtxMessage};
pub use payload::{NvtxPayload, NvtxPayloadValue, PayloadExtensionEvent};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// A verbatim NVTX core event.
///
/// Every variant mirrors one core NVTX call kind. Handles are raw integers,
/// captured with no resolution. The default (NULL) domain is represented as a
/// `domain` of `0`.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum NvtxEvent {
/// `nvtxDomainRangePushEx` — open a nested (per-thread) range.
RangePush {
/// Raw domain handle (`0` = default domain).
domain: u64,
/// Captured event attributes (message, color, category, payload).
attributes: NvtxEventAttributes,
},
/// `nvtxDomainRangePop` — close the most recent push on this thread.
RangePop {
/// Raw domain handle (`0` = default domain).
domain: u64,
},
/// `nvtxDomainRangeStartEx` — open a process-wide range keyed by id.
RangeStart {
/// Raw domain handle (`0` = default domain).
domain: u64,
/// Raw `nvtxRangeId_t` correlating start and end.
range_id: u64,
/// Captured event attributes (message, color, category, payload).
attributes: NvtxEventAttributes,
},
/// `nvtxDomainRangeEnd` — close the range with the matching id.
RangeEnd {
/// Raw domain handle (`0` = default domain).
domain: u64,
/// Raw `nvtxRangeId_t` correlating start and end.
range_id: u64,
},
/// `nvtxDomainMarkEx` — an instantaneous marker.
Mark {
/// Raw domain handle (`0` = default domain).
domain: u64,
/// Captured event attributes (message, color, category, payload).
attributes: NvtxEventAttributes,
},
/// `nvtxDomainCreate` — create a named domain.
DomainCreate {
/// Raw domain handle assigned by NVTX.
domain: u64,
/// The domain's name.
name: String,
},
/// `nvtxDomainDestroy` — destroy a domain.
DomainDestroy {
/// Raw domain handle being destroyed.
domain: u64,
},
/// `nvtxDomainRegisterString` — register a string, returning a handle.
RegisterString {
/// Raw domain handle the string is registered against.
domain: u64,
/// Raw registered-string handle assigned by NVTX.
handle: u64,
/// The registered string value.
string: String,
},
/// `nvtxDomainNameCategory` — name a category within a domain.
NameCategory {
/// Raw domain handle the category belongs to.
domain: u64,
/// Raw category id (namespaced by `domain` in the analyzer).
category: u32,
/// The category's name.
name: String,
},
/// `nvtxNameOsThread` — name an OS thread.
NameThread {
/// Raw OS thread id.
thread_id: u32,
/// The thread's name.
name: String,
},
/// `nvtxDomainResourceCreate` — associate a resource with a handle.
ResourceCreate {
/// Raw domain handle the resource belongs to.
domain: u64,
/// Raw resource handle assigned by NVTX.
handle: u64,
/// Raw `identifierType` tag from `nvtxResourceAttributes_t`.
identifier_type: i32,
/// Raw identifier value (union member captured as bits).
identifier: u64,
/// Optional resource name (immediate string or registered handle).
message: Option<NvtxMessage>,
},
/// `nvtxDomainResourceDestroy` — release a resource handle.
ResourceDestroy {
/// Raw resource handle being destroyed.
handle: u64,
},
}
93 changes: 93 additions & 0 deletions integrations/nvtx/events/src/payload.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

//! NVTX payload vocabulary.
//!
//! Two tiers live here:
//!
//! * The payload **union** carried on core `nvtxEventAttributes` — captured
//! verbatim (undecoded) ([`NvtxPayload`]).
//! * The payload-**extension** vocabulary (schema/enum registration, binary
//! blobs) — **defined but not wired** ([`PayloadExtensionEvent`]). These are
//! deferred to a later phase (alongside payload decoding); they exist now only
//! so the stream can carry them later without a vocabulary-breaking change. No
//! capture path emits them today.

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// The payload union carried on core `nvtxEventAttributes`, captured verbatim
/// (undecoded).
///
/// Carries the raw `NVTX_PAYLOAD_TYPE_*` tag alongside the scalar value the
/// union holds. Interpretation/decoding is deferred to the analyzer.
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct NvtxPayload {
/// Raw `NVTX_PAYLOAD_TYPE_*` tag, preserved verbatim.
pub payload_type: i32,
/// The scalar value carried by the union.
pub value: NvtxPayloadValue,
}

/// The scalar members of the core payload union.
///
/// Each variant mirrors one member of NVTX's payload union; values are captured
/// as-is with no reinterpretation.
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum NvtxPayloadValue {
/// `ullValue` — unsigned 64-bit integer.
UnsignedInt64(u64),
/// `llValue` — signed 64-bit integer.
Int64(i64),
/// `dValue` — double-precision float.
Double(f64),
/// `uiValue` — unsigned 32-bit integer.
UnsignedInt32(u32),
/// `iValue` — signed 32-bit integer.
Int32(i32),
/// `fValue` — single-precision float.
Float(f32),
/// A pointer-sized handle, captured as raw bits.
///
/// Reserved for a future payload-extension mapping; **not** emitted by core
/// capture (unknown core payload tags fall back to [`Self::UnsignedInt64`]).
Pointer(u64),
}

/// NVTX payload-**extension** vocabulary.
///
/// Deferred: these variants are defined so the event stream can carry
/// payload-extension data in a later phase without a vocabulary-breaking change,
/// but they are **not** wired into [`NvtxEvent`](crate::NvtxEvent) and no capture
/// path emits them yet.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum PayloadExtensionEvent {
/// Register a payload schema (`nvtxPayloadSchemaRegister`).
SchemaRegister {
/// Raw domain handle the schema is registered against.
domain: u64,
/// Raw schema id returned by NVTX.
schema_id: u64,
/// Raw schema descriptor bytes, captured verbatim.
descriptor: Vec<u8>,
},
/// Register a payload enum (`nvtxPayloadEnumRegister`).
EnumRegister {
/// Raw domain handle the enum is registered against.
domain: u64,
/// Raw enum id returned by NVTX.
enum_id: u64,
/// Raw enum descriptor bytes, captured verbatim.
descriptor: Vec<u8>,
},
/// A binary payload blob attached to an event (`nvtxPayloadData_t`).
BinaryPayload {
/// Raw schema id the blob conforms to.
schema_id: u64,
/// Raw payload bytes, captured verbatim (decoded in a later phase).
bytes: Vec<u8>,
},
}
Loading