Files
video-shader-toys/apps/LoopThroughWithOpenGLCompositing/runtime/telemetry/HealthTelemetry.cpp
Aiden 0a7954e879
All checks were successful
CI / React UI Build (push) Successful in 10s
CI / Native Windows Build And Tests (push) Successful in 2m47s
CI / Windows Release Package (push) Successful in 3m2s
Phase 7 done
2026-05-11 21:15:51 +10:00

325 lines
14 KiB
C++

#include "stdafx.h"
#include "HealthTelemetry.h"
void HealthTelemetry::ReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
{
std::lock_guard<std::mutex> lock(mMutex);
mSignalStatus.hasSignal = hasSignal;
mSignalStatus.width = width;
mSignalStatus.height = height;
mSignalStatus.modeName = modeName;
}
bool HealthTelemetry::TryReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
mSignalStatus.hasSignal = hasSignal;
mSignalStatus.width = width;
mSignalStatus.height = height;
mSignalStatus.modeName = modeName;
return true;
}
void HealthTelemetry::ReportVideoIOStatus(const std::string& backendName, const std::string& modelName,
bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable,
bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage)
{
std::lock_guard<std::mutex> lock(mMutex);
mVideoIOStatus.backendName = backendName;
mVideoIOStatus.modelName = modelName;
mVideoIOStatus.supportsInternalKeying = supportsInternalKeying;
mVideoIOStatus.supportsExternalKeying = supportsExternalKeying;
mVideoIOStatus.keyerInterfaceAvailable = keyerInterfaceAvailable;
mVideoIOStatus.externalKeyingRequested = externalKeyingRequested;
mVideoIOStatus.externalKeyingActive = externalKeyingActive;
mVideoIOStatus.statusMessage = statusMessage;
}
bool HealthTelemetry::TryReportVideoIOStatus(const std::string& backendName, const std::string& modelName,
bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable,
bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
mVideoIOStatus.backendName = backendName;
mVideoIOStatus.modelName = modelName;
mVideoIOStatus.supportsInternalKeying = supportsInternalKeying;
mVideoIOStatus.supportsExternalKeying = supportsExternalKeying;
mVideoIOStatus.keyerInterfaceAvailable = keyerInterfaceAvailable;
mVideoIOStatus.externalKeyingRequested = externalKeyingRequested;
mVideoIOStatus.externalKeyingActive = externalKeyingActive;
mVideoIOStatus.statusMessage = statusMessage;
return true;
}
void HealthTelemetry::RecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
{
std::lock_guard<std::mutex> lock(mMutex);
mPerformance.frameBudgetMilliseconds = std::max(frameBudgetMilliseconds, 0.0);
mPerformance.renderMilliseconds = std::max(renderMilliseconds, 0.0);
if (mPerformance.smoothedRenderMilliseconds <= 0.0)
mPerformance.smoothedRenderMilliseconds = mPerformance.renderMilliseconds;
else
mPerformance.smoothedRenderMilliseconds = mPerformance.smoothedRenderMilliseconds * 0.9 + mPerformance.renderMilliseconds * 0.1;
}
bool HealthTelemetry::TryRecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
mPerformance.frameBudgetMilliseconds = std::max(frameBudgetMilliseconds, 0.0);
mPerformance.renderMilliseconds = std::max(renderMilliseconds, 0.0);
if (mPerformance.smoothedRenderMilliseconds <= 0.0)
mPerformance.smoothedRenderMilliseconds = mPerformance.renderMilliseconds;
else
mPerformance.smoothedRenderMilliseconds = mPerformance.smoothedRenderMilliseconds * 0.9 + mPerformance.renderMilliseconds * 0.1;
return true;
}
void HealthTelemetry::RecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
{
std::lock_guard<std::mutex> lock(mMutex);
mPerformance.completionIntervalMilliseconds = std::max(completionIntervalMilliseconds, 0.0);
mPerformance.smoothedCompletionIntervalMilliseconds = std::max(smoothedCompletionIntervalMilliseconds, 0.0);
mPerformance.maxCompletionIntervalMilliseconds = std::max(maxCompletionIntervalMilliseconds, 0.0);
mPerformance.lateFrameCount = lateFrameCount;
mPerformance.droppedFrameCount = droppedFrameCount;
mPerformance.flushedFrameCount = flushedFrameCount;
}
bool HealthTelemetry::TryRecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
mPerformance.completionIntervalMilliseconds = std::max(completionIntervalMilliseconds, 0.0);
mPerformance.smoothedCompletionIntervalMilliseconds = std::max(smoothedCompletionIntervalMilliseconds, 0.0);
mPerformance.maxCompletionIntervalMilliseconds = std::max(maxCompletionIntervalMilliseconds, 0.0);
mPerformance.lateFrameCount = lateFrameCount;
mPerformance.droppedFrameCount = droppedFrameCount;
mPerformance.flushedFrameCount = flushedFrameCount;
return true;
}
void HealthTelemetry::RecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
uint64_t droppedCount, double oldestEventAgeMilliseconds)
{
std::lock_guard<std::mutex> lock(mMutex);
mRuntimeEvents.queue.queueName = queueName;
mRuntimeEvents.queue.depth = depth;
mRuntimeEvents.queue.capacity = capacity;
mRuntimeEvents.queue.droppedCount = droppedCount;
mRuntimeEvents.queue.oldestEventAgeMilliseconds = std::max(oldestEventAgeMilliseconds, 0.0);
}
bool HealthTelemetry::TryRecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity,
uint64_t droppedCount, double oldestEventAgeMilliseconds)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
mRuntimeEvents.queue.queueName = queueName;
mRuntimeEvents.queue.depth = depth;
mRuntimeEvents.queue.capacity = capacity;
mRuntimeEvents.queue.droppedCount = droppedCount;
mRuntimeEvents.queue.oldestEventAgeMilliseconds = std::max(oldestEventAgeMilliseconds, 0.0);
return true;
}
void HealthTelemetry::RecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
std::size_t handlerFailures, double dispatchDurationMilliseconds)
{
std::lock_guard<std::mutex> lock(mMutex);
++mRuntimeEvents.dispatch.dispatchCallCount;
mRuntimeEvents.dispatch.dispatchedEventCount += static_cast<uint64_t>(dispatchedEvents);
mRuntimeEvents.dispatch.handlerInvocationCount += static_cast<uint64_t>(handlerInvocations);
mRuntimeEvents.dispatch.handlerFailureCount += static_cast<uint64_t>(handlerFailures);
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds = std::max(dispatchDurationMilliseconds, 0.0);
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds = std::max(
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds,
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds);
}
bool HealthTelemetry::TryRecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations,
std::size_t handlerFailures, double dispatchDurationMilliseconds)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
++mRuntimeEvents.dispatch.dispatchCallCount;
mRuntimeEvents.dispatch.dispatchedEventCount += static_cast<uint64_t>(dispatchedEvents);
mRuntimeEvents.dispatch.handlerInvocationCount += static_cast<uint64_t>(handlerInvocations);
mRuntimeEvents.dispatch.handlerFailureCount += static_cast<uint64_t>(handlerFailures);
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds = std::max(dispatchDurationMilliseconds, 0.0);
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds = std::max(
mRuntimeEvents.dispatch.maxDispatchDurationMilliseconds,
mRuntimeEvents.dispatch.lastDispatchDurationMilliseconds);
return true;
}
void HealthTelemetry::RecordPersistenceWriteResult(bool succeeded, const std::string& targetKind, const std::string& targetPath,
const std::string& reason, const std::string& errorMessage, bool newerRequestPending)
{
std::lock_guard<std::mutex> lock(mMutex);
if (succeeded)
++mPersistence.writeSuccessCount;
else
++mPersistence.writeFailureCount;
mPersistence.lastWriteSucceeded = succeeded;
mPersistence.unsavedChanges = !succeeded || newerRequestPending;
mPersistence.newerRequestPending = newerRequestPending;
mPersistence.lastTargetKind = targetKind;
mPersistence.lastTargetPath = targetPath;
mPersistence.lastReason = reason;
mPersistence.lastErrorMessage = errorMessage;
}
bool HealthTelemetry::TryRecordPersistenceWriteResult(bool succeeded, const std::string& targetKind, const std::string& targetPath,
const std::string& reason, const std::string& errorMessage, bool newerRequestPending)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
if (succeeded)
++mPersistence.writeSuccessCount;
else
++mPersistence.writeFailureCount;
mPersistence.lastWriteSucceeded = succeeded;
mPersistence.unsavedChanges = !succeeded || newerRequestPending;
mPersistence.newerRequestPending = newerRequestPending;
mPersistence.lastTargetKind = targetKind;
mPersistence.lastTargetPath = targetPath;
mPersistence.lastReason = reason;
mPersistence.lastErrorMessage = errorMessage;
return true;
}
void HealthTelemetry::RecordBackendPlayoutHealth(const std::string& lifecycleState, const std::string& completionResult,
std::size_t readyQueueDepth, std::size_t readyQueueCapacity, uint64_t readyQueuePushedCount,
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
uint64_t completedFrameIndex, uint64_t scheduledFrameIndex, uint64_t scheduledLeadFrames,
uint64_t measuredLagFrames, uint64_t catchUpFrames, uint64_t lateStreak, uint64_t dropStreak,
uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount,
bool degraded, const std::string& statusMessage)
{
std::lock_guard<std::mutex> lock(mMutex);
mBackendPlayout.lifecycleState = lifecycleState;
mBackendPlayout.completionResult = completionResult;
mBackendPlayout.readyQueueDepth = readyQueueDepth;
mBackendPlayout.readyQueueCapacity = readyQueueCapacity;
mBackendPlayout.readyQueuePushedCount = readyQueuePushedCount;
mBackendPlayout.readyQueuePoppedCount = readyQueuePoppedCount;
mBackendPlayout.readyQueueDroppedCount = readyQueueDroppedCount;
mBackendPlayout.readyQueueUnderrunCount = readyQueueUnderrunCount;
mBackendPlayout.completedFrameIndex = completedFrameIndex;
mBackendPlayout.scheduledFrameIndex = scheduledFrameIndex;
mBackendPlayout.scheduledLeadFrames = scheduledLeadFrames;
mBackendPlayout.measuredLagFrames = measuredLagFrames;
mBackendPlayout.catchUpFrames = catchUpFrames;
mBackendPlayout.lateStreak = lateStreak;
mBackendPlayout.dropStreak = dropStreak;
mBackendPlayout.lateFrameCount = lateFrameCount;
mBackendPlayout.droppedFrameCount = droppedFrameCount;
mBackendPlayout.flushedFrameCount = flushedFrameCount;
mBackendPlayout.degraded = degraded;
mBackendPlayout.statusMessage = statusMessage;
}
bool HealthTelemetry::TryRecordBackendPlayoutHealth(const std::string& lifecycleState, const std::string& completionResult,
std::size_t readyQueueDepth, std::size_t readyQueueCapacity, uint64_t readyQueuePushedCount,
uint64_t readyQueuePoppedCount, uint64_t readyQueueDroppedCount, uint64_t readyQueueUnderrunCount,
uint64_t completedFrameIndex, uint64_t scheduledFrameIndex, uint64_t scheduledLeadFrames,
uint64_t measuredLagFrames, uint64_t catchUpFrames, uint64_t lateStreak, uint64_t dropStreak,
uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount,
bool degraded, const std::string& statusMessage)
{
std::unique_lock<std::mutex> lock(mMutex, std::try_to_lock);
if (!lock.owns_lock())
return false;
mBackendPlayout.lifecycleState = lifecycleState;
mBackendPlayout.completionResult = completionResult;
mBackendPlayout.readyQueueDepth = readyQueueDepth;
mBackendPlayout.readyQueueCapacity = readyQueueCapacity;
mBackendPlayout.readyQueuePushedCount = readyQueuePushedCount;
mBackendPlayout.readyQueuePoppedCount = readyQueuePoppedCount;
mBackendPlayout.readyQueueDroppedCount = readyQueueDroppedCount;
mBackendPlayout.readyQueueUnderrunCount = readyQueueUnderrunCount;
mBackendPlayout.completedFrameIndex = completedFrameIndex;
mBackendPlayout.scheduledFrameIndex = scheduledFrameIndex;
mBackendPlayout.scheduledLeadFrames = scheduledLeadFrames;
mBackendPlayout.measuredLagFrames = measuredLagFrames;
mBackendPlayout.catchUpFrames = catchUpFrames;
mBackendPlayout.lateStreak = lateStreak;
mBackendPlayout.dropStreak = dropStreak;
mBackendPlayout.lateFrameCount = lateFrameCount;
mBackendPlayout.droppedFrameCount = droppedFrameCount;
mBackendPlayout.flushedFrameCount = flushedFrameCount;
mBackendPlayout.degraded = degraded;
mBackendPlayout.statusMessage = statusMessage;
return true;
}
HealthTelemetry::SignalStatusSnapshot HealthTelemetry::GetSignalStatusSnapshot() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mSignalStatus;
}
HealthTelemetry::VideoIOStatusSnapshot HealthTelemetry::GetVideoIOStatusSnapshot() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mVideoIOStatus;
}
HealthTelemetry::PerformanceSnapshot HealthTelemetry::GetPerformanceSnapshot() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mPerformance;
}
HealthTelemetry::RuntimeEventMetricsSnapshot HealthTelemetry::GetRuntimeEventMetricsSnapshot() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mRuntimeEvents;
}
HealthTelemetry::PersistenceSnapshot HealthTelemetry::GetPersistenceSnapshot() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mPersistence;
}
HealthTelemetry::BackendPlayoutSnapshot HealthTelemetry::GetBackendPlayoutSnapshot() const
{
std::lock_guard<std::mutex> lock(mMutex);
return mBackendPlayout;
}
HealthTelemetry::Snapshot HealthTelemetry::GetSnapshot() const
{
std::lock_guard<std::mutex> lock(mMutex);
Snapshot snapshot;
snapshot.signal = mSignalStatus;
snapshot.videoIO = mVideoIOStatus;
snapshot.performance = mPerformance;
snapshot.runtimeEvents = mRuntimeEvents;
snapshot.persistence = mPersistence;
snapshot.backendPlayout = mBackendPlayout;
return snapshot;
}