docs(audit): ScadaBridge C7 review — correct 'six persisted' computed-col wording (5 persisted + IngestedAtUtc non-persisted) + stale perf iteration comment

This commit is contained in:
Joseph Doherty
2026-06-02 15:08:49 -04:00
parent 635461c0fd
commit bc0e5bfd37
4 changed files with 14 additions and 10 deletions
@@ -8,8 +8,11 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Configurations;
/// <summary>
/// Maps the C5 (Task 2.5) <see cref="AuditLogRow"/> persistence shape to the central
/// <c>dbo.AuditLog</c> table: the 10 canonical <c>ZB.MOM.WW.Audit.AuditEvent</c> columns
/// (writable) plus six read-only, server-side <b>persisted computed columns</b> derived
/// from <c>DetailsJson</c> via <c>JSON_VALUE</c>. The computed-column SQL and the index
/// (writable) plus six read-only, server-side <b>computed columns</b> derived from
/// <c>DetailsJson</c> via <c>JSON_VALUE</c> — five PERSISTED (<c>Kind</c>/<c>Status</c>/
/// <c>SourceSiteId</c>/<c>ExecutionId</c>/<c>ParentExecutionId</c>) plus <c>IngestedAtUtc</c>
/// which is computed but NOT persisted (SQL Server forbids PERSISTED on its non-deterministic
/// <c>SWITCHOFFSET</c> cast). The computed-column SQL and the index
/// set here mirror the <c>CollapseAuditLogToCanonical</c> migration's
/// <c>dbo.AuditLog_v2</c> DDL byte-for-byte — keep them in sync.
/// </summary>
@@ -46,8 +46,8 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations
protected override void Up(MigrationBuilder migrationBuilder)
{
// 1) Create dbo.AuditLog_v2 on the PRESERVED partition scheme. Ten
// canonical columns first (ordinal-stable), then the six persisted
// computed columns. The clustered PK is composite {EventId,
// canonical columns first (ordinal-stable), then the six computed
// columns (five PERSISTED + IngestedAtUtc non-persisted). The clustered PK is composite {EventId,
// OccurredAtUtc} (partition-aligned). The computed-column expressions
// here are the single source of truth that AuditLogEntityTypeConfiguration
// and SwitchOutPartitionAsync's staging table must mirror exactly.
@@ -6,7 +6,7 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations;
/// <summary>
/// C7 (Task 2.5) data-projection tests for the <c>CollapseAuditLogToCanonical</c>
/// migration. Verifies that the canonical column layout and six persisted computed
/// migration. Verifies that the canonical column layout and the five persisted computed
/// columns are correct after the migration has been applied:
/// <list type="bullet">
/// <item><c>Action</c> = "{Channel}.{Kind}" per <see cref="AuditFieldBuilders.BuildAction"/>.</item>
@@ -17,9 +17,10 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations;
/// else → <c>Success</c>.</item>
/// <item>Empty <c>Actor</c> maps to NULL.</item>
/// <item><c>DetailsJson</c> produced by <see cref="AuditDetailsCodec.Serialize"/> round-trips
/// correctly and the six persisted computed columns (<c>Kind</c>, <c>Status</c>,
/// correctly and the five persisted computed columns (<c>Kind</c>, <c>Status</c>,
/// <c>SourceSiteId</c>, <c>ExecutionId</c>, <c>ParentExecutionId</c>) resolve to
/// the expected values via <c>JSON_VALUE</c>.</item>
/// the expected values via <c>JSON_VALUE</c> (<c>IngestedAtUtc</c> is computed but
/// non-persisted, so not asserted here).</item>
/// </list>
/// </summary>
/// <remarks>
@@ -30,7 +31,7 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations;
/// seed, apply C5), the tests insert rows directly into the canonical table using
/// <see cref="AuditDetailsCodec"/> — the same codec the migration's
/// <c>FOR JSON PATH, WITHOUT_ARRAY_WRAPPER</c> projection is designed to match —
/// and verify that all six computed columns resolve correctly from <c>DetailsJson</c>.
/// and verify that the five persisted computed columns resolve correctly from <c>DetailsJson</c>.
/// This validates the computed-column SQL expressions that are the source of truth
/// for both the live table and <c>SwitchOutPartitionAsync</c>'s staging table.
/// </para>
@@ -29,8 +29,8 @@ namespace ZB.MOM.WW.ScadaBridge.PerformanceTests.AuditLog;
/// <b>C7 re-baseline rationale.</b> The canonical <see cref="ScadaBridgeAuditRedactor"/>
/// works on a single <c>DetailsJson</c> bag (one JSON parse + one re-serialize per
/// call) whereas the former typed-field approach touched many individual
/// fields. Empirical measurements on Apple M-series (2026-06-02, Release build,
/// 5 000 iterations after 500 warm-ups):
/// fields. Empirical calibration measurements on Apple M-series (2026-06-02, Release build;
/// the CI test itself runs MeasureIterations=2 000 after WarmupIterations=200):
/// <list type="bullet">
/// <item>4 KB body (2 body-regex matches + truncation): p50 ≈ 13 µs, p95 ≈ 14 µs.</item>
/// <item>Small DetailsJson, no redactors (JSON parse + rewrite only): p50 ≈ 1.5 µs, p95 ≈ 2 µs.</item>