169 lines
6.6 KiB
C++
169 lines
6.6 KiB
C++
#include "HealthTelemetry.h"
|
|
|
|
#include <iostream>
|
|
|
|
namespace
|
|
{
|
|
int gFailures = 0;
|
|
|
|
void Expect(bool condition, const char* message)
|
|
{
|
|
if (condition)
|
|
return;
|
|
|
|
std::cerr << "FAIL: " << message << "\n";
|
|
++gFailures;
|
|
}
|
|
|
|
void TestRuntimeEventQueueMetrics()
|
|
{
|
|
HealthTelemetry telemetry;
|
|
telemetry.RecordRuntimeEventQueueMetrics("runtime-events", 3, 64, 2, 12.5);
|
|
|
|
const HealthTelemetry::RuntimeEventMetricsSnapshot metrics = telemetry.GetRuntimeEventMetricsSnapshot();
|
|
Expect(metrics.queue.queueName == "runtime-events", "queue metrics store queue name");
|
|
Expect(metrics.queue.depth == 3, "queue metrics store depth");
|
|
Expect(metrics.queue.capacity == 64, "queue metrics store capacity");
|
|
Expect(metrics.queue.droppedCount == 2, "queue metrics store dropped count");
|
|
Expect(metrics.queue.oldestEventAgeMilliseconds == 12.5, "queue metrics store oldest event age");
|
|
}
|
|
|
|
void TestRuntimeEventDispatchStats()
|
|
{
|
|
HealthTelemetry telemetry;
|
|
telemetry.RecordRuntimeEventDispatchStats(2, 5, 1, 0.75);
|
|
telemetry.RecordRuntimeEventDispatchStats(3, 6, 0, 0.25);
|
|
|
|
const HealthTelemetry::Snapshot snapshot = telemetry.GetSnapshot();
|
|
Expect(snapshot.runtimeEvents.dispatch.dispatchCallCount == 2, "dispatch stats count dispatch calls");
|
|
Expect(snapshot.runtimeEvents.dispatch.dispatchedEventCount == 5, "dispatch stats accumulate dispatched events");
|
|
Expect(snapshot.runtimeEvents.dispatch.handlerInvocationCount == 11, "dispatch stats accumulate handler invocations");
|
|
Expect(snapshot.runtimeEvents.dispatch.handlerFailureCount == 1, "dispatch stats accumulate handler failures");
|
|
Expect(snapshot.runtimeEvents.dispatch.lastDispatchDurationMilliseconds == 0.25, "dispatch stats store latest duration");
|
|
Expect(snapshot.runtimeEvents.dispatch.maxDispatchDurationMilliseconds == 0.75, "dispatch stats store max duration");
|
|
}
|
|
|
|
void TestRuntimeEventTryRecord()
|
|
{
|
|
HealthTelemetry telemetry;
|
|
Expect(telemetry.TryRecordRuntimeEventQueueMetrics("runtime-events", 1, 4, 0, -5.0), "try queue metrics succeeds when uncontended");
|
|
Expect(telemetry.TryRecordRuntimeEventDispatchStats(1, 2, 0, -1.0), "try dispatch stats succeeds when uncontended");
|
|
|
|
const HealthTelemetry::RuntimeEventMetricsSnapshot metrics = telemetry.GetRuntimeEventMetricsSnapshot();
|
|
Expect(metrics.queue.oldestEventAgeMilliseconds == 0.0, "queue age is clamped to non-negative values");
|
|
Expect(metrics.dispatch.lastDispatchDurationMilliseconds == 0.0, "dispatch duration is clamped to non-negative values");
|
|
}
|
|
|
|
void TestPersistenceWriteHealth()
|
|
{
|
|
HealthTelemetry telemetry;
|
|
telemetry.RecordPersistenceWriteResult(false, "runtime-state", "runtime/runtime_state.json", "UpdateLayerParameter",
|
|
"disk full", true);
|
|
|
|
HealthTelemetry::PersistenceSnapshot persistence = telemetry.GetPersistenceSnapshot();
|
|
Expect(persistence.writeFailureCount == 1, "persistence health counts write failures");
|
|
Expect(!persistence.lastWriteSucceeded, "persistence health records failed write state");
|
|
Expect(persistence.unsavedChanges, "persistence health reports unsaved changes after failure");
|
|
Expect(persistence.newerRequestPending, "persistence health records pending newer request");
|
|
Expect(persistence.lastTargetKind == "runtime-state", "persistence health records target kind");
|
|
Expect(persistence.lastReason == "UpdateLayerParameter", "persistence health records reason");
|
|
Expect(persistence.lastErrorMessage == "disk full", "persistence health records error message");
|
|
|
|
Expect(telemetry.TryRecordPersistenceWriteResult(true, "runtime-state", "runtime/runtime_state.json", "flush", "", false),
|
|
"try persistence health succeeds when uncontended");
|
|
persistence = telemetry.GetPersistenceSnapshot();
|
|
Expect(persistence.writeSuccessCount == 1, "persistence health counts write successes");
|
|
Expect(persistence.lastWriteSucceeded, "persistence health records successful write state");
|
|
Expect(!persistence.unsavedChanges, "persistence health clears unsaved changes after latest successful write with no pending request");
|
|
}
|
|
|
|
void TestBackendPlayoutHealth()
|
|
{
|
|
HealthTelemetry telemetry;
|
|
telemetry.RecordBackendPlayoutHealth(
|
|
"Degraded",
|
|
"Dropped",
|
|
1,
|
|
4,
|
|
12,
|
|
10,
|
|
2,
|
|
1,
|
|
8,
|
|
11,
|
|
3,
|
|
2,
|
|
2,
|
|
1,
|
|
2,
|
|
5,
|
|
3,
|
|
1,
|
|
true,
|
|
"Output underrun");
|
|
|
|
const HealthTelemetry::BackendPlayoutSnapshot playout = telemetry.GetBackendPlayoutSnapshot();
|
|
Expect(playout.lifecycleState == "Degraded", "backend playout health stores lifecycle state");
|
|
Expect(playout.completionResult == "Dropped", "backend playout health stores completion result");
|
|
Expect(playout.readyQueueDepth == 1, "backend playout health stores ready queue depth");
|
|
Expect(playout.readyQueueCapacity == 4, "backend playout health stores ready queue capacity");
|
|
Expect(playout.readyQueueDroppedCount == 2, "backend playout health stores queue dropped count");
|
|
Expect(playout.readyQueueUnderrunCount == 1, "backend playout health stores queue underrun count");
|
|
Expect(playout.completedFrameIndex == 8, "backend playout health stores completed index");
|
|
Expect(playout.scheduledFrameIndex == 11, "backend playout health stores scheduled index");
|
|
Expect(playout.measuredLagFrames == 2, "backend playout health stores measured lag");
|
|
Expect(playout.catchUpFrames == 2, "backend playout health stores catch-up frames");
|
|
Expect(playout.lateStreak == 1, "backend playout health stores late streak");
|
|
Expect(playout.dropStreak == 2, "backend playout health stores drop streak");
|
|
Expect(playout.lateFrameCount == 5, "backend playout health stores late frame count");
|
|
Expect(playout.droppedFrameCount == 3, "backend playout health stores dropped frame count");
|
|
Expect(playout.flushedFrameCount == 1, "backend playout health stores flushed frame count");
|
|
Expect(playout.degraded, "backend playout health stores degraded state");
|
|
Expect(playout.statusMessage == "Output underrun", "backend playout health stores status message");
|
|
|
|
Expect(telemetry.TryRecordBackendPlayoutHealth(
|
|
"Running",
|
|
"Completed",
|
|
2,
|
|
4,
|
|
13,
|
|
11,
|
|
2,
|
|
1,
|
|
9,
|
|
12,
|
|
3,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
5,
|
|
3,
|
|
1,
|
|
false,
|
|
""),
|
|
"try backend playout health succeeds when uncontended");
|
|
const HealthTelemetry::Snapshot snapshot = telemetry.GetSnapshot();
|
|
Expect(snapshot.backendPlayout.lifecycleState == "Running", "full health snapshot includes backend playout state");
|
|
Expect(!snapshot.backendPlayout.degraded, "full health snapshot includes backend degraded state");
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
TestRuntimeEventQueueMetrics();
|
|
TestRuntimeEventDispatchStats();
|
|
TestRuntimeEventTryRecord();
|
|
TestPersistenceWriteHealth();
|
|
TestBackendPlayoutHealth();
|
|
|
|
if (gFailures != 0)
|
|
{
|
|
std::cerr << gFailures << " HealthTelemetry test failure(s).\n";
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "HealthTelemetry tests passed.\n";
|
|
return 0;
|
|
}
|