Skip to content

Feat: finetuningoptions validation telemetry - #6286

Open
rsareddy0329 wants to merge 5 commits into
aws:masterfrom
rsareddy0329:feat/finetuningoptions-validation-telemetry
Open

rsareddy0329 wants to merge 5 commits into
aws:masterfrom
rsareddy0329:feat/finetuningoptions-validation-telemetry

Conversation

@rsareddy0329

@rsareddy0329 rsareddy0329 commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Issue #, if available:

  • Instrument FineTuningOptions validation failures.

Description of changes:
Instruments FineTuningOptions.setattr so client-side hyperparameter validation failures are captured in the SDK dev-experience logs, enabling detection/measurement of this failure class:

  • setting an option name that isn't a valid/overridable hyperparameter (AttributeError), and
  • setting a value outside its spec — type/range/enum (ValueError).

Emission is failure-only via sagemaker.core.telemetry helper _emit_failure_telemetry: a single MODEL_CUSTOMIZATION FAILURE event is sent on the failure path, success path would not be captured as it records as multiple for one trainer call(per number of overridable params in recipe). The helper also adds the TelemetryOptOut config, mirrors the decorator's env/platform payload fields.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Roja Reddy Sareddy and others added 2 commits September 16, 2026 23:30
Instrument FineTuningOptions.__setattr__ so client-side hyperparameter
validation failures are captured in the SDK dev-experience logs, enabling
detection and measurement of this class of failure:

- setting an option name that is not a valid/overridable hyperparameter
  (raises AttributeError), and
- setting a value outside its spec (type/range/enum; raises ValueError).

Emission is failure-only: a single MODEL_CUSTOMIZATION FAILURE event is
sent on the failure path, and nothing is emitted on successful sets,
internal attribute sets, or construction, so no telemetry noise is added
to the happy path. The emit is best-effort and never masks or replaces
the user-facing validation error.

Add unit tests covering both failure paths, the no-emit happy paths, and
that a telemetry backend error still lets the validation error propagate.
@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown

Claude finished @rsareddy0329's task in 1m 24s —— View job


Code Review: FineTuningOptions validation telemetry

  • Read PR diff and changed files
  • Verify telemetry imports & signatures against sagemaker-core
  • Analyze correctness, security/privacy, performance, tests
  • Post review

Note: the inline-comment tool isn't available in this run, so findings are consolidated below with file/line references.


The change is well-scoped and the mechanics are correct: the new imports (_send_telemetry_request, _classify_error, _get_default_sagemaker_session, STATUS_TO_CODE, FEATURE_TO_CODE, SDK_VERSION, Status) all resolve, and the positional args passed to _send_telemetry_request(status, feature_list, session, failure_reason, failure_type, extra_info) line up correctly. The best-effort try/except wrapper and the "re-raise after emit" flow correctly guarantee telemetry never masks the user-facing validation error, and the tests cover that. Two substantive points:

🔴 Telemetry opt-out is not honored on this new path

common.py:109-125_emit_validation_failure calls _send_telemetry_request directly, without checking the TelemetryOptOut config flag. Every other emit site in this codebase gates on it: the _telemetry_emitter decorator resolves telemetry_opt_out_flag via resolve_value_from_config(..., config_path=TELEMETRY_OPT_OUT_PATH, ...) and only sends if not telemetry_opt_out_flag (see telemetry_logging.py:316-324, 398, 412).

As written, a user who has explicitly opted out of telemetry will still have these validation-failure events emitted. That's a privacy/compliance regression and is inconsistent with the rest of the module. Please resolve the opt-out flag (using the resolved session) and early-return when it is set, e.g.:

session = _get_default_sagemaker_session()
if not session:
    return
if resolve_value_from_config(
    direct_input=None,
    config_path=TELEMETRY_OPT_OUT_PATH,
    default_value=False,
    sagemaker_session=session,
):
    return

A unit test asserting mock_send.assert_not_called() when opt-out is set would lock this in.

🟡 extra string omits the standard env/platform fields

common.py:113-117 — the decorator's extra includes &x-env=<py>, &x-sys=<os>, &x-platform=<studio> (telemetry_logging.py:365-371). This new payload includes only func_name, x-sdkVersion, and x-errorCategory. Not a bug, but if these events are meant to be analyzed alongside the decorator-emitted ones, the missing platform dimensions will make them harder to slice consistently. Consider reusing the same fields for parity.

Minor

  • common.py:126 — the # noqa: E722 comment is slightly off: E722 flags bare except:, but this is except Exception: (which isn't E722). The rest of the module uses # pylint: disable=W0703 for the same intent; matching that would be more accurate.
  • Every validation failure creates a fresh boto3.Session() + Session(...) via _get_default_sagemaker_session() and spawns a daemon thread that makes an STS get_caller_identity() call. This is off the happy path and infrequent, so it's acceptable — just flagging that a caller looping over many invalid sets would incur repeated STS calls.

Overall: the approach and tests are solid; the opt-out gap is the one item I'd consider blocking before merge.
· feat/finetuningoptions-validation-telemetry

Move the failure-only telemetry emit out of FineTuningOptions and into the
core telemetry module as a reusable _emit_failure_telemetry(feature, func_name,
exc, sagemaker_session=None) helper. Unlike the @_telemetry_emitter decorator,
which emits on success and failure for every call, this emits a single FAILURE
event only when a caller explicitly hits a failure -- so it adds no happy-path
telemetry or per-call overhead. It is best-effort and never raises.

FineTuningOptions.__setattr__ now calls the shared helper on its two validation
failure paths (invalid option name, out-of-spec value) instead of carrying its
own emit plumbing, which shrinks the common.py change to a single import and two
call sites. Add unit tests for the helper in the core telemetry suite and update
the common.py tests to assert the helper is invoked on failures only.
@rsareddy0329
rsareddy0329 marked this pull request as ready for review September 18, 2026 16:54
@rsareddy0329 rsareddy0329 changed the title Feat/finetuningoptions validation telemetry Feat: finetuningoptions validation telemetry Sep 18, 2026
@github-actions

github-actions Bot commented Sep 18, 2026

Copy link
Copy Markdown

Claude finished @rsareddy0329's task in 58s —— View job


Code Review: FineTuningOptions validation telemetry

  • Read PR diff and changed files
  • Verify telemetry helper against sagemaker-core (imports, opt-out handling, signatures)
  • Analyze correctness, security/privacy, tests
  • Post review

Note: the inline-comment tool isn't available in this run, so findings are consolidated below with file/line references.


The change is well-scoped and mechanically correct. The new _emit_failure_telemetry helper resolves against sagemaker-core cleanly: the positional args passed to _send_telemetry_request(status, feature_list, session, failure_reason, failure_type, extra_info) line up, str(feature) matches the decorator's FEATURE_TO_CODE[str(feature)] convention, and the best-effort try/except plus the "emit then re-raise" flow in common.py correctly guarantee telemetry never masks the user-facing validation error. Tests cover the happy path, the three failure kinds, the no-session case, the provided-session case, and backend-error swallowing. One blocking issue:

🔴 Telemetry opt-out is not honored on this new path

telemetry_logging.py:497-515_emit_failure_telemetry calls _send_telemetry_request without checking the TelemetryOptOut config flag. Every other emit site gates on it: the decorator resolves telemetry_opt_out_flag via resolve_value_from_config(..., config_path=TELEMETRY_OPT_OUT_PATH, ...) and only sends if not telemetry_opt_out_flag (telemetry_logging.py:316-324, 398, 412).

As written, a user who has explicitly opted out of telemetry will still have these validation-failure events emitted — a privacy/compliance regression and inconsistent with the rest of the module. Both resolve_value_from_config and TELEMETRY_OPT_OUT_PATH are already imported at module level (lines 42-43), so the fix is small:

session = sagemaker_session or _get_default_sagemaker_session()
if not session:
    return
if resolve_value_from_config(
    direct_input=None,
    config_path=TELEMETRY_OPT_OUT_PATH,
    default_value=False,
    sagemaker_session=session,
):
    return

A unit test asserting mock_send.assert_not_called() when opt-out is set would lock this in. This is the one item I'd consider blocking before merge.

🟡 extra string omits the standard env/platform fields

telemetry_logging.py:501-505 — the decorator's extra also carries &x-env=<py>, &x-sys=<os>, and &x-platform=<studio> (telemetry_logging.py:365-371); this payload has only func_name, x-sdkVersion, and x-errorCategory. Not a bug, but if these events are analyzed alongside the decorator-emitted ones, the missing platform dimensions make them harder to slice consistently. Consider reusing the same fields for parity.

Minor

  • telemetry_logging.py:474feature: str is annotated as str, but every caller passes a Feature enum (and str(feature) is applied internally). Typing it Feature would be more accurate; cosmetic only.
  • Every validation failure resolves a default session (_get_default_sagemaker_session()), which builds a boto3.Session() and spawns a daemon thread doing an STS get_caller_identity(). This is off the happy path and infrequent, so acceptable — just flagging that a caller looping over many invalid sets would incur repeated STS calls.

Overall: solid approach and tests; the opt-out gap is the only thing I'd want addressed before merge.

jam-jee
jam-jee previously approved these changes Sep 18, 2026
@jam-jee

jam-jee commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

nit: can you add details to PR description.

Gate _emit_failure_telemetry on the TelemetryOptOut config flag (via
resolve_value_from_config), matching the @_telemetry_emitter decorator, so a
user who has opted out of telemetry does not have validation-failure events
emitted. Also include the standard env/platform dimensions (x-env, x-sys,
x-platform) in the payload for parity with decorator-emitted events, so the two
can be sliced consistently.

Add a unit test asserting no event is sent when opt-out is set.
@github-actions

github-actions Bot commented Sep 18, 2026

Copy link
Copy Markdown

Claude finished @rsareddy0329's task in 1m 41s —— View job


Code Review: FineTuningOptions validation telemetry

  • Read PR diff and changed files
  • Verify telemetry helper against sagemaker-core (imports, opt-out, signatures)
  • Analyze correctness, security/privacy, tests
  • Post review

Note: the inline-comment tool isn't available in this run, so findings are consolidated below with file/line references.


This revision resolves the blocking issue from the earlier reviews. _emit_failure_telemetry now honors the TelemetryOptOut config flag (telemetry_logging.py:39-45) and mirrors the decorator's env/platform dimensions (x-env, x-sys, x-platform) in the extra string (telemetry_logging.py:48-55). I verified every symbol used resolves in sagemaker-core: resolve_value_from_config / TELEMETRY_OPT_OUT_PATH (imported lines 42-43), SDK_VERSION / process_studio_metadata_file (line 50), PYTHON_VERSION / OS_NAME_VERSION (lines 56-59), STATUS_TO_CODE / FEATURE_TO_CODE (lines 87-104), _classify_error (line 129), and _get_default_sagemaker_session (line 633). The positional args to _send_telemetry_request(status, feature_list, session, failure_reason, failure_type, extra_info) line up correctly, and the best-effort try/except plus emit-then-raise flow in common.py guarantees telemetry never masks the caller's exception. Tests cover opt-out, no-session, provided-session, backend-error swallowing, and the three failure kinds — good coverage.

A few non-blocking observations:

🟡 Cross-field length validation raises but doesn't emit telemetry

common.py:47-81validate_length_constraints() raises ValueError for out-of-range max_prompt_length + max_response_length and dataset_max_len, but does not call _emit_failure_telemetry. Given this PR's goal is to capture invalid-input failures for FineTuningOptions, this is a coverage gap: per-field validation failures (via __setattr__) are recorded, but this cross-field validation failure — arguably the more interesting one, since a per-field max can't express it — is silent. If the omission is intentional, fine; otherwise consider wrapping the raises here too.

🟡 Failure events omit the NOVA/OSS sub-feature dimension

telemetry_logging.py:57-58 — the payload sends only [FEATURE_TO_CODE[str(feature)]]. The @_telemetry_emitter decorator, for MODEL_CUSTOMIZATION, additionally appends MODEL_CUSTOMIZATION_NOVA / MODEL_CUSTOMIZATION_OSS based on _is_nova_model_for_telemetry() (telemetry_logging.py:333-344). These failure events therefore can't be sliced by NOVA vs OSS alongside the decorator-emitted ones. FineTuningOptions has no model instance to introspect at this point, so this may be unavoidable here — just flagging the inconsistency for whoever analyzes the data.

Minor

  • telemetry_logging.py:475feature: str is annotated as str, but every caller passes a Feature enum (and str(feature) is applied internally). Typing it Feature would be more accurate. Cosmetic.
  • common.py:99-105 / 113-116 — the error path now runs synchronously in the caller's thread through _get_default_sagemaker_session() (builds a boto3.Session() + STS get_caller_identity()) and resolve_value_from_config before the async send. It's an infrequent error path so acceptable, but a caller looping over many invalid sets and catching the exceptions would incur repeated STS/session-resolution work on each failure.

Also, per @jam-jee's note: the PR description is currently empty — worth filling in a short summary of the change and its motivation.

Overall: solid, well-tested, and the earlier blocking concern is addressed. The remaining items are optional.

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.

2 participants