Skip to content

feat(health): add primary system UUID and static labels to telemetry#4041

Open
jingxiang-z wants to merge 6 commits into
NVIDIA:mainfrom
jingxiang-z:feat/primary-system-uuid-telemetry
Open

feat(health): add primary system UUID and static labels to telemetry#4041
jingxiang-z wants to merge 6 commits into
NVIDIA:mainfrom
jingxiang-z:feat/primary-system-uuid-telemetry

Conversation

@jingxiang-z

Copy link
Copy Markdown

Fleet Intelligence needs hardware-health telemetry to carry stable hardware
identity and deployment-specific context. This change adds an optional
BMC-derived system UUID label and user-defined labels for static endpoints.

For machine endpoints, hardware health discovers the primary Redfish
ComputerSystem UUID, preferring a system with BIOS metadata and falling back
to the first collection member. When available, the UUID is emitted as
system_uuid in Prometheus, system.uuid in OTLP resources, and through log
and health-event context. Telemetry collection continues without this optional
label when identity discovery is unavailable.

Static BMC endpoints can also define user-defined telemetry labels. Label names
use the Prometheus-compatible identifier shape, built-in identity labels are
reserved, values are bounded, and each endpoint supports at most 32 custom
labels.

Related issues

None.

Type of Change

  • Add - New feature or capability
  • Change - Changes in existing functionality
  • Fix - Bug fixes
  • Remove - Removed features or deprecated functionality
  • Internal - Internal changes (refactoring, tests, docs, etc.)

Breaking Changes

  • This PR contains breaking changes

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No testing required (docs, internal refactor, etc.)

cargo test -p carbide-health (410 passed)

Additional Notes

The system UUID is discovered from the BMC and cannot be overridden with a
user-defined label. This preserves upstream's optional machine_id behavior
for static deployments that do not use NICo.

@copy-pr-bot

copy-pr-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

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.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2730ee39-2f24-46f2-ac2d-41ade711fe3e

📥 Commits

Reviewing files that changed from the base of the PR and between bae7cd2 and 92457b9.

📒 Files selected for processing (2)
  • docs/architecture/health_aggregation.md
  • docs/operations/monitoring-health.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/architecture/health_aggregation.md
  • docs/operations/monitoring-health.md

Summary by CodeRabbit

  • New Features

    • Added support for custom telemetry labels on static BMC endpoints, including validation rules (key format, reserved-name rejection such as system_uuid, 32-label limit, and max label value size).
    • Enriched machine metadata with a BMC-derived primary system.uuid during discovery (best-effort when available).
    • Propagated endpoint labels and system.uuid through Prometheus, OTLP resource attributes, JSONL logs, and tracing. JSONL omits labels when empty.
  • Documentation

    • Updated example configuration and monitoring/telemetry mappings to reflect label and system.uuid export behavior.

Walkthrough

The health service adds validated static endpoint labels and optional machine system UUID metadata, resolves primary Redfish system identities during discovery, and exports the resulting metadata through Prometheus, OTLP, JSONL, and tracing sinks.

Changes

Health metadata propagation

Layer / File(s) Summary
Metadata contracts and endpoint construction
crates/health/Cargo.toml, crates/health/src/config.rs, crates/health/src/endpoint/*, crates/health/src/api_client.rs, docs/operations/monitoring-health.md
Static BMC endpoints accept validated custom labels, while endpoint and machine models carry labels and optional system UUID values.
Context and fixture propagation
crates/health/src/sink/events.rs, crates/health/benches/*, crates/health/src/collectors/*, crates/health/src/processor/*, crates/health/src/discovery/spawn.rs
Endpoint labels are copied into EventContext, and benchmark and test fixtures initialize the expanded metadata structures.
Primary system UUID discovery
crates/health/src/discovery/*
Discovery selects a primary Redfish ComputerSystem, attaches its UUID to machine endpoints, and performs bounded concurrent best-effort enrichment.
Telemetry and log exports
crates/health/src/otlp/convert.rs, crates/health/src/sink/prometheus.rs, crates/health/src/sink/log_file.rs, crates/health/src/sink/tracing.rs, docs/architecture/health_aggregation.md
Prometheus, OTLP, JSONL, and tracing outputs include endpoint labels and available system UUID metadata.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Discovery
  participant BMC
  participant EventContext
  participant TelemetrySinks
  Discovery->>BMC: Resolve primary ComputerSystem
  BMC-->>Discovery: Return system UUID
  Discovery->>EventContext: Attach system UUID and endpoint labels
  EventContext->>TelemetrySinks: Export metadata with events and metrics
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding primary system UUID support and static labels to telemetry.
Description check ✅ Passed The description matches the diff and objectives, covering system UUID discovery, telemetry emission, and static labels.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@jingxiang-z
jingxiang-z marked this pull request as ready for review July 23, 2026 20:36
@jingxiang-z
jingxiang-z requested review from a team and polarweasel as code owners July 23, 2026 20:36
@ajf

ajf commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

@yoks @akorobkov-nvda @kensimon

Seems like this'll come up again and again - since high cardinality destroys prometheus.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
crates/health/src/discovery/identity.rs (1)

104-149: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a table-driven selection test.

These tests all map system collections to a selected identity. Consolidate them into check_cases/value_scenarios! cases, including the empty collection case.

As per coding guidelines, “Use table-driven tests for functions mapping inputs to outputs or errors.”

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

In `@crates/health/src/discovery/identity.rs` around lines 104 - 149, Consolidate
the three tests for select_primary_system into a single table-driven test using
the project’s check_cases/value_scenarios! pattern. Include cases for preferring
the first BIOS-bearing system, falling back to the first member, and returning
None for an empty collection, while preserving the current expected identities
and UUIDs.

Source: Coding guidelines

crates/health/src/sink/events.rs (1)

63-74: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression coverage for the new context metadata.

The current tests only use an empty label map and system_uuid: None, so they do not verify that EventContext::from_endpoint copies labels or that system_uuid() returns a populated UUID. Add table-driven cases covering populated and absent values.

As per coding guidelines and path instructions, changed Rust behavior should have table-driven regression coverage, with particular attention to missing tests.

Also applies to: 96-101

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

In `@crates/health/src/sink/events.rs` around lines 63 - 74, Add table-driven
regression cases for EventContext::from_endpoint and system_uuid(), covering
both populated and absent labels and system UUID values. Assert that populated
endpoint labels are copied and populated UUIDs are returned, while preserving
expected behavior for empty or missing metadata; update the existing tests near
endpoint_key() and labels() coverage.

Sources: Coding guidelines, Path instructions

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

Inline comments:
In `@crates/health/src/config.rs`:
- Around line 315-359: Update the static BMC endpoint label validation in the
configuration validation method containing RESERVED_LABELS so arbitrary
per-endpoint label values cannot become metric attributes; restrict labels to an
explicitly bounded, low-cardinality set or reject labels intended to carry
unique identifiers such as asset, machine, or instance IDs. Preserve the
existing name, count, reserved-name, and byte-length checks while ensuring the
accepted configuration cannot create unbounded telemetry series in the endpoint
source flow.

---

Nitpick comments:
In `@crates/health/src/discovery/identity.rs`:
- Around line 104-149: Consolidate the three tests for select_primary_system
into a single table-driven test using the project’s check_cases/value_scenarios!
pattern. Include cases for preferring the first BIOS-bearing system, falling
back to the first member, and returning None for an empty collection, while
preserving the current expected identities and UUIDs.

In `@crates/health/src/sink/events.rs`:
- Around line 63-74: Add table-driven regression cases for
EventContext::from_endpoint and system_uuid(), covering both populated and
absent labels and system UUID values. Assert that populated endpoint labels are
copied and populated UUIDs are returned, while preserving expected behavior for
empty or missing metadata; update the existing tests near endpoint_key() and
labels() coverage.
🪄 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: CHILL

Plan: Enterprise

Run ID: ef8229a7-e811-4515-b577-c99716aa6209

📥 Commits

Reviewing files that changed from the base of the PR and between cfe6bd9 and 5d44a03.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (33)
  • crates/health/Cargo.toml
  • crates/health/benches/collector_pipeline.rs
  • crates/health/benches/processor_pipeline.rs
  • crates/health/benches/sink_pipeline.rs
  • crates/health/example/config.example.toml
  • crates/health/src/api_client.rs
  • crates/health/src/collectors/nvue/gnmi/on_change_processor.rs
  • crates/health/src/collectors/nvue/gnmi/sample_processor.rs
  • crates/health/src/collectors/nvue/rest/collector.rs
  • crates/health/src/config.rs
  • crates/health/src/discovery/identity.rs
  • crates/health/src/discovery/iteration.rs
  • crates/health/src/discovery/mod.rs
  • crates/health/src/discovery/spawn.rs
  • crates/health/src/endpoint/cluster.rs
  • crates/health/src/endpoint/mod.rs
  • crates/health/src/endpoint/model.rs
  • crates/health/src/endpoint/sources.rs
  • crates/health/src/otlp/convert.rs
  • crates/health/src/processor/health_report.rs
  • crates/health/src/processor/intrusion_events.rs
  • crates/health/src/processor/leak_events.rs
  • crates/health/src/processor/mod.rs
  • crates/health/src/processor/rack_leak.rs
  • crates/health/src/sink/events.rs
  • crates/health/src/sink/health_report.rs
  • crates/health/src/sink/log_file.rs
  • crates/health/src/sink/mod.rs
  • crates/health/src/sink/otlp.rs
  • crates/health/src/sink/prometheus.rs
  • crates/health/src/sink/tracing.rs
  • docs/architecture/health_aggregation.md
  • docs/operations/monitoring-health.md

Comment thread crates/health/src/config.rs
@yoks

yoks commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

@ajf this high cardinality data emited through non standart /telemetry endpoint and not scraped by default. In large clusters Prometheus endpoint is disabled and only OpenTelemetry one is exposed.

Comment thread crates/health/src/discovery/iteration.rs Outdated
Comment thread crates/health/src/discovery/identity.rs Outdated
Signed-off-by: Jingxiang Zhang <jingzhang@nvidia.com>
Signed-off-by: Jingxiang Zhang <jingzhang@nvidia.com>
Signed-off-by: Jingxiang Zhang <jingzhang@nvidia.com>
Signed-off-by: Jingxiang Zhang <jingzhang@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/health/src/discovery/identity.rs (1)

144-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep primary-system selection tests table-driven.

This adds another standalone input/output case; consolidate these cases into one table-driven test so selection rules remain easy to extend and compare.

As per coding guidelines, “Use table-driven tests for functions mapping inputs to outputs or errors.”

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

In `@crates/health/src/discovery/identity.rs` around lines 144 - 163, Consolidate
the standalone primary-system selection cases, including
primary_system_prefers_host_bios_over_auxiliary_uuid, into one table-driven test
for select_primary_system. Define named input/expected-output cases and iterate
over them, preserving each case’s selection and UUID assertions while making
future cases easy to add.

Source: Coding guidelines

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

Nitpick comments:
In `@crates/health/src/discovery/identity.rs`:
- Around line 144-163: Consolidate the standalone primary-system selection
cases, including primary_system_prefers_host_bios_over_auxiliary_uuid, into one
table-driven test for select_primary_system. Define named input/expected-output
cases and iterate over them, preserving each case’s selection and UUID
assertions while making future cases easy to add.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8610a4d1-2fb1-4e05-9461-7aeb99c64b4e

📥 Commits

Reviewing files that changed from the base of the PR and between 5d44a03 and 3b7773b.

📒 Files selected for processing (17)
  • crates/health/benches/collector_pipeline.rs
  • crates/health/benches/processor_pipeline.rs
  • crates/health/benches/sink_pipeline.rs
  • crates/health/src/api_client.rs
  • crates/health/src/discovery/identity.rs
  • crates/health/src/discovery/iteration.rs
  • crates/health/src/discovery/spawn.rs
  • crates/health/src/endpoint/mod.rs
  • crates/health/src/endpoint/model.rs
  • crates/health/src/endpoint/sources.rs
  • crates/health/src/otlp/convert.rs
  • crates/health/src/processor/health_report.rs
  • crates/health/src/sink/events.rs
  • crates/health/src/sink/health_report.rs
  • crates/health/src/sink/log_file.rs
  • crates/health/src/sink/mod.rs
  • crates/health/src/sink/prometheus.rs
🚧 Files skipped from review as they are similar to previous changes (11)
  • crates/health/benches/sink_pipeline.rs
  • crates/health/src/endpoint/mod.rs
  • crates/health/src/processor/health_report.rs
  • crates/health/src/discovery/spawn.rs
  • crates/health/benches/processor_pipeline.rs
  • crates/health/src/sink/health_report.rs
  • crates/health/src/sink/log_file.rs
  • crates/health/src/sink/events.rs
  • crates/health/src/sink/mod.rs
  • crates/health/src/sink/prometheus.rs
  • crates/health/src/otlp/convert.rs

Signed-off-by: Jingxiang Zhang <jingzhang@nvidia.com>
@jingxiang-z
jingxiang-z force-pushed the feat/primary-system-uuid-telemetry branch from 3b7773b to bae7cd2 Compare July 24, 2026 17:44
@jingxiang-z
jingxiang-z requested a review from yoks July 24, 2026 17:50
@yoks

yoks commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

/ok to test bae7cd2

@yoks
yoks enabled auto-merge (squash) July 24, 2026 18:36
@github-actions

Copy link
Copy Markdown

Comment thread docs/architecture/health_aggregation.md Outdated
Comment thread docs/architecture/health_aggregation.md Outdated
Comment thread docs/operations/monitoring-health.md Outdated
Co-authored-by: Alex Ball <awball@polarweasel.org>
Signed-off-by: Jingxiang Zhang <72907213+jingxiang-z@users.noreply.github.com>
auto-merge was automatically disabled July 24, 2026 19:33

Head branch was pushed to by a user without write access

@jingxiang-z
jingxiang-z requested a review from polarweasel July 24, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants