Skip to content

Switch runtime metrics to operation-weighted progress#869

Merged
ptr727 merged 6 commits into
developfrom
feature/metrics-v3-heavy-op-progress
Jul 19, 2026
Merged

Switch runtime metrics to operation-weighted progress#869
ptr727 merged 6 commits into
developfrom
feature/metrics-v3-heavy-op-progress

Conversation

@ptr727

@ptr727 ptr727 commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

Reworks the develop-only runtime metrics (still 3.22, unreleased) from the v2 in-tool partial-credit model to a simpler operation-counting model. Each heavy full-file operation on a file counts the file's size as work to do when it starts (OpStarted) and as work done when it ends (OpCompleted), so progress.ratio = work.completed / work.total. The total grows as the non-deterministic per-file path is discovered — no per-file fraction weighting, and no parsing of tool progress output (which risked perturbing tool behavior).

Motivation: the metrics are a diagnostic for a small audience; the op-counting model is simpler, lower-risk (no -progress/--json/stdout-stream parsing in the processing path), and covers every heavy pass uniformly — including the ffprobe closed-caption scan, which has no incremental progress signal and so could not be instrumented under the v2 model.

Changes

  • Metrics.cs: work.total/work.completed byte counters incremented at operation boundaries via an ambient thread-local file size; dropped the FileSink partial-credit machinery. bytes.total stays the static input-size reference.
  • Bracketed the heavy full-file operations with OpStarted/OpCompleted: closed-caption scan, idet, ffmpeg re-encode (both overloads), HandBrake deinterlace, packet analysis, and VerifyMedia.
  • Kept the tool progress-parsing capability unused-but-tested for the future media-tools library: FfMpeg/HandBrake.ParseProgressFraction, MediaTool.ExecuteStreamStdOut, and the Progress()/Json() builder methods, plus ToolProgressParsingTests. Only the Metrics wiring was removed.
  • NativeAOT: the csproj sets <EventSourceSupport>true</EventSourceSupport> only when PublishAot=true, so an AOT build links the enabled EventPipe and exposes the diagnostics IPC server for dotnet-counters/dotnet-monitor. Default (non-AOT) builds are unchanged. (EventSourceSupport is the real switch; EventPipeSupport is a no-op.)

No version bump (develop-only feature, no released behavior). HISTORY 3.22 and the README Runtime Metrics section updated to describe op-counting.

Verification

  • Build analyzer-clean, 0 warnings; CSharpier + dotnet format style --verify-no-changes --severity=info clean; 238 tests pass (op-counting fold math + the retained parser tests); markdownlint clean.
  • Container e2e (container ffmpeg 8) — CoreCLR branch build: work.total grew as ops were discovered, progress.ratio = completed/total climbed. AOT binary: same, read live via the image counters wrapper.
  • AOT e2e: the AOT binary runs the full pipeline in the develop image with container tools (Exit Code 0) and, with EventSourceSupport, creates the diagnostic socket so dotnet-counters attaches and reads the meter.

🤖 Generated with Claude Code

Replace the in-tool partial-credit progress with a simpler
operation-counting model: each heavy full-file operation adds the
file's size to the work total when it starts and to the completed total
when it ends, so progress reflects the actual, non-deterministic work
with no per-file fraction weighting and no parsing of tool progress
output.

- Metrics: work.total/work.completed byte counters incremented at
  operation boundaries via an ambient thread-local file size; drop the
  FileSink partial-credit machinery. bytes.total stays the input-size
  reference.
- Bracket the heavy full-file operations (closed-caption scan, idet,
  ffmpeg re-encode, HandBrake deinterlace, packet analysis, verify)
  with OpStarted/OpCompleted.
- Keep the tool progress-parsing capability (ParseProgressFraction,
  ExecuteStreamStdOut, the Progress()/Json() builders) and its unit
  tests unused by this feature, for the media-tools library.
- NativeAOT: enable EventSourceSupport when PublishAot is set so
  dotnet-counters and dotnet-monitor can read the meter from an AOT
  build; default builds are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 14:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors PlexCleaner’s develop-only runtime metrics to an operation-weighted model: each heavy full-file operation contributes the file’s size to work.total at start and to work.completed at completion, with progress.ratio derived from those gauges. It also adjusts tool wrappers and tests accordingly, and enables EventSource support for NativeAOT builds so metrics can be read via diagnostics tooling.

Changes:

  • Replaced the prior per-file partial-credit progress model with operation-boundary OpStarted/OpCompleted accounting in Metrics.
  • Wrapped heavy full-file operations (ffprobe scans, ffmpeg verify/idet/encode, HandBrake deinterlace, packet analysis) with OpStarted/OpCompleted and removed tool-output-driven progress reporting.
  • Enabled EventSourceSupport for AOT publishes to ensure diagnostics IPC is available for dotnet-counters/dotnet-monitor.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Updates the runtime-metrics documentation to describe operation-weighted progress and instrument set.
HISTORY.md Updates 3.22 release notes to reflect the new operation-weighted progress model and instrument names.
PlexCleanerTests/MetricsTests.cs Reworks unit tests to validate operation-weighted progress/ETA behavior and meter observability.
PlexCleaner/ProcessFile.cs Removes the packet-level partial-credit reporting hook from analysis packet iteration.
PlexCleaner/ProcessDriver.cs Switches file completion metrics call signature and ensures per-file thread-local size setup/teardown remains correct.
PlexCleaner/Process.cs Removes now-unused duration seeding previously used for tool-progress-derived partial credit.
PlexCleaner/PlexCleaner.csproj Enables EventSourceSupport only for PublishAot=true so metrics remain readable in AOT builds.
PlexCleaner/Metrics.cs Implements operation-weighted work accounting via thread-local file size and new work.* gauges.
PlexCleaner/HandBrakeTool.cs Removes progress-stream parsing and brackets the deinterlace operation with metrics work accounting.
PlexCleaner/FfProbeTool.cs Brackets closed-caption scan and packet analysis with metrics work accounting.
PlexCleaner/FfMpegTool.cs Brackets verify, idet, and encode operations with metrics work accounting; removes encode progress streaming.

Comment thread README.md Outdated
Comment thread HISTORY.md Outdated
work.total and work.completed are run-scoped observable gauges, not
Counter instruments, so name them gauges to avoid confusing
dotnet-counters and OpenTelemetry consumers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 14:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Comment thread PlexCleaner/HandBrakeTool.cs Outdated
Comment thread PlexCleaner/FfProbeTool.cs
Comment thread PlexCleaner/FfMpegTool.cs
Comment thread PlexCleaner/FfMpegTool.cs Outdated
Comment thread PlexCleaner/FfMpegTool.cs Outdated
Comment thread PlexCleaner/FfMpegTool.cs
Move OpCompleted after the executed guard so a cancelled or
failed-to-start tool is not credited as completed work, which would
skew progress and ETA on interrupted runs. A non-zero exit still
counts, the tool did the full-file work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 14:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread PlexCleaner/FfProbeTool.cs
GetPackets returns false on a non-zero exit where ffprobe still ran
the scan, so gate OpCompleted on cancellation instead of the return
value, otherwise a ran-but-non-zero scan strands its work in the
total and skews progress for the rest of the run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 14:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread PlexCleaner/FfProbeTool.cs
Gate OpCompleted on the scan having run, evidenced by exit 0 or
captured stderr, instead of a cancellation check, so a cancellation
or a failure to start (empty error) is excluded while a ran-but-non-zero
scan is still counted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 14:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

PlexCleaner/HandBrakeTool.cs:147

  • Metrics.OpStarted() is called before Execute(...). If Execute returns false (cancellation or failure to start), work.total has already been incremented and is never rolled back, so progress.ratio/eta.seconds can remain skewed for the rest of the run. Consider only counting discovered work once the operation is confirmed to have started, or add a Metrics.OpAborted() (subtract current file size from work.total) and call it on the executed==false path.
            Metrics.OpStarted();
            bool executed = Execute(command, true, true, out BufferedCommandResult result);
            if (!executed)
            {
                return false;

Comment thread PlexCleaner/FfMpegTool.cs
Comment thread PlexCleaner/FfProbeTool.cs
Comment thread PlexCleaner/FfProbeTool.cs
OpStarted adds the file size to the work total up front, so an
operation that is cancelled or fails to start would leave the total
permanently inflated and stop progress converging. Add OpAborted to
roll that size back out, and call it on every abort path so each
started operation resolves to exactly one of completed or aborted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 15:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@ptr727
ptr727 merged commit acd795c into develop Jul 19, 2026
15 checks passed
@ptr727
ptr727 deleted the feature/metrics-v3-heavy-op-progress branch July 19, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants