Skip to content

chore: add telemetry sending - #408

Merged
mckornfield merged 12 commits into
mainfrom
nemo-telemetry-pt2/mck
May 13, 2026
Merged

chore: add telemetry sending #408
mckornfield merged 12 commits into
mainfrom
nemo-telemetry-pt2/mck

Conversation

@mckornfield

@mckornfield mckornfield commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Pre-Review Checklist

Ensure that the following pass:

  • make format && make check or via prek validation.
  • make test passes locally
  • make test-e2e passes locally
  • make test-ci-container passes locally (recommended)
  • GPU CI status check passes -- comment /sync on this PR to trigger a run (auto-triggers on ready-for-review)

Pre-Merge Checklist

  • New or updated tests for any fix or new behavior
  • Updated documentation for new features and behaviors, including docstrings for API docs.

Other Notes

Copilot AI review requested due to automatic review settings April 15, 2026 19:48
@mckornfield
mckornfield requested review from a team as code owners April 15, 2026 19:48

Copilot AI 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.

Pull request overview

Adds a new telemetry subsystem and wires it into the Safe Synthesizer SDK pipeline so runs can enqueue/send anonymized, bucketed event metrics.

Changes:

  • Introduces src/nemo_safe_synthesizer/telemetry.py with event schemas, bucketing helpers, payload builder, and an async telemetry handler with retry/DLQ behavior.
  • Adds unit tests for telemetry helpers, payload formatting, and handler send/retry behavior.
  • Emits telemetry from SafeSynthesizer lifecycle (completed/canceled/error) and adds httpx as a dependency.

Reviewed changes

Copilot reviewed 4 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/nemo_safe_synthesizer/telemetry.py New telemetry event models + handler (batching/sending/retry) and payload construction.
tests/telemetry/test_telemetry.py New unit tests covering bucketing, event serialization, payload structure, and send/retry logic.
src/nemo_safe_synthesizer/sdk/library_builder.py Emits a telemetry event from SDK execution paths and tracks idempotent emission.
src/nemo_safe_synthesizer/evaluation/assets/text/multi_modal_tooltips.py Minor whitespace cleanup in tooltip text.
pyproject.toml Adds httpx dependency required by telemetry sender.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +83
Used to avoid transmitting exact record counts in telemetry.
"""

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

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

bucket_records() treats n <= 0 as the lowest bucket (e.g., 0 -> '1-100'), which is misleading and can happen for empty DataFrames. Consider handling non-positive values explicitly (e.g., return 'undefined' or a 0 bucket) before the first if n <= 100: branch.

Suggested change
Used to avoid transmitting exact record counts in telemetry.
"""
Used to avoid transmitting exact record counts in telemetry.
Non-positive counts are reported as undefined.
"""
if n <= 0:
return "undefined"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we don't run if there are too few records. might want to make the lower bucket the preflight threshold.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

do we not have any way to run for under 200? I thought you could if you set holdout to 0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

With the validation checks now, we hard crash on <200 rows. Not sure if that's in a constant we could (or would want to) import here.

I guess we'll get an error event back if someone runs with 150 records, so would be tidier to have that all fall under the same 1-200 bucket (or 1-199, not sure on a >= or > check) where we should see 100% errors. And then the 201-1000 bucket wouldn't ever have the <200 row error. Instead of 1-100 being all errors and 101-1000 being a mix of known error when <200 but success otherwise.

Comment thread src/nemo_safe_synthesizer/telemetry.py
Comment thread src/nemo_safe_synthesizer/telemetry.py
Comment on lines 528 to 532
report=self.evaluator.report,
generate_results=self.generator.gen_results,
)
_emit_nss_telemetry(self, TaskStatusEnum.COMPLETED)
return self

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

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

Telemetry is emitted as COMPLETED at the end of evaluate(). In run(), this happens before save_results(), so if saving results fails you’ll still have already emitted a completed event and the later error handler won’t emit due to _telemetry_emitted. Consider emitting the final COMPLETED status after save_results() in run() (and only emitting from evaluate() when evaluate() is called standalone), or adjust the idempotence logic so failures after evaluation can be reported accurately.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

worth double checking

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

moved these around for CLI and SDK

Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py Outdated
Comment thread src/nemo_safe_synthesizer/telemetry.py Outdated
Comment on lines +52 to +59
_deployment_type_raw = os.getenv("NEMO_DEPLOYMENT_TYPE", "sdk").lower()
try:
DEPLOYMENT_TYPE = DeploymentTypeEnum(_deployment_type_raw)
except ValueError:
valid_values = [e.value for e in DeploymentTypeEnum]
raise ValueError(
f"Invalid NEMO_DEPLOYMENT_TYPE: {_deployment_type_raw!r}. Must be one of: {valid_values}"
) from None

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

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

DEPLOYMENT_TYPE is validated at import time and raises ValueError for an unexpected NEMO_DEPLOYMENT_TYPE. That can prevent importing the whole library even when telemetry is disabled/best-effort. Consider defaulting to DeploymentTypeEnum.UNDEFINED (and optionally logging) instead of raising during module import.

Copilot uses AI. Check for mistakes.
Comment thread src/nemo_safe_synthesizer/telemetry.py Outdated
Comment thread src/nemo_safe_synthesizer/telemetry.py
Comment thread tests/telemetry/test_telemetry.py Fixed
Comment thread tests/telemetry/test_telemetry.py Fixed
Comment thread src/nemo_safe_synthesizer/telemetry.py Fixed
Comment thread src/nemo_safe_synthesizer/telemetry.py Fixed
Copilot AI review requested due to automatic review settings May 1, 2026 13:49
@mckornfield
mckornfield force-pushed the nemo-telemetry-pt2/mck branch from 6fc651e to a1cc23c Compare May 1, 2026 13:49

Copilot AI 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.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/nemo_safe_synthesizer/telemetry.py Outdated
Comment thread src/nemo_safe_synthesizer/telemetry.py
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py Outdated
Comment thread README.md Outdated
Comment thread src/nemo_safe_synthesizer/telemetry.py Outdated
@mckornfield
mckornfield force-pushed the nemo-telemetry-pt2/mck branch from a1cc23c to c23bf05 Compare May 4, 2026 18:25
@codecov

codecov Bot commented May 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.45777% with 13 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/nemo_safe_synthesizer/sdk/library_builder.py 83.63% 9 Missing ⚠️
src/nemo_safe_synthesizer/cli/run.py 90.00% 2 Missing ⚠️
src/nemo_safe_synthesizer/telemetry.py 95.12% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Signed-off-by: Matt Kornfield <mkornfield@nvidia.com>
Signed-off-by: mkornfield <mkornfield@nvidia.com>
Signed-off-by: mkornfield <mkornfield@nvidia.com>
@mckornfield
mckornfield force-pushed the nemo-telemetry-pt2/mck branch from c23bf05 to ac308c5 Compare May 7, 2026 17:33
Signed-off-by: mkornfield <mkornfield@nvidia.com>
Comment thread tests/smoke/test_telemetry_smoke.py Outdated
@@ -0,0 +1,58 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I can also delete this hehe

Comment thread README.md Outdated

@binaryaaron binaryaaron left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

thanks, let's make this a top-level config object so it's more easily managed and piped with everything else.

need to update the user guide/docs to note the flag as well.

Comment thread src/nemo_safe_synthesizer/cli/run.py Outdated
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py Outdated
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py
Comment on lines 528 to 532
report=self.evaluator.report,
generate_results=self.generator.gen_results,
)
_emit_nss_telemetry(self, TaskStatusEnum.COMPLETED)
return self

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

worth double checking

Comment thread src/nemo_safe_synthesizer/generation/processors.py
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py Outdated
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py Outdated
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py Outdated
Comment thread tests/cli/test_run.py Outdated
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py Outdated
Comment thread README.md Outdated
Comment thread README.md
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py
@kendrickb-nvidia

Copy link
Copy Markdown
Collaborator

Are we detecting/tracking CLI vs SDK usage? That was in the doc list last I saw.

If so, maybe that's the way to track internal slurm usage. Use an env var to add a suffix so it would show up as cli_nvidia_slurm or something?

Signed-off-by: mkornfield <mkornfield@nvidia.com>
Comment thread tests/telemetry/test_telemetry.py Dismissed
Comment thread src/nemo_safe_synthesizer/cli/run.py Outdated
Comment on lines +82 to +83
Used to avoid transmitting exact record counts in telemetry.
"""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we don't run if there are too few records. might want to make the lower bucket the preflight threshold.

Comment on lines 528 to 532
report=self.evaluator.report,
generate_results=self.generator.gen_results,
)
_emit_nss_telemetry(self, TaskStatusEnum.COMPLETED)
return self

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Comment thread tests/cli/test_run.py Outdated
Comment thread README.md
Comment thread README.md Outdated
Signed-off-by: mkornfield <mkornfield@nvidia.com>
@mckornfield
mckornfield requested a review from binaryaaron May 9, 2026 05:22
Signed-off-by: mkornfield <mkornfield@nvidia.com>
Signed-off-by: mkornfield <mkornfield@nvidia.com>
Signed-off-by: mkornfield <mkornfield@nvidia.com>
Comment thread script/slurm/slurm_srun.sh Outdated
Comment thread src/nemo_safe_synthesizer/sdk/config_builder.py Outdated
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py
Comment thread src/nemo_safe_synthesizer/sdk/library_builder.py
Comment thread README.md
Signed-off-by: mkornfield <mkornfield@nvidia.com>

@kendrickb-nvidia kendrickb-nvidia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few small items, but looks ready.

Comment thread .github/workflows/ci-checks.yml
Comment thread script/slurm/env_variables.sh Outdated
Comment thread src/nemo_safe_synthesizer/telemetry.py Outdated
Comment thread src/nemo_safe_synthesizer/telemetry.py Outdated
Signed-off-by: mkornfield <mkornfield@nvidia.com>
Signed-off-by: mkornfield <mkornfield@nvidia.com>
@mckornfield
mckornfield merged commit dc0e9b3 into main May 13, 2026
19 checks passed
@mckornfield
mckornfield deleted the nemo-telemetry-pt2/mck branch May 13, 2026 21:17
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.

Add opt out telemetry to understand library usage

5 participants