Skip to content

fix: harden ATOF HTTP endpoint export#295

Merged
rapids-bot[bot] merged 2 commits into
NVIDIA:mainfrom
bbednarski9:bbednarski/atof-http-endpoint-field-policy
Jun 24, 2026
Merged

fix: harden ATOF HTTP endpoint export#295
rapids-bot[bot] merged 2 commits into
NVIDIA:mainfrom
bbednarski9:bbednarski/atof-http-endpoint-field-policy

Conversation

@bbednarski9

@bbednarski9 bbednarski9 commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Overview

Adds an endpoint-local field-name policy for ATOF streaming exporters and hardens HTTP endpoint delivery failure handling.

  • 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 field_name_policy = "preserve" | "replace_dots" to ATOF endpoint config, defaulting to preserve so canonical ATOF JSON remains unchanged unless configured.
  • Applies replace_dots recursively to endpoint payload JSON object keys for HTTP POST, WebSocket, and NDJSON endpoint transports while keeping local JSONL file output canonical.
  • Handles field-name collisions deterministically so canonical dotted keys win their underscore-projected name and existing underscore keys receive a numeric suffix.
  • Installs the rustls crypto provider before ATOF endpoint workers create HTTP clients.
  • Preserves endpoint config access in the NDJSON worker after spawning the upload task.
  • Logs bounded non-2xx HTTP response bodies so rejected endpoint posts are diagnosable.
  • Exposes the new option through plugin config and Rust, Python, Node, and Go binding surfaces.

Where should the reviewer start?

Start with crates/core/src/observability/atof.rs for the endpoint payload transformation, HTTP error logging, and runtime robustness fixes. Then review crates/core/src/observability/plugin_component.rs for config parsing and validation.

Validation run:

  • cargo test -p nemo-relay --features atof-streaming observability::atof::tests
  • cargo test -p nemo-relay --features atof-streaming observability::plugin_component::tests
  • uv run pytest python/tests/test_observability_plugin.py::TestObservabilityConfigHelpers::test_atof_endpoint_config_serializes_streaming_fields python/tests/test_types.py::TestAtofExporterType::test_config_defaults_mutation_and_repr
  • node --test --test-name-pattern="serializes ATOF streaming endpoints" tests/observability_plugin_tests.mjs
  • GOCACHE=/private/tmp/nemo-relay-atof-http-field-policy/.tmp/go-build-cache go test -run 'Test(NewAtofExporterConfigDefaults|ObservabilityConfigHelpers)$' ./...
  • uv run ruff check python/nemo_relay/observability.py python/tests/test_observability_plugin.py python/tests/test_types.py
  • git diff --check

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

  • Relates to: none

Summary by CodeRabbit

  • New Features
    • Added field_name_policy for ATOF streaming endpoints (preserve default, or replace_dots to rewrite JSON object keys by replacing . with _, including nested structures).
  • Bug Fixes
    • Improved streaming payload handling to generate the correct transformed event JSON, and enhanced HTTP/NDJSON/WebSocket error logging (with optional response-body truncation).
  • Tests
    • Expanded unit, integration-style, and cross-language (Node/Python/Go) coverage for policy parsing, validation, serialization, and transformation behavior.

Adds an endpoint-local field_name_policy option for ATOF streaming exporters. The default preserves canonical ATOF JSON, while replace_dots recursively rewrites dotted JSON object keys to underscores for HTTP receivers that reject dotted field names.

This also fixes ATOF HTTP streaming robustness by installing the rustls crypto provider before endpoint workers create HTTP clients, preserving the endpoint config in the NDJSON worker after spawning the upload task, and logging bounded non-2xx response bodies so rejected events are diagnosable.

Exposes the new option through plugin config and Rust, Python, Node, and Go bindings, with tests for validation, serialization, recursive key rewriting, and collision handling.

Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
@bbednarski9 bbednarski9 requested a review from a team as a code owner June 23, 2026 22:54
@github-actions github-actions Bot added size:M PR is medium Bug issue describes bug; PR fixes bug 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 labels Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

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: de851ba2-2d36-4818-bf66-44fd7edbb424

📥 Commits

Reviewing files that changed from the base of the PR and between ffe92a2 and 41d2980.

📒 Files selected for processing (6)
  • crates/core/tests/unit/observability/atof_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/node/tests/atof_tests.mjs
  • go/nemo_relay/atof_test.go
  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_types.py
📜 Recent review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (29)
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/atof_test.go
  • go/nemo_relay/observability_plugin_test.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/atof_test.go
  • go/nemo_relay/observability_plugin_test.go
{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:

  • go/nemo_relay/atof_test.go
  • crates/node/tests/atof_tests.mjs
  • go/nemo_relay/observability_plugin_test.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/atof_test.go
  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_types.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/unit/observability/atof_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/atof_test.go
  • go/nemo_relay/observability_plugin_test.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/atof_test.go
  • go/nemo_relay/observability_plugin_test.go
**/*.{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:

  • go/nemo_relay/atof_test.go
  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_types.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/unit/observability/atof_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:

  • go/nemo_relay/atof_test.go
  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_types.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/unit/observability/atof_tests.rs
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
  wasm/       # wasm-bindgen WebAssembly binding and JS wrappers
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
third_party/  # P...

Files:

  • go/nemo_relay/atof_test.go
  • crates/node/tests/atof_tests.mjs
  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_types.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/unit/observability/atof_tests.rs
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/atof_test.go
  • go/nemo_relay/observability_plugin_test.go
{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:

  • go/nemo_relay/atof_test.go
  • crates/node/tests/atof_tests.mjs
  • go/nemo_relay/observability_plugin_test.go
  • python/tests/test_types.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/unit/observability/atof_tests.rs
{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/tests/atof_tests.mjs
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/tests/atof_tests.mjs
**/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_types.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/tests/test_types.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/tests/test_types.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_types.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_types.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/tests/test_types.py
**/*.{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:

  • python/tests/test_types.py
**/*.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/core/tests/unit/observability/plugin_component_tests.rs
  • 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/plugin_component_tests.rs
  • 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/plugin_component_tests.rs
  • 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/plugin_component_tests.rs
  • 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/plugin_component_tests.rs
  • 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

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/tests/unit/observability/plugin_component_tests.rs
  • 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/plugin_component_tests.rs
  • crates/core/tests/unit/observability/atof_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/core/tests/unit/observability/plugin_component_tests.rs
  • 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/plugin_component_tests.rs
  • crates/core/tests/unit/observability/atof_tests.rs
🔇 Additional comments (6)
crates/core/tests/unit/observability/atof_tests.rs (1)

423-435: LGTM!

Also applies to: 437-458

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

180-186: LGTM!

Also applies to: 538-553, 567-579

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

41-48: LGTM!

go/nemo_relay/atof_test.go (1)

43-49: LGTM!

go/nemo_relay/observability_plugin_test.go (1)

89-95: LGTM!

python/tests/test_types.py (1)

485-497: LGTM!


Walkthrough

Adds AtofEndpointFieldNamePolicy (Preserve/ReplaceDots) to the ATOF streaming endpoint configuration. ReplaceDots recursively rewrites JSON object keys (replacing dots with underscores, resolving collisions) before sending via HTTP POST, WebSocket, or NDJSON paths. The field is threaded through the Rust core, plugin component validation, Node.js, Python, and Go binding surfaces with matching tests and stubs.

Changes

AtofEndpointFieldNamePolicy end-to-end

Layer / File(s) Summary
Policy enum and AtofEndpointConfig contract
crates/core/src/observability/atof.rs
Introduces AtofEndpointFieldNamePolicy with Preserve/ReplaceDots variants, parse/as_str helpers, adds field_name_policy field to AtofEndpointConfig, and exposes a with_field_name_policy builder method.
Streaming worker: policy application and error logging
crates/core/src/observability/atof.rs
Adds endpoint_event_json called by HTTP POST, WebSocket, and NDJSON send paths; implements recursive key rewriting with deterministic collision suffixing for ReplaceDots; adds log_http_error/truncate_log_body helpers (1024-char cap); calls install_rustls_crypto_provider() at worker startup.
Plugin component: config building and validation
crates/core/src/observability/plugin_component.rs
Extends AtofEndpointSectionConfig with field_name_policy: String, wires it into build_atof_endpoint_config via parse, validates allowed values in validate_atof_endpoint_values emitting a policy diagnostic on invalid input, and adds default_atof_endpoint_field_name_policy().
Language bindings: Node, Python, Go
crates/node/src/api/mod.rs, crates/node/observability.d.ts, crates/python/src/py_types/observability.rs, python/nemo_relay/observability.py, python/nemo_relay/observability.pyi, python/nemo_relay/_native.pyi, go/nemo_relay/nemo_relay.go, go/nemo_relay/observability_plugin.go
Surfaces field_name_policy on the public config object in each binding layer: Node.js (optional string field + .d.ts), Python (PyAtofEndpointConfig struct, to_rust_config with PyValueError on invalid, constructor default "preserve", dataclass + to_dict, stubs), Go (new AtofEndpointFieldNamePolicy type + constants, struct fields with JSON tags).
Tests across all layers
crates/core/tests/unit/observability/atof_tests.rs, crates/core/tests/unit/observability/plugin_component_tests.rs, crates/node/tests/observability_plugin_tests.mjs, crates/node/tests/atof_tests.mjs, go/nemo_relay/atof_test.go, go/nemo_relay/observability_plugin_test.go, python/tests/test_observability_plugin.py, python/tests/test_types.py
Validates ReplaceDots recursive key rewriting, parse/as_str round-trips, plugin validation diagnostics for invalid policy values, config builder mapping, and binding-level serialization/validation in all language test suites.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Caller (any binding)
  participant PluginComponent as plugin_component
  participant AtofWorker as AtofEndpointWorker
  participant EEJ as endpoint_event_json
  participant Transport as HTTP/WS/NDJSON

  Caller->>PluginComponent: field_name_policy = "replace_dots"
  PluginComponent->>PluginComponent: AtofEndpointFieldNamePolicy::parse("replace_dots")
  PluginComponent->>AtofWorker: AtofEndpointConfig { field_name_policy: ReplaceDots }
  AtofWorker->>AtofWorker: install_rustls_crypto_provider()
  loop per event
    AtofWorker->>EEJ: raw_json + ReplaceDots policy
    EEJ->>EEJ: recursively rewrite dot-keys → underscore-keys
    EEJ-->>AtofWorker: transformed JSON
    AtofWorker->>Transport: send transformed payload
    Transport-->>AtofWorker: HTTP response
    alt non-2xx
      AtofWorker->>AtofWorker: log_http_error(status, truncated_body)
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title follows Conventional Commits format with 'fix' type and clearly describes the main change of hardening ATOF HTTP endpoint export within the 72-character limit.
Description check ✅ Passed Description includes all required sections: Overview with checkboxes, comprehensive Details of changes, Where to start with file pointers, and Related Issues statement.
Docstring Coverage ✅ Passed Docstring coverage is 83.67% 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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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

@github-actions

Copy link
Copy Markdown

Comment thread crates/core/src/observability/atof.rs
@bbednarski9 bbednarski9 added this to the 0.5 milestone Jun 23, 2026
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
@bbednarski9

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot rapids-bot Bot merged commit c57182d into NVIDIA:main Jun 24, 2026
71 of 72 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug issue describes bug; PR fixes bug 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:M PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants