feat(observability): emit guardrail findings as span events on ETW DTO path#260
Open
nikhilNava wants to merge 1 commit into
Open
feat(observability): emit guardrail findings as span events on ETW DTO path#260nikhilNava wants to merge 1 commit into
nikhilNava wants to merge 1 commit into
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR brings the ETW DTO logging path for apply_guardrail into parity with the Activity span export path by allowing guardrail findings to be carried through DTOs and emitted as OTLP-style span events in the formatted ETW JSON payload.
Changes:
- Extended
IA365EtwLogger.LogApplyGuardrail/A365EtwLogger.LogApplyGuardrailwith an optionalfindingsparameter and forwarded it into DTO construction. - Added a generic
Eventscarrier to DTO base data, mapped findings into OTLP-style event dictionaries inApplyGuardrailDataBuilder, and emitted theEventsarray fromExportFormatter.FormatLogDatawhen present. - Added focused unit/integration tests (including a cross-path structural consistency test vs. the Activity path) plus a design spec documenting the intended schema.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Tests/Microsoft.Agents.A365.Observability.Runtime.Tests/Etw/EtwLoggerTests.cs | Verifies ETW end-to-end JSON output includes Events for findings and omits it when absent. |
| src/Tests/Microsoft.Agents.A365.Observability.Runtime.Tests/DTOs/Builders/ApplyGuardrailDataBuilderTests.cs | Validates findings → event mapping shape, conditional attribute inclusion, and value types. |
| src/Tests/Microsoft.Agents.A365.Observability.Runtime.Tests/DTOs/BaseDataTests.cs | Confirms BaseData.Events defaults empty and only serializes when populated. |
| src/Tests/Microsoft.Agents.A365.Observability.Runtime.Tests/Common/ExportFormatterEventsTests.cs | Ensures FormatLogData emits/omits Events correctly and enforces DTO-vs-Activity event structural parity. |
| src/Observability/Runtime/Etw/IA365EtwLogger.cs | Adds optional findings parameter to the public ETW logger interface contract. |
| src/Observability/Runtime/Etw/A365EtwLogger.cs | Accepts and forwards findings into the DTO builder for apply_guardrail. |
| src/Observability/Runtime/DTOs/Builders/BaseDataBuilder.cs | Adds a DTO-side ToUnixNanos helper to timestamp DTO-emitted events consistently with the Activity path. |
| src/Observability/Runtime/DTOs/Builders/ApplyGuardrailDataBuilder.cs | Maps GuardrailFinding instances into OTLP-style event dictionaries attached to the DTO. |
| src/Observability/Runtime/DTOs/BaseData.cs | Introduces the Events carrier and conditionally includes it in ToDictionary(). |
| src/Observability/Runtime/Common/ExportFormatter.cs | Emits Events in FormatLogData payload when present (null omitted by serializer). |
| docs/superpowers/specs/2026-06-26-etw-guardrail-findings-design.md | Documents the problem, goals, event schema, and test strategy for anti-drift parity. |
…O path The ETW DTO logging path (A365EtwLogger.LogApplyGuardrail -> ApplyGuardrailDataBuilder -> BaseData -> ExportFormatter.FormatLogData) previously dropped guardrail findings entirely, so they were invisible to downstream consumers despite being emitted on the Activity span path. Add an optional findings parameter that flows through to a generic Events carrier on BaseData and is emitted by FormatLogData. The event JSON is pinned to match the Activity path's finding events exactly (same event name, attribute keys, value types), enforced by a cross-path consistency test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ec9814d to
57bdd81
Compare
threddy
approved these changes
Jun 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Guardrail findings were dropped entirely on the ETW DTO logging path (
A365EtwLogger.LogApplyGuardrail→ApplyGuardrailDataBuilder→BaseData.ToDictionary→EtwLogProcessor→ExportFormatter.FormatLogData→LogJson). Unlike the Activity span path (which emits findings viaApplyGuardrailScope.RecordFinding→MapEvents), this path had no findings parameter, no events carrier, andFormatLogDataemitted noeventsfield — so findings logged through it were invisible to downstream consumers.This change brings the DTO path to parity, mirroring the prior
etw-span-statuswork.Changes
Scoped to the ETW DTO path — no new types in
Runtime/Common, Activity path untouched.IA365EtwLogger/A365EtwLogger.LogApplyGuardrail: optionalIEnumerable<GuardrailFinding>? findingsparameter (backward compatible).ApplyGuardrailDataBuilder: maps each finding to an event dictionary (timeUnixNano/name/attributes), mirroringRecordFinding's keys, value types, and conditional inclusion.BaseData: genericEventscarrier;ToDictionary()emits"Events"only when non-empty.BaseDataBuilder:ToUnixNanoshelper (DTO-local).ExportFormatter.FormatLogData: emits theEventsarray (omitted when absent).Event structure parity
The emitted event JSON is pinned to match the Activity path's finding events exactly (event name
microsoft.security.finding, samemicrosoft.security.*attribute keys, preserveddouble/string[]value types). A cross-path consistency test runs one finding through both paths and asserts the event objects are structurally equal (ignoringtimeUnixNano), preventing drift.Testing
ApplyGuardrailDataBuilderTests,ExportFormatterEventsTests(incl. cross-path consistency),BaseDataevents tests, ETW end-to-endLogApplyGuardrailfindings tests.dotnet formatclean.Notes
A365EtwLogger.csdiff includes pre-commit-hook whitespace cleanup on untouchedLog*methods; the substantive change is thefindingsparameter.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com