feat(auditlog): inbound audit rows carry ExecutionId
This commit is contained in:
@@ -145,17 +145,21 @@ public sealed class AuditWriteMiddleware
|
||||
OccurredAtUtc = DateTime.UtcNow,
|
||||
Channel = AuditChannel.ApiInbound,
|
||||
Kind = kind,
|
||||
// Audit Log #23: a fresh per-request correlation id so the
|
||||
// Audit Log #23: a fresh per-request execution id so the
|
||||
// inbound row carries a request identifier (closes the design
|
||||
// gap that inbound rows should be correlatable).
|
||||
//
|
||||
// This id is intentionally request-local: it is NOT bridged to
|
||||
// RouteHelper's routed-call correlation id or to
|
||||
// HttpContext.TraceIdentifier. Threading an inbound request's
|
||||
// correlation id through to the routed script execution (so an
|
||||
// execution id through to the routed script execution (so an
|
||||
// inbound call and the outbound API/DB rows it triggers share
|
||||
// one id) is a deliberate future follow-up, out of scope here.
|
||||
CorrelationId = Guid.NewGuid(),
|
||||
ExecutionId = Guid.NewGuid(),
|
||||
// CorrelationId is purely the per-operation-lifecycle id; an
|
||||
// inbound request is a one-shot from the audit row's
|
||||
// perspective with no multi-row operation to correlate.
|
||||
CorrelationId = null,
|
||||
Actor = actor,
|
||||
Target = methodName,
|
||||
Status = status,
|
||||
|
||||
@@ -351,12 +351,14 @@ public class AuditWriteMiddlewareTests
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Correlation id — Audit Log #23: each inbound row carries a fresh
|
||||
// per-request correlation id so inbound rows are correlatable.
|
||||
// Execution id — Audit Log #23: each inbound row carries a fresh
|
||||
// per-request execution id so inbound rows are correlatable. The inbound
|
||||
// row's CorrelationId stays null — CorrelationId is purely the
|
||||
// per-operation-lifecycle id and an inbound request is a one-shot.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public async Task InboundRow_CarriesNonNull_CorrelationId()
|
||||
public async Task InboundRow_CarriesNonNull_ExecutionId_And_NullCorrelationId()
|
||||
{
|
||||
var writer = new RecordingAuditWriter();
|
||||
var ctx = BuildContext();
|
||||
@@ -369,12 +371,15 @@ public class AuditWriteMiddlewareTests
|
||||
await mw.InvokeAsync(ctx);
|
||||
|
||||
var evt = Assert.Single(writer.Events);
|
||||
Assert.NotNull(evt.CorrelationId);
|
||||
Assert.NotEqual(Guid.Empty, evt.CorrelationId!.Value);
|
||||
Assert.NotNull(evt.ExecutionId);
|
||||
Assert.NotEqual(Guid.Empty, evt.ExecutionId!.Value);
|
||||
// CorrelationId is the per-operation-lifecycle id; an inbound request
|
||||
// is a one-shot with no multi-row operation to correlate.
|
||||
Assert.Null(evt.CorrelationId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SeparateRequests_GetDistinct_CorrelationIds()
|
||||
public async Task SeparateRequests_GetDistinct_ExecutionIds()
|
||||
{
|
||||
var writer = new RecordingAuditWriter();
|
||||
var mw = CreateMiddleware(hc =>
|
||||
@@ -387,7 +392,7 @@ public class AuditWriteMiddlewareTests
|
||||
await mw.InvokeAsync(BuildContext());
|
||||
|
||||
Assert.Equal(2, writer.Events.Count);
|
||||
Assert.NotEqual(writer.Events[0].CorrelationId, writer.Events[1].CorrelationId);
|
||||
Assert.NotEqual(writer.Events[0].ExecutionId, writer.Events[1].ExecutionId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user