Skip to content

feature: diagnostic report collector for issue reporting (#65) - #88

Merged
mcpolo99 merged 4 commits into
developfrom
65-diagnostic-report-collector-capture-crash-data-for-issue-reporting
Jul 4, 2026
Merged

feature: diagnostic report collector for issue reporting (#65)#88
mcpolo99 merged 4 commits into
developfrom
65-diagnostic-report-collector-capture-crash-data-for-issue-reporting

Conversation

@mcpolo99

@mcpolo99 mcpolo99 commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the diagnostic report collector from #65. When obfuscation fails (or succeeds), users can now produce a complete, copy-pasteable markdown report with one CLI flag or one GUI button — system info, project configuration, run result, and the full log transcript.

Fixes #65

What was added

Core — Confuser.Core/Diagnostics/

  • DiagnosticCollector — decorates both ILogger and IProgressReporter. Passes every call through to the real logger/reporter while capturing a full-verbosity transcript, timing, and outcome.
  • DiagnosticReport — renders the captured data into a self-contained markdown report (System / Project Configuration / Result / Log Output / Elapsed). Never throws.
  • DiagnosticRedactor — scrubs the user-profile path (%USER%) from text destined for a public report.

CLI--dump / --dump=<file> flag. Wraps the logger+reporter, writes the report after the run (success or failure), prints the path.

GUI — "Copy Report" button on the Protect tab, enabled once a run completes; copies the report to the clipboard.

Design notes — caveats and how they're handled

The issue's own "Caveats" section only named memory usage; hooking the logging core and pasting output publicly raised several sharper edges, all addressed:

  • Secret / PII leakage (report is pasted publicly): strong-name passwords (SNKeyPassword, SNSigKeyPassword) are never emitted; absolute paths have the user-profile prefix replaced with %USER%, applied to both the config block and captured log lines (the engine's PrintEnvironmentInfo dumps assembly locations into the log stream too).
  • Finish() moved to IProgressReporter (in the Replace custom ILogger with Serilog + Microsoft.Extensions.Logging #64 logging migration, so the issue text is stale): the collector decorates the progress reporter as well, giving it the authoritative success flag + timing.
  • Capture vs. display verbosity: capture is independent of the inner logger's level (IsEnabled → true, entries always retained), so a report from a default Information run still contains the Debug detail needed to diagnose. Display filtering is preserved by only forwarding to the inner logger when it's enabled for that level.
  • Packer nested runs: Finish is last-wins, so the top-level run — which finishes last — determines the reported outcome/elapsed.
  • Thread safety: bounded ring buffer (last 2000 entries) behind a lock, with a dropped-entry count surfaced in the report so truncation is never silent.
  • Markdown break-out: dynamic code-fence longer than any backtick run in the log body.
  • Robustness: report generation is fully defensive — it runs precisely when things are already broken.

Known limitation

The sample report in the issue shows a "Target Framework" line, but ConfuserProject has no TFM field, so it's omitted for now (the log output already shows the auto-detected runtime paths and the module). Could be added later as a best-effort read of the module's TargetFrameworkAttribute.

Testing

  • 19 Core unit tests (collector capture/forwarding, full-verbosity, ring-buffer + dropped count, last-wins Finish, redaction, dynamic fence, never-throws).
  • CLI E2E test — runs the CLI with --dump against the pre-built sample and asserts the report is written with the expected sections and no secret leakage.
  • Full offline CI (local-ci.sh): MSBuild build across all TFMs + entire test suite — all green.

Example report

## System
- OS: Microsoft Windows 10.0.26100
- Runtime: .NET 10.0.9
- ConfuserExx: Confuser.Core 1.7.0-alpha.28

## Project Configuration
- Base Directory: %USER%\...\dumptest
- Modules: SampleApp.exe
- Protections: rename
- Packer: (none)

## Result: SUCCESS

## Log Output
... full Debug transcript ...

## Elapsed: 0.9 s

RandomCrocodile added 3 commits July 4, 2026 11:37
Core of the diagnostic report collector: a DiagnosticCollector that decorates
both ILogger and IProgressReporter, capturing a full-verbosity transcript,
timing and outcome during an obfuscation run, plus a DiagnosticReport formatter
that renders a self-contained markdown report.

- Full-verbosity capture independent of display level; bounded ring buffer
  (last 2000 entries) with dropped-entry accounting.
- Last-wins Finish so a packer's nested run does not clobber the top-level
  result/elapsed.
- Redaction: never emits strong-name passwords; scrubs the user-profile path
  from config and log lines. Dynamic code-fence prevents markdown break-out.
- 19 unit tests, TDD.
Wraps the logger and progress reporter with a DiagnosticCollector when --dump
is passed, and writes the markdown report after the run completes (success or
failure). --dump uses a default filename; --dump=<file> writes to a custom path.
The report path is printed to the console. E2E test asserts the report is
written with the expected sections.
The protect tab now wraps the logger and progress reporter with a
DiagnosticCollector during each run. A 'Copy Report' button (enabled once a run
completes, success or failure) copies the markdown diagnostic report to the
clipboard for pasting into a bug report. Clipboard failures are swallowed so a
transient lock cannot crash the app.
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

Lint Results

All checks passed

Check Result
Whitespace (indentation, line endings)
Style (IDE rules, naming, var usage)
Analyzers (CA*, RCS* rules)

Reads each input module's TargetFrameworkAttribute (via dnlib, from an in-memory
copy so the file is never locked) and adds a 'Target Framework' line to the
report's configuration section. Best-effort: silently omitted when a module is
missing, not a valid assembly, or predates the attribute (net2.0-3.5). Verified
end-to-end — a net8 library reports '.NETCoreApp,Version=v8.0'; a failing run on
an invalid assembly still produces a clean FAILED report. 4 new tests.
@mcpolo99
mcpolo99 force-pushed the 65-diagnostic-report-collector-capture-crash-data-for-issue-reporting branch from 42630a8 to 760addb Compare July 4, 2026 10:35
@mcpolo99
mcpolo99 merged commit a3c177f into develop Jul 4, 2026
3 checks passed
@mcpolo99
mcpolo99 deleted the 65-diagnostic-report-collector-capture-crash-data-for-issue-reporting branch July 4, 2026 10:44
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.

1 participant