9. Bug Reporting System
The application has a built-in, automatic bug-reporting channel that forwards warning-and-above log events to the PureLogicCode BugReport API. This page documents the full pipeline, the API contract, and — importantly — the noise-filtering rules.
9.1 Pipeline
LogMessage / LogWarning / LogError (MainWindow.xaml.cs:606–622)
│ (Serilog: Information / Warning / Error)
▼
Serilog Logger (App.xaml.cs:56–78)
├── Debug sink
├── File sink → %LocalAppData%\BatchConvertToCHD\logs\BatchConvertToCHD-YYYYMMDD.log
└── BugReportApiSink.Emit (Services/BugReportApiSink.cs:33)
├─ ignore events below Warning
├─ ignore messages matching exclusion patterns
└─ fire-and-forget SendBugReportAsync (single in-flight send via interlocked flag)
│
▼
BugReportService.SendBugReportAsync (Services/BugReportService.cs:94)
│ POST https://www.purelogiccode.com/bugreport/api/send-bug-report
▼
BugReport API (server)
Additionally, unhandled exceptions are reported directly (not via the sink):
AppDomain.CurrentDomain.UnhandledException→Log.Fatal+ synchronousReportException(the process is about to terminate, so the report must complete inline —App.xaml.cs:236–250). For dispatcher and task-scheduler exceptions the report is fire-and-forget to avoid blocking the UI thread.DispatcherUnhandledException→Log.Error+ReportException; a small allowlist of known-benign exceptions is suppressed (App.xaml.cs:207–233): WPF rendering errors (GlyphTypefaceURI errors, PresentationCore OOM inDUCE.Channel/HwndTarget) and the WPF-internalFileNotFoundExceptionfromPopupSecurityHelper.ForceMsaaToUiaBridge(ToolTip/Popup opening when the OS accessibility bridge cannot be loaded — the tooltip simply never appears). These are suppressed at the handler level and never reach the log sink.TaskScheduler.UnobservedTaskException→Log.Error+ReportException, thenSetObserved().- Stats-rate-limit handling:
StatsService.RecordUsageAsyncreturns early on HTTP 429 (Too Many Requests) and logs at Debug level, so these transient conditions never reach the warning-level sink.
9.2 API Contract
SendBugReportAsync (BugReportService.cs:94) POSTs JSON with header X-API-KEY:
| Field | Source |
|---|---|
message |
BuildFormattedReport — three sections: === Environment Details ===, === Error Details === (the raw message), === Exception Details === (inner-exception chain, max depth 5) |
applicationName |
AppConfig.ApplicationName = "BatchConvertToCHD" |
version |
Assembly version (e.g. 3.4.0.0) |
userInfo |
Environment.UserName |
environment |
"Production" (release) / "Development" (DEBUG build) |
stackTrace |
Formatted exception details, or "N/A" |
Environment Details includes: date/time, app name + version, OS version, architecture, bitness, Windows version, processor count, base directory, temp path.
9.3 Flood Control & Failure Semantics
- Only one bug report is in flight at a time (
BugReportApiSinkinterlocked flag); bursts of warnings are coalesced. A 12-second safety timer clears the flag even if the HTTP call hangs, preventing indefinite throttling. - Sending is fire-and-forget from the sink; failures are logged at
Debugand never surface to the user. - Cancellation tokens are respected;
OperationCanceledExceptionis rethrown only when the caller’s token is cancelled.
9.4 Exclusion Patterns
IsExcludedFromBugReport (BugReportService.cs:63) performs a case-insensitive substring match against ExcludedMessagePatterns (:21–61). Any match → the report is dropped entirely (no HTTP call). The categories:
| Category | Example patterns |
|---|---|
| Stats noise | "Failed to record usage statistics" |
| Drive / temp-space info | "Temp drive (", "Output drive (", "drive has ", "drive (", "input files total", "CHD files total", "You may run out of disk space", "disk space", "disk full" |
| Extraction outcomes | "No supported primary files found in archive", "Partial extraction:", "File not found, skipping:" |
| Tooling | "chdman.exe not found", "CRITICAL ERROR: The following required component is missing" |
| Corrupt/unopenable CHD data | "Not a valid CHD file", "Invalid or corrupt data", "Cannot open file" |
| chdman output (user data) | "Fatal error occurred" (chdman exit summary), "cannot create std::vector" (chdman C++ crash on user input) |
| Cue/dependency validation | "referenced files are missing", "could not be resolved", "could not validate referenced files", "MP3 audio track could not be decoded", "is not divisible by", "The file or directory is corrupted and unreadable", "Retry via temp failed" |
| Archive errors | "archive file may be corrupted", "archive is invalid or corrupt", "archive file appears to be incomplete", "multi-part RAR with a missing volume", "unavailable network location", "Archive is encrypted", "compression method that is not supported", "CCDSharp: Conversion error" |
Design intent: the exclusion list only contains messages that describe user-data or environmental conditions (corrupt files, full disks, missing volumes, rate limits) — conditions the application handles gracefully and that would otherwise flood the bug database. Genuine code defects (exceptions, unexpected failures) still reach the API — including CHDSharp and PBPSharp extraction failures, which are reported by design (with debug details such as file size, disc index/count, and numeric error codes) so the library maintainer can fix them. Every exclusion is covered by unit tests (BugReportServiceTests).
9.5 Server-Side Notes
- Timestamps in reports are local time formatted
yyyy-MM-dd HH:mm:ssinside the message body; the API’s ownreportedAtis UTC ISO-8601. - Bug reports are stored per application and can be retrieved/deleted via the agent API (
https://www.purelogiccode.com/bugreport/api/agent/...) — seeInstructionsToRetrieveBugs.mdin the AspNet_BugReportEmailService repository. - Depending on server-side storage settings, non-ASCII characters in messages (e.g. the em dash in “— referenced files are missing”) can be mangled (U+FFFD) on retrieval; messages containing them are excluded from reporting anyway.