feat(33): structured pump stats + the session planner and its plain-words copy
Slice 2. 588 green, 0 warnings. - `FramePumpStats` and `FramePump.StatsReported`: the 5 s window the log line already describes, as data. `Dropped` is the ENCODER's counter (frames submitted, not accepted); `Stalls`/`AvgRenderMs` are the pump's. `FramesRendered` is deliberately not used for classification — a static scene reuses the paste cache and renders few frames while completely healthy, so it would read as starvation. - `StepDownPlanner`: one per broadcast, owns the stateful policy, converts stats → sample, exposes the landed tier for the restart. It never acts — the VM owns the effects, which is what keeps the ladder testable without an encoder. - `Describe` / `ReportLine`: the sentences a creator sees. Machine cause says LlamaCasty couldn't keep up and the connection was not the problem; upload cause blames the upload and promises no further thrash. A test asserts the machine copy never leaks "dropped" — mechanism strings stay in the log. Remaining for the task: VM subscription, the encoder restart at the landed tier, the toast, and shedding our own capture cost before stepping fps.
This commit is contained in:
@@ -133,6 +133,10 @@ public sealed class FramePump : IDisposable
|
||||
/// Raised before the pump stops, so the session can relaunch the push instead of ending.</summary>
|
||||
public event EventHandler<string>? EncoderFailed;
|
||||
|
||||
/// <summary>TASK 33: the same 5-second window the stats line reports, structured — so a policy can
|
||||
/// tell machine starvation from encoder backpressure without parsing prose.</summary>
|
||||
public event EventHandler<FramePumpStats>? StatsReported;
|
||||
|
||||
public FramePump(
|
||||
Func<Scene?> sceneProvider,
|
||||
Func<SceneElement, VideoFrame?> frameResolver,
|
||||
@@ -426,6 +430,21 @@ public sealed class FramePump : IDisposable
|
||||
_log?.Invoke($"FramePump parts ({statRenders} renders/5s): {parts}");
|
||||
_timings.Reset();
|
||||
|
||||
// Structured twin of the line above, raised before the counters reset. `dropped` is the
|
||||
// ENCODER's count (ffmpeg blocked); a renderer that duplicates frames is already visible
|
||||
// as render time + stalls, and FramesRendered is ambiguous by design (paste cache).
|
||||
StatsReported?.Invoke(this, new FramePumpStats(
|
||||
WindowSeconds: 5,
|
||||
FramesSubmitted: statFrames,
|
||||
FramesRendered: statRenders,
|
||||
AvgRenderMs: statRenders > 0 ? renderTicks / freq * 1000 / statRenders : 0,
|
||||
AvgSubmitMs: statFrames > 0 ? submitTicks / freq * 1000 / statFrames : 0,
|
||||
AvgWaitMs: statRenders > 0 ? waitTicks / freq * 1000 / statRenders : 0,
|
||||
WorstRenderMs: worstRender / freq * 1000,
|
||||
WorstSubmitMs: worstSubmit / freq * 1000,
|
||||
Dropped: dropped,
|
||||
Stalls: stalls));
|
||||
|
||||
worstRender = 0;
|
||||
worstSubmit = 0;
|
||||
renderTicks = submitTicks = resolveTicks = waitTicks = 0;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace ytLive.Services.Encoder;
|
||||
|
||||
/// <summary>One 5-second window of pump and encoder evidence, structured.
|
||||
///
|
||||
/// <para>The stats line in the log is for humans; this is for the policy that has to decide whether
|
||||
/// the machine or the connection is the problem. Note which counter is which:</para>
|
||||
/// <list type="bullet">
|
||||
/// <item><see cref="Stalls"/> and <see cref="AvgRenderMs"/> are the MACHINE's evidence — the pump
|
||||
/// could not produce a frame in time.</item>
|
||||
/// <item><see cref="Dropped"/> is the ENCODER's — frames submitted but not accepted downstream. It
|
||||
/// rises when ffmpeg is blocked, which under CBR means the socket, not the renderer.</item>
|
||||
/// <item><see cref="FramesRendered"/> is deliberately NOT used for classification: a static scene
|
||||
/// legitimately reuses the paste cache and renders few frames while completely healthy.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public readonly record struct FramePumpStats(
|
||||
double WindowSeconds,
|
||||
int FramesSubmitted,
|
||||
int FramesRendered,
|
||||
double AvgRenderMs,
|
||||
double AvgSubmitMs,
|
||||
double AvgWaitMs,
|
||||
double WorstRenderMs,
|
||||
double WorstSubmitMs,
|
||||
int Dropped,
|
||||
int Stalls);
|
||||
Reference in New Issue
Block a user