feat(cli): flow-debug logs column and --show-logs
This commit is contained in:
@@ -302,4 +302,80 @@ public class FlowDebugCommandsTests
|
||||
Assert.Equal(JsonValueKind.Null, rows[1].GetProperty("lifecycle").ValueKind);
|
||||
Assert.Equal(JsonValueKind.Null, rows[1].GetProperty("correlation").ValueKind);
|
||||
}
|
||||
|
||||
/// <summary>Builds a run whose script step carries two <c>ScriptLog</c> rows and fails with an exception detail (step-logs plan 2026-09-09, Task 14).</summary>
|
||||
private static string StepLogsPayload(out DateTime log1Time, out DateTime log2Time)
|
||||
{
|
||||
var root = Guid.NewGuid();
|
||||
var child = Guid.NewGuid();
|
||||
var t0 = new DateTime(2026, 9, 9, 10, 0, 0, 0, DateTimeKind.Utc);
|
||||
log1Time = t0.AddMilliseconds(30);
|
||||
log2Time = t0.AddMilliseconds(31);
|
||||
var events = new List<AuditEvent>
|
||||
{
|
||||
ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.RouteCall, AuditStatus.Delivered,
|
||||
occurredAtUtc: t0, target: "DelmiaSim01.ProcessRecipeDownload", executionId: root, durationMs: 100,
|
||||
extra: new ScriptTraceExtra { ChildExecutionId = child }.ToJson()),
|
||||
ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.ScriptRun, AuditStatus.Failed,
|
||||
occurredAtUtc: t0.AddMilliseconds(10), target: "ProcessRecipeDownload", executionId: child, parentExecutionId: root,
|
||||
sourceSiteId: "site-a", sourceInstanceId: "DelmiaSim01", sourceScript: "ProcessRecipeDownload", durationMs: 50,
|
||||
errorMessage: "boom", errorDetail: "System.InvalidOperationException: boom\n at X\n at Y\n at Z"),
|
||||
ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.ScriptLog, AuditStatus.Delivered,
|
||||
occurredAtUtc: log1Time, target: "ProcessRecipeDownload", executionId: child,
|
||||
requestSummary: "hello", extra: new ScriptTraceExtra { LogLevel = "warn", LogSource = "script", Seq = 1 }.ToJson()),
|
||||
ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.ScriptLog, AuditStatus.Delivered,
|
||||
occurredAtUtc: log2Time, target: "ProcessRecipeDownload", executionId: child,
|
||||
requestSummary: "world", extra: new ScriptTraceExtra { LogLevel = "warn", LogSource = "script", Seq = 2 }.ToJson()),
|
||||
};
|
||||
|
||||
var result = new FlowDebugRunResult(root, true, null, null, events, false, new DateTimeOffset(t0), new DateTimeOffset(t0.AddSeconds(1)));
|
||||
return JsonSerializer.Serialize(result, CamelCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Projection_LogsColumn_CountsAttachedLogLines()
|
||||
{
|
||||
var projected = FlowDebugTableProjection.ProjectEvents(StepLogsPayload(out _, out _));
|
||||
|
||||
using var doc = JsonDocument.Parse(projected);
|
||||
var rows = doc.RootElement.EnumerateArray().ToList();
|
||||
Assert.Equal(2, rows.Count); // RouteCall + ScriptRun — no note rows without --show-logs
|
||||
|
||||
Assert.Equal(0, rows[0].GetProperty("logs").GetInt32());
|
||||
Assert.Equal(2, rows[1].GetProperty("logs").GetInt32());
|
||||
Assert.All(rows, r => Assert.False(r.TryGetProperty("note", out _)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Projection_ShowLogsTrue_PrintsIndentedLogLinesAndExceptionDetail_UnderTheStepRow()
|
||||
{
|
||||
var json = StepLogsPayload(out var log1Time, out var log2Time);
|
||||
var projected = FlowDebugTableProjection.ProjectEvents(json, showLogs: true);
|
||||
|
||||
using var doc = JsonDocument.Parse(projected);
|
||||
var rows = doc.RootElement.EnumerateArray().ToList();
|
||||
|
||||
// RouteCall, ScriptRun, 2 log lines, 3 exception-detail lines (capped at 3 of the 4 available).
|
||||
Assert.Equal(7, rows.Count);
|
||||
|
||||
var expectedLog1 = $" {log1Time:HH:mm:ss.fff} WARN script hello";
|
||||
var expectedLog2 = $" {log2Time:HH:mm:ss.fff} WARN script world";
|
||||
Assert.Equal(expectedLog1, rows[2].GetProperty("note").GetString());
|
||||
Assert.Equal(expectedLog2, rows[3].GetProperty("note").GetString());
|
||||
|
||||
Assert.Equal(" exception: System.InvalidOperationException: boom", rows[4].GetProperty("note").GetString());
|
||||
Assert.Equal(" " + " at X", rows[5].GetProperty("note").GetString());
|
||||
Assert.Equal(" " + " at Y", rows[6].GetProperty("note").GetString());
|
||||
|
||||
Assert.DoesNotContain("at Z", projected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Projection_ShowLogsFalse_OmitsLogAndExceptionDetailLines()
|
||||
{
|
||||
var projected = FlowDebugTableProjection.ProjectEvents(StepLogsPayload(out _, out _), showLogs: false);
|
||||
|
||||
Assert.DoesNotContain("WARN", projected);
|
||||
Assert.DoesNotContain("exception:", projected);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user