Skip to content

feat: add streaming ATOF exporter#173

Open
omkarmehta06 wants to merge 9 commits into
NVIDIA:mainfrom
omkarmehta06:feat/streaming-atof-exporter
Open

feat: add streaming ATOF exporter#173
omkarmehta06 wants to merge 9 commits into
NVIDIA:mainfrom
omkarmehta06:feat/streaming-atof-exporter

Conversation

@omkarmehta06
Copy link
Copy Markdown

@omkarmehta06 omkarmehta06 commented May 28, 2026

Overview

Add a streaming ATOF exporter for NeMo Relay so downstream tools can consume canonical ATOF JSONL from a separate local process in real time.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

  • Adds a TCP-backed AtofStreamingExporter that connects to a local receiver and writes newline-delimited canonical ATOF events.
  • Keeps socket writes out of the subscriber callback path with a bounded queue and dedicated writer thread.
  • Preserves Relay as the recorder/exporter owner; downstream cockpit/viewer tools can consume the stream without introducing a second trace contract.
  • Adds focused tests for canonical delivery, connection/config errors, stored stream errors, shutdown/flush behavior, and future-events-only runtime registration.
  • Updates the ATOF observability docs with streaming exporter and receiver examples.

Where should the reviewer start?

Start with crates/core/src/observability/atof.rs, especially AtofStreamingExporter, then review the socket receiver tests in crates/core/tests/unit/observability/atof_tests.rs.

Validation

Already run locally:

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test -p nemo-relay streaming_exporter -- --test-threads=1
  • just test-rust
  • just docs

Breaking changes

None intended. This adds a new exporter surface and docs; existing ATOF/ATIF file export behavior remains unchanged.

Related Issues

Summary by CodeRabbit

Release Notes

  • New Features

    • Streaming observability exporter: Send agent trajectory events over TCP in real-time with bounded queue buffering and event dropping on overflow
  • Documentation

    • Added architecture and design documentation for streaming observability
    • Extended configuration guides with examples for Rust, Node.js, Python, and Go SDKs
  • Tests

    • Added test coverage for streaming observability configuration and runtime behavior

Review Change Stack

Signed-off-by: Omkar Mehta <omehta@nvidia.com>
@omkarmehta06 omkarmehta06 requested a review from a team as a code owner May 28, 2026 20:44
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 28, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added size:L PR is large lang:rust PR changes/introduces Rust code labels May 28, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: ed2000cd-77d1-4ce7-9cf3-c057315839ed

📥 Commits

Reviewing files that changed from the base of the PR and between d1c35fc and f1d01e0.

📒 Files selected for processing (15)
  • crates/cli/src/plugins/editor_model.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/node/observability.d.ts
  • crates/node/observability.js
  • crates/node/tests/observability_plugin_tests.mjs
  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
  • go/nemo_relay/observability_plugin.go
  • go/nemo_relay/observability_plugin_test.go
  • python/nemo_relay/observability.py
  • python/nemo_relay/observability.pyi
  • python/tests/test_observability_plugin.py
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (46)
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Python native binding in crates/python/src/py_api/mod.rs with Python wrapper docstring in python/nemo_relay/<module>.py and type stubs in python/nemo_relay/*.pyi modules

Files:

  • python/nemo_relay/observability.pyi
  • python/nemo_relay/observability.py
python/nemo_relay/**/*

⚙️ CodeRabbit configuration file

python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/nemo_relay/observability.pyi
  • python/nemo_relay/observability.py
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/node/observability.d.ts
  • crates/node/observability.js
  • crates/node/tests/observability_plugin_tests.mjs
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/node/observability.d.ts
  • crates/node/observability.js
  • crates/node/tests/observability_plugin_tests.mjs
  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
**/*.{wasm,js,ts}{,x}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Files:

  • crates/node/observability.d.ts
  • crates/node/observability.js
crates/node/**/*.{js,ts,jsx,tsx,json}

📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)

Format changed Node files with npm run format --workspace=nemo-relay-node

Files:

  • crates/node/observability.d.ts
  • crates/node/observability.js
crates/node/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)

Use npm run check:docstrings --workspace=nemo-relay-node to validate public API docstring checks when surface docs changed

Files:

  • crates/node/observability.d.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run Node.js formatting with npm run format --workspace=nemo-relay-node

Include SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax

Files:

  • crates/node/observability.d.ts
  • crates/node/observability.js
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • crates/node/observability.d.ts
  • crates/cli/src/plugins/editor_model.rs
  • crates/node/observability.js
  • python/nemo_relay/observability.py
  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
  • python/tests/test_observability_plugin.py
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • crates/node/observability.d.ts
  • crates/cli/src/plugins/editor_model.rs
  • crates/node/observability.js
  • python/nemo_relay/observability.py
  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
  • python/tests/test_observability_plugin.py
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
crates/node/**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js public entry points include the main runtime package plus nemo-relay-node/typed, nemo-relay-node/plugin, and nemo-relay-node/adaptive.

Files:

  • crates/node/observability.d.ts
  • crates/node/observability.js
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/node/observability.d.ts
  • crates/node/observability.js
  • crates/node/tests/observability_plugin_tests.mjs
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/cli/src/plugins/editor_model.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
**/{Cargo.toml,**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/cli/src/plugins/editor_model.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
**/*.{h,hpp,c,cpp,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/cli/src/plugins/editor_model.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/cli/src/plugins/editor_model.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/cli/src/plugins/editor_model.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/node/tests/observability_plugin_tests.mjs
  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_observability_plugin.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
{docs/**,README.md,CONTRIBUTING.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
{docs/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
{docs/**,examples/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current

Files:

  • docs/observability-plugin/about.mdx
  • python/nemo_relay/observability.py
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • python/tests/test_observability_plugin.py
  • docs/observability-plugin/streaming-atof-design.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.

Files:

  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/atof.mdx
  • docs/observability-plugin/configuration.mdx
  • docs/observability-plugin/streaming-atof-design.mdx
python/nemo_relay/**/*.py

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Python identifiers (e.g., nemo_relay.tools.call)

Format changed Python wrapper and test files with uv run ruff format python

Python wrapper modules live under python/nemo_relay/; the native extension is built from crates/python with maturin.

Files:

  • python/nemo_relay/observability.py
{pyproject.toml,**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Python package names in pyproject.toml and import paths used throughout the codebase

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
**/*.{py,txt,toml,cfg,yaml,yml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Python package names and top-level module imports during coordinated rename operations

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
**/*.py

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.py: Run Python formatting with uv run ruff format python
Run Python testing with uv run pytest -k "<pattern>"

**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Run ty for Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code with uv run pre-commit run --all-files to enforce Ruff linting and formatting, and ty type checking

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
go/nemo_relay/**/*.go

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Go wrapper in go/nemo_relay/nemo_relay.go with doc comment and shorthand package if the capability belongs there

go/nemo_relay/**/*.go: Format changed Go packages with cd go/nemo_relay && go fmt ./...
Run Go tests with just test-go to build and test the NeMo Relay Go binding
Use just build-go when you want an explicit build-only pass or need the artifact for other work
Use just ci=true test-go when you need the CI-style coverage and JUnit path
On macOS, set DYLD_LIBRARY_PATH to the ../../target/release directory before running the raw go test command directly

Files:

  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
go/**/*.go

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use PascalCase naming convention for Go identifiers (e.g., nemo_relay.ToolCall)

Run Go formatting with cd go/nemo_relay && go fmt ./...

Files:

  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_observability_plugin.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
{go/nemo_relay/go.mod,go/**/*.go}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure Go module path in go/nemo_relay/go.mod matches import statements in Go source files

Files:

  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
**/*.go

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Go module paths and package paths during coordinated rename operations

**/*.go: Use gofmt for Go code formatting
Run go vet ./... for Go static analysis
Use Go PascalCase naming convention for Go identifiers
Include SPDX license header in all Go source files using double-slash comment syntax
Validate Go code with uv run pre-commit run --all-files to enforce gofmt formatting and go vet static analysis

Files:

  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
go/nemo_relay/**/*

⚙️ CodeRabbit configuration file

go/nemo_relay/**/*: Review Go binding changes for cgo memory ownership, race safety, callback cleanup, idiomatic exported APIs, and parity with Rust/FFI behavior.
Any API change should include focused Go tests and consider race-test behavior.

Files:

  • go/nemo_relay/observability_plugin_test.go
  • go/nemo_relay/observability_plugin.go
**/test_*.{py,py}

📄 CodeRabbit inference engine (.agents/skills/add-integration/SKILL.md)

Relevant integration tests or smoke coverage must exist for the integration path

Files:

  • python/tests/test_observability_plugin.py
python/**/*test*.py

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

python/**/*test*.py: Do not add @pytest.mark.asyncio to any test in Python test files
Do not add a -> None return type annotation to test functions
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock with the spec constructor argument when necessary, rather than defining a new class
Prefix mocked class names with mock, not fake
Prefer pytest fixtures over helper methods in Python tests
Prefer pytest.mark.parametrize over creating individual tests for different input types

Files:

  • python/tests/test_observability_plugin.py
python/**/{conftest.py,*test*.py}

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

When creating a fixture follow the pattern: @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) def <fixture_name>_fixture() -> <return_type>: and only specify the scope argument when the value is something other than "function"

Files:

  • python/tests/test_observability_plugin.py
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
crates/{core,adaptive}/**

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Files:

  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
🧠 Learnings (1)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • crates/node/observability.d.ts
🪛 LanguageTool
docs/observability-plugin/streaming-atof-design.mdx

[style] ~39-~39: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...cket, or multi-client fan-out server. - No replacement for ATIF, OpenTelemetry, or...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~40-~40: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...elemetry, or OpenInference exporters. - No durable replay, backfill, or local data...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~41-~41: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... replay, backfill, or local database. - No new PII redaction policy in this change...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~101-~101: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...alidation for missing stream address. - Unit test plugin initialization registers `a...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[grammar] ~111-~111: Ensure spelling is correct
Context: ... stats become a generic exporter health surface? - Should redaction hooks become configu...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~112-~112: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...me a generic exporter health surface? - Should redaction hooks become configurable bef...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🔇 Additional comments (24)
crates/cli/src/plugins/editor_model.rs (1)

36-38: LGTM!

Also applies to: 151-153

docs/observability-plugin/about.mdx (1)

24-25: LGTM!

Also applies to: 59-60, 90-91

docs/observability-plugin/atof.mdx (1)

267-269: LGTM!

docs/observability-plugin/configuration.mdx (1)

39-40: LGTM!

Also applies to: 49-50, 73-75, 137-138, 153-156, 215-218, 262-277

docs/observability-plugin/streaming-atof-design.mdx (1)

1-114: LGTM!

crates/core/src/observability/plugin_component.rs (6)

38-38: LGTM!


114-116: LGTM!

Also applies to: 136-136, 180-196


398-404: LGTM!

Also applies to: 444-449


622-652: LGTM!


1362-1362: LGTM!

Also applies to: 1379-1385, 1454-1467, 1589-1610


578-580: LGTM!

crates/core/tests/unit/observability/plugin_component_tests.rs (5)

26-66: LGTM!


117-127: LGTM!


222-222: LGTM!

Also applies to: 233-235, 252-252, 262-262


273-273: LGTM!

Also applies to: 282-282, 380-380, 448-448, 470-476, 481-481, 601-607


657-714: LGTM!

crates/node/observability.d.ts (1)

16-19: LGTM!

Also applies to: 61-61, 80-81

crates/node/observability.js (1)

35-46: LGTM!

Also applies to: 99-99

crates/node/tests/observability_plugin_tests.mjs (1)

24-24: LGTM!

Also applies to: 53-53, 58-62

go/nemo_relay/observability_plugin.go (1)

11-17: LGTM!

Also applies to: 28-32, 78-81

go/nemo_relay/observability_plugin_test.go (1)

34-37: LGTM!

Also applies to: 48-48, 56-58, 190-192, 201-201

python/nemo_relay/observability.py (1)

76-91: LGTM!

Also applies to: 201-201, 213-213, 244-244

python/nemo_relay/observability.pyi (1)

28-32: LGTM!

Also applies to: 77-77

python/tests/test_observability_plugin.py (1)

18-18: LGTM!

Also applies to: 32-32, 63-63, 70-71


Walkthrough

This PR adds TCP-backed streaming ATOF event export: a new AtofStreamingExporter with bounded queue and background writer thread, integrated into the Observability plugin with configuration validation, comprehensive socket-based testing, multi-language configuration helpers (Node/Go/Python), and detailed documentation covering architecture and usage.

Changes

Streaming ATOF Export via TCP

Layer / File(s) Summary
Stream error handling and TCP imports
crates/core/src/observability/atof.rs
TCP/threading imports and three new AtofExporterError variants: ConnectStream (connection failure with address), ConfigureStream (socket option failure with operation name and timeout), StoredStreamFailure (stored error message).
Core streaming exporter implementation
crates/core/src/observability/atof.rs
AtofStreamingExporter with AtofStreamingExporterConfig, AtofStreamingExporterStats; bounded mpsc::SyncSender queue, background writer thread on TcpStream; lifecycle API (new, connect, register, deregister, force_flush, shutdown, stats) with queue-overflow drop tracking and stored-error propagation.
JSONL serialization helpers
crates/core/src/observability/atof.rs
Extract serialize_event (event → JSON string), write_serialized_event (write JSONL line + newline + flush to generic Write), update write_event to reuse; add shared error storage for writer thread's last error.
Plugin configuration schema and editor mappings
crates/core/src/observability/plugin_component.rs
Add AtofStreamSectionConfig (enabled, optional address), extend ObservabilityConfig with atof_stream field, define editor config mappings for section and field display.
Plugin registration and validation
crates/core/src/observability/plugin_component.rs
Add register_atof_stream_exporter helper; conditionally register "atof_stream" subscriber when enabled; validate atof_stream in known-fields allowlist; add per-section field rules and validate_atof_stream_values to diagnose missing/empty address when enabled.
Streaming exporter socket tests
crates/core/tests/unit/observability/atof_tests.rs
Add AtofSocketSink and helpers (start_atof_socket_sink, start_atof_eof_sink) with timeout-based TCP accept and JSON line reading; test canonical JSONL writes, queue-full drops without poisoning, connect/configure errors, shutdown with stored failure, first-error preservation, and runtime registration stats.
Plugin integration and configuration tests
crates/core/tests/unit/observability/plugin_component_tests.rs
Add in-test TCP receiver; validate editor schema includes atof_stream with optional address; verify defaults and component representation; extend validation tests (disabled, unknown fields, policy handling); add initialization failure and end-to-end streaming test with event ordering and stats assertions.
Node.js configuration helper
crates/node/observability.d.ts, crates/node/observability.js, crates/node/tests/observability_plugin_tests.mjs
TypeScript AtofStreamConfig interface with optional enabled/address; extend Config interface; implement atofStreamConfig defaulting function; test defaults and validation diagnostics.
Go configuration support
go/nemo_relay/observability_plugin.go, go/nemo_relay/observability_plugin_test.go
ObservabilityAtofStreamConfig struct; extend ObservabilityConfig with AtofStream field; add NewObservabilityAtofStreamConfig constructor; test serialization, defaults, and validation diagnostics.
Python configuration support
python/nemo_relay/observability.py, python/nemo_relay/observability.pyi, python/tests/test_observability_plugin.py
AtofStreamConfig dataclass with to_dict(); extend ObservabilityConfig with optional atof_stream field; add type stubs; export and test defaults and validation.
Design and usage documentation
docs/observability-plugin/about.mdx, docs/observability-plugin/atof.mdx, docs/observability-plugin/configuration.mdx, docs/observability-plugin/streaming-atof-design.mdx
Add "Streaming API" section and Rust receiver example; add capability bullet and exporter selection link; add configuration examples (TOML, Node, Rust); add comprehensive design document covering configuration, architecture, runtime behavior, failure semantics, and validation plan.
Editor component boxed payloads
crates/cli/src/plugins/editor_model.rs
Box EditableComponent enum variant payloads for Observability, Adaptive, and NeMo Guardrails to reduce stack usage; update constructor and pattern matches.

🎯 4 (Complex) | ⏱️ ~45 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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.

Inline comments:
In `@crates/core/src/observability/atof.rs`:
- Around line 415-420: The exporter currently treats mpsc::TrySendError::Full as
a terminal error by calling store_stream_error(&state.last_error, ...) which
poisons the exporter; instead, in the match arm for
Err(mpsc::TrySendError::Full(_)) (around
sender.try_send(AtofStreamMessage::Event(value)) / AtofStreamMessage::Event), do
not call store_stream_error or mutate state.last_error: treat it as transient
backpressure by incrementing a transient-dropped counter (e.g.,
state.events_dropped or creating one), optionally log a debug/trace message, and
return/continue without setting last_error so future sends can succeed after the
queue drains. Ensure only genuine fatal errors (other TrySendError variants)
call store_stream_error and update state.last_error.

In `@crates/core/tests/unit/observability/atof_tests.rs`:
- Around line 127-129: The detached sink helpers start_atof_socket_sink and
start_atof_eof_sink spawn threads that can block forever on
TcpListener::accept() and BufReader reads (read_line/read_to_string), so change
them to enforce a bounded accept/read lifetime: make the listener nonblocking or
loop with a deadline using TEST_RECV_TIMEOUT, use TcpStream::set_read_timeout
(or set_read_timeout on accepted streams) before blocking reads, and
break/terminate the thread when the deadline elapses or when a shutdown signal
is received; ensure accepted sockets are closed on timeout so the helper thread
always returns instead of hanging CI.

In `@docs/observability-plugin/atof.mdx`:
- Around line 235-241: Add a short sentence to the AtofStreamingExporter docs
explaining the bounded queue backpressure behavior: state whether the
per-exporter bounded queue will block the producer, drop oldest/newest events,
or surface errors when the receiver cannot keep up, and describe any retry or
overflow policy (e.g., blocking until space, dropping with metric/log, or
returning errors) so users understand reliability/performance tradeoffs; place
this sentence in the paragraph that begins "Use `AtofStreamingExporter`..." and
reference the exporter name `AtofStreamingExporter` and "bounded queue" so
readers can correlate doc text with the implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 9fb0c8b1-4c78-4ab2-a8d7-e2664edc8f37

📥 Commits

Reviewing files that changed from the base of the PR and between a3c552b and 232c587.

📒 Files selected for processing (3)
  • crates/core/src/observability/atof.rs
  • crates/core/tests/unit/observability/atof_tests.rs
  • docs/observability-plugin/atof.mdx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (21)
{docs/**,README.md,CONTRIBUTING.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/atof.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/observability-plugin/atof.mdx
{docs/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/atof.mdx
{docs/**,examples/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/atof.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • docs/observability-plugin/atof.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current

Files:

  • docs/observability-plugin/atof.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/observability-plugin/atof.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/observability-plugin/atof.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/atof.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/atof.mdx
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.

Files:

  • docs/observability-plugin/atof.mdx
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Keep SPDX headers on Rust source files. The project is Apache-2.0.
Use snake_case for Rust binding naming conventions.
Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.
Preserve async behavior on the existing tokio-based model i...

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
**/{Cargo.toml,**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
**/*.{h,hpp,c,cpp,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
crates/{core,adaptive}/**

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/src/observability/atof.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
🔇 Additional comments (4)
docs/observability-plugin/atof.mdx (3)

6-7: LGTM!


267-280: LGTM!


253-255: ⚡ Quick win

Streaming exporter lifecycle example is already correct (no missing force_flush())

AtofStreamingExporter::shutdown() calls force_flush() internally, so deregister(...) -> shutdown() -> stats() already flushes buffered TCP writes. stats() is just a snapshot of counters/errors and is safe to read after shutdown().

crates/core/src/observability/atof.rs (1)

315-555: 🏗️ Heavy lift

Run the full CI test matrix for crates/core changes (use just test-all, not validate-change)

just test-all is the repo’s full Rust/Python/Go/Node/OpenClaw/WASM matrix (test-rust, test-python, test-go, test-node, test-openclaw, test-wasm). There is no validate-change task in the current justfile; run just test-all (or the repo’s equivalent command if it’s named differently elsewhere) before merging.

Comment thread crates/core/src/observability/atof.rs Outdated
Comment thread crates/core/tests/unit/observability/atof_tests.rs
Comment thread docs/observability-plugin/atof.mdx
@willkill07
Copy link
Copy Markdown
Member

/ok to test 232c587

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 28, 2026

@willkill07 willkill07 added this to the 0.4 milestone May 28, 2026
@willkill07 willkill07 changed the title Add streaming ATOF exporter feat: add streaming ATOF exporter May 28, 2026
@github-actions github-actions Bot added the Feature a new feature label May 28, 2026
@willkill07 willkill07 self-assigned this May 28, 2026
Signed-off-by: Omkar Mehta <omehta@nvidia.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@omkarmehta06
Copy link
Copy Markdown
Author

Current head is now e0835e5. CodeRabbit re-reviewed the update with 0 actionable comments; local validation passed cargo fmt, focused ATOF tests, just test-rust, docs-linkcheck, clippy, and diff-check. Could a vetter re-run validation (/ok to test) for this updated fork commit so the NVIDIA runner matrix can start?

@omkarmehta06
Copy link
Copy Markdown
Author

Additional local validation for current head e0835e5: I reran the full repo matrix with the repo-pinned Rust toolchain path first in PATH: PATH=/Users/omehta/.rustup/toolchains/1.93.0-aarch64-apple-darwin/bin:$PATH just test-all. It completed with exit 0 locally.\n\nNotes: local setup needed wasm-pack plus the wasm32-unknown-unknown target for Rust 1.93.0 before the WASM lane could run. npm still emitted the existing Node engine warning because this machine has Node v23.7.0 while the package asks for >=24, but the Node lane and the full matrix completed successfully. The test tooling generated transient package-lock drift, which I inspected and restored; the PR worktree is clean.

@willkill07
Copy link
Copy Markdown
Member

/ok to test e0835e5

Signed-off-by: Omkar Mehta <omehta@nvidia.com>
@omkarmehta06
Copy link
Copy Markdown
Author

Updated the PR head to 42ccba91ecb200d4d887c7674015a948e2ec5f4c to address the Windows-arm64 CI failure.

What changed: the test socket sink now keeps the receiver side alive until exporter shutdown/EOF instead of dropping immediately after the expected event count. That preserves the separate-process streaming behavior under test and avoids the Windows late-flush race that surfaced as os error 10053 in streaming_exporter_registers_with_runtime_events.

Local validation on the same tree passed:

  • cargo test -p nemo-relay streaming_exporter_registers_with_runtime_events
  • cargo test -p nemo-relay observability::atof
  • just test-rust
  • git diff --check

Could a maintainer please re-run validation for the new head when convenient?

@willkill07
Copy link
Copy Markdown
Member

/ok to test 42ccba9

@willkill07
Copy link
Copy Markdown
Member

You still have a CI failure: https://github.com/NVIDIA/NeMo-Relay/actions/runs/26613916449/job/78425763052

Additionally, Just having the exporter is one part. We need to expose this to the Observability Plugin... where multiple, named exporters can be defined in the plugin configuration file (and edited via nemo-relay plugins edit.

I would really appreciate a design document for this feature rather than jumping straight to an implementation.

Signed-off-by: Omkar Mehta <omehta@nvidia.com>
Signed-off-by: Omkar Mehta <omehta@nvidia.com>
Signed-off-by: Omkar Mehta <omehta@nvidia.com>
Signed-off-by: Omkar Mehta <omehta@nvidia.com>
Signed-off-by: Omkar Mehta <omehta@nvidia.com>
@omkarmehta06
Copy link
Copy Markdown
Author

Pushed an update on top of 42ccba9. It keeps the accepted test sockets blocking through shutdown and treats platform-specific TCP close/reset as expected stream termination, which should address the Windows-arm64 10053 failure.

Local validation:

  • cargo test -p nemo-relay observability::atof: 16 passed
  • just test-rust: passed

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@docs/observability-plugin/local-cockpit-viewer.mdx`:
- Around line 21-24: Update the four bullet questions in the
docs/observability-plugin/local-cockpit-viewer.mdx list to vary their sentence
openings: keep "What session or prompt is active?" as-is, change the second
"Which model, tool, file, skill, memory, or subagent drove the result?" to
retain meaning but consider rephrasing (e.g., "What model, tool, file, skill,
memory, or subagent drove the result?"), rewrite the third "Which token or cost
fields are observed, and which are unavailable?" to a contrastive form like "Are
token or cost fields observed, or are they unavailable?", and rephrase the
fourth "Which hook or provider limitation explains missing trace detail?" to a
"What" form such as "What hook or provider limitation explains missing trace
detail?" to avoid three consecutive "Which" openings while preserving intent and
clarity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 6283b078-1c76-48e2-94e9-a5f1fdb4c755

📥 Commits

Reviewing files that changed from the base of the PR and between 42ccba9 and d1c35fc.

📒 Files selected for processing (3)
  • crates/core/tests/unit/observability/atof_tests.rs
  • docs/observability-plugin/about.mdx
  • docs/observability-plugin/local-cockpit-viewer.mdx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (21)
{docs/**,README.md,CONTRIBUTING.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
{docs/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
{docs/**,examples/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.

Files:

  • docs/observability-plugin/local-cockpit-viewer.mdx
  • docs/observability-plugin/about.mdx
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Keep SPDX headers on Rust source files. The project is Apache-2.0.
Use snake_case for Rust binding naming conventions.
Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.
Preserve async behavior on the existing tokio-based model i...

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
**/{Cargo.toml,**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
**/*.{h,hpp,c,cpp,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
crates/{core,adaptive}/**

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/core/tests/unit/observability/atof_tests.rs
🪛 LanguageTool
docs/observability-plugin/local-cockpit-viewer.mdx

[style] ~24-~24: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... observed, and which are unavailable? - Which hook or provider limitation explains mi...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~89-~89: You have already used ‘right’ in nearby sentences. Consider using an alternative word to let your writing stand out and sound more polished.
Context: ... preserves lifecycle order. ATIF is the right shape for post-run trajectory analysis,...

(REP_RIGHT)

🔇 Additional comments (4)
crates/core/tests/unit/observability/atof_tests.rs (2)

16-17: LGTM!

Also applies to: 121-189, 214-223


336-347: LGTM!

Also applies to: 467-524

docs/observability-plugin/about.mdx (1)

92-93: LGTM!

docs/observability-plugin/local-cockpit-viewer.mdx (1)

1-235: Run docs link validation for docs/observability-plugin/local-cockpit-viewer.mdx
Link checking couldn’t be executed here because just isn’t available (just: command not found); run just docs-linkcheck to validate the new internal references.

Comment thread docs/observability-plugin/local-cockpit-viewer.mdx Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You misunderstood my request.

I need a design doc for this streaming ATOF support.

I don't want to conflate this PR (or documentation) with anything related to the local cockpit viewer. This file should not exist.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The standalone ATOF streaming exporter seems okay, but what about the updates to the Observability plugin shape requested as part of a prior review comment?

Signed-off-by: Omkar Mehta <omehta@nvidia.com>
@github-actions github-actions Bot added size:XL PR is extra large lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code and removed size:L PR is large labels May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature a new feature lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:XL PR is extra large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants