Publish runtime metrics and byte-weighted progress via System.Diagnostics.Metrics#865
Merged
Conversation
Add an always-on System.Diagnostics.Metrics meter (PlexCleaner.Process) so a long-running process or monitor pass can be inspected live with dotnet-counters, no extra infrastructure. Overall progress is weighted by input bytes, not file count, so a run mixing tiny and huge files reports actual work done. - Metrics.cs owns the meter, the instruments, and Interlocked run-scoped state; observable-gauge callbacks only read, so the parallel loop needs no lock. - ProcessDriver.ProcessFiles drives files/bytes/in-flight, byte-weighted progress.ratio and eta.seconds, and file.duration; it sums input sizes once up front and credits the same size at completion. Run-scoped gauges reset per pass; counters stay cumulative for rate display. - Process.ProcessFiles records per-SidecarFile.StatesType outcomes; MediaTool and the ffprobe packet reader record tool.duration. Tags are bounded (state, tool) with no filename tags. - v1 gives in-flight files no partial credit until they finish; per-file child-process progress is a separate follow-up. - Docker ships a "counters" wrapper so reading the meter is "docker exec <container> counters". Zero new packages (Metrics is in the BCL). Implements #848 v1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds an always-on System.Diagnostics.Metrics meter (PlexCleaner.Process) to expose live runtime/process progress (byte-weighted) and tool/file timing via dotnet-counters, implementing #848.
Changes:
- Introduces
PlexCleaner.Processmetrics (Metrics.cs) with counters/gauges/histograms for files/bytes/progress/ETA and tool + per-file durations. - Integrates metrics updates at key choke points:
ProcessDriver.ProcessFiles,Process.ProcessFiles,MediaToolexecution, and ffprobe packet scanning. - Documents usage (README/ARCHITECTURE/HISTORY) and adds a Docker
counterswrapper plus unit tests validating byte-weighted math and observability.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| version.json | Bumps version floor to 3.22. |
| README.md | Adds Runtime Metrics section + usage examples. |
| HISTORY.md | Adds 3.22 changelog entry describing metrics feature. |
| ARCHITECTURE.md | Documents metrics architecture and hook points. |
| PlexCleaner/Metrics.cs | New meter/instruments + run-scoped state and computations. |
| PlexCleaner/ProcessDriver.cs | Computes size totals and records per-file progress/ETA inputs and durations. |
| PlexCleaner/Process.cs | Records per-outcome state/modified/verifyfailed metrics. |
| PlexCleaner/MediaTool.cs | Records per-tool execution duration metrics. |
| PlexCleaner/FfProbeTool.cs | Records ffprobe packet-scan duration as tool time. |
| PlexCleaner/Program.cs | Disposes the meter on shutdown. |
| PlexCleanerTests/MetricsTests.cs | Adds unit tests for progress/ETA/flag enumeration and listener observability. |
| Docker/Dockerfile | Installs counters wrapper into the image. |
| Docker/counters.sh | Wrapper script for dotnet-counters targeting PID 1 with a writable extract dir. |
…ounters cmd - ProcessDriver bases the byte-size map and BeginRun totals on the files that will actually be processed (filters to MKV when mkvFilesOnly), and no longer credits skipped non-MKV files as completed, so progress/ETA and files.total reflect real work for the MKV-only commands. - README local dotnet-counters example uses --counters, matching the wrapper. - Replace an em dash with a hyphen in ARCHITECTURE.md (ASCII-only guidance). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…locs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Rework the Metrics and ProcessDriver comments to house style: one statement per line, no class-header block, no prose semicolons. - Drop the internal tracking issue reference from HISTORY. - Split semicolon-joined sentences in ARCHITECTURE. - Add the 3.22 release-notes summary to README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
PlexCleaner/ProcessDriver.cs:223
- Cancellation is checked before incrementing processedCount and before recording FileCompleted. If a cancellation is requested after taskFunc returns but before this check, the file has already finished but metrics (bytes.completed, files.completed, file.duration) and the processedCount-based percentage won't reflect it, making progress/ETA under-report completed work on interrupted runs. Consider deferring ThrowIfCancellationRequested until after recording completion for this file.
// Handle cancel request
Program.CancelToken().ThrowIfCancellationRequested();
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #848 (v1).
What
Adds an always-on
System.Diagnostics.Metricsmeter (PlexCleaner.Process) so a long-runningprocess/monitorpass can be inspected live withdotnet-counters— no config flag, no extra infrastructure (instruments are inert until observed). Overall progress is weighted by input bytes, not file count, so a run mixing tiny and huge files reports the actual work completed.Design
Metrics.csowns the meter, all instruments, andInterlockedrun-scoped state. Observable-gauge callbacks only read, so the parallel loop needs no lock. Tags are bounded (state,tool) — no filename tags (cardinality).ProcessDriver.ProcessFiles(the choke point every command and monitor cycle funnels through) drives files/bytes/in-flight, the byte-weightedprogress.ratioandeta.seconds, andfile.duration. Input sizes are summed once up front and the same size is credited at completion, so a remux/rename mid-run can't drift the total. Run-scoped gauges reset per pass; counters stay cumulative for rate display.Process.ProcessFilesrecords per-SidecarFile.StatesTypeoutcomes;MediaToolexecution paths and the ffprobe packet reader recordtool.duration.Instruments
files.total/completed/modified/errors/verifyfailed,files.processed{state},files.inflight,threads.active,bytes.total/completed,progress.ratio,eta.seconds,file.duration,tool.duration{tool}.Scope (v1)
In-flight files get no partial credit until they finish. Per-file child-process progress (ffmpeg
-progress, mkvmerge--gui-mode, ffprobe pts-advance) feeding partial credit is a metrics-only v2 follow-up. Nostatus.json— metrics are the sole surface.Reading it
dotnet-counters monitor -p <pid> PlexCleaner.Processdocker exec <container> counters— a bundled wrapper (Docker/counters.sh) that sets the self-extract dir and targets PID 1.Notes
System.Diagnostics.Metricsis in the BCL;System.Diagnostics.DiagnosticSource.dllalready ships transitively.MetricsTests.cs) cover the byte-weighted math, ETA guards, flag enumeration, and aMeterListenerend-to-end assertion — no media files. Full suite 226/226.🤖 Generated with Claude Code