#pragma once #include #include #include #include // Phase 1 compatibility seam for status and timing reporting. HealthTelemetry // owns the current operational status snapshot directly, so callers can report // health without sharing runtime-store state. class HealthTelemetry { public: struct SignalStatusSnapshot { bool hasSignal = false; unsigned width = 0; unsigned height = 0; std::string modeName; }; struct VideoIOStatusSnapshot { std::string backendName = "decklink"; std::string modelName; bool supportsInternalKeying = false; bool supportsExternalKeying = false; bool keyerInterfaceAvailable = false; bool externalKeyingRequested = false; bool externalKeyingActive = false; std::string statusMessage; }; struct PerformanceSnapshot { double frameBudgetMilliseconds = 0.0; double renderMilliseconds = 0.0; double smoothedRenderMilliseconds = 0.0; double completionIntervalMilliseconds = 0.0; double smoothedCompletionIntervalMilliseconds = 0.0; double maxCompletionIntervalMilliseconds = 0.0; uint64_t lateFrameCount = 0; uint64_t droppedFrameCount = 0; uint64_t flushedFrameCount = 0; }; struct RuntimeEventQueueSnapshot { std::string queueName = "runtime-events"; std::size_t depth = 0; std::size_t capacity = 0; uint64_t droppedCount = 0; double oldestEventAgeMilliseconds = 0.0; }; struct RuntimeEventDispatchSnapshot { uint64_t dispatchCallCount = 0; uint64_t dispatchedEventCount = 0; uint64_t handlerInvocationCount = 0; uint64_t handlerFailureCount = 0; double lastDispatchDurationMilliseconds = 0.0; double maxDispatchDurationMilliseconds = 0.0; }; struct RuntimeEventMetricsSnapshot { RuntimeEventQueueSnapshot queue; RuntimeEventDispatchSnapshot dispatch; }; struct PersistenceSnapshot { uint64_t writeSuccessCount = 0; uint64_t writeFailureCount = 0; bool lastWriteSucceeded = true; bool unsavedChanges = false; bool newerRequestPending = false; std::string lastTargetKind; std::string lastTargetPath; std::string lastReason; std::string lastErrorMessage; }; struct Snapshot { SignalStatusSnapshot signal; VideoIOStatusSnapshot videoIO; PerformanceSnapshot performance; RuntimeEventMetricsSnapshot runtimeEvents; PersistenceSnapshot persistence; }; HealthTelemetry() = default; void ReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName); bool TryReportSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName); void ReportVideoIOStatus(const std::string& backendName, const std::string& modelName, bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable, bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage); bool TryReportVideoIOStatus(const std::string& backendName, const std::string& modelName, bool supportsInternalKeying, bool supportsExternalKeying, bool keyerInterfaceAvailable, bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage); void RecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds); bool TryRecordPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds); void RecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds, double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount); bool TryRecordFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds, double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount); void RecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity, uint64_t droppedCount, double oldestEventAgeMilliseconds); bool TryRecordRuntimeEventQueueMetrics(const std::string& queueName, std::size_t depth, std::size_t capacity, uint64_t droppedCount, double oldestEventAgeMilliseconds); void RecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations, std::size_t handlerFailures, double dispatchDurationMilliseconds); bool TryRecordRuntimeEventDispatchStats(std::size_t dispatchedEvents, std::size_t handlerInvocations, std::size_t handlerFailures, double dispatchDurationMilliseconds); void RecordPersistenceWriteResult(bool succeeded, const std::string& targetKind, const std::string& targetPath, const std::string& reason, const std::string& errorMessage, bool newerRequestPending); bool TryRecordPersistenceWriteResult(bool succeeded, const std::string& targetKind, const std::string& targetPath, const std::string& reason, const std::string& errorMessage, bool newerRequestPending); SignalStatusSnapshot GetSignalStatusSnapshot() const; VideoIOStatusSnapshot GetVideoIOStatusSnapshot() const; PerformanceSnapshot GetPerformanceSnapshot() const; RuntimeEventMetricsSnapshot GetRuntimeEventMetricsSnapshot() const; PersistenceSnapshot GetPersistenceSnapshot() const; Snapshot GetSnapshot() const; private: mutable std::mutex mMutex; SignalStatusSnapshot mSignalStatus; VideoIOStatusSnapshot mVideoIOStatus; PerformanceSnapshot mPerformance; RuntimeEventMetricsSnapshot mRuntimeEvents; PersistenceSnapshot mPersistence; };