ACAT Logging Migration Guide
February 5, 2026 · View on GitHub
Executive Summary
This document outlines the strategy for migrating ACAT's static Log.* calls to instance-based diagnostic logging across 217 files containing 2,044 logging calls.
Current State Analysis
Codebase Statistics
- Total C# files: 764
- Files using Log: 217
- Total Log calls: 2,044
Log Call Distribution
| Method | Count | Percentage |
|---|---|---|
| Log.Debug | 1,235 | 60.4% |
| Log.Exception | 408 | 20.0% |
| Log.Verbose | 301 | 14.7% |
| Log.Error | 61 | 3.0% |
| Log.Warn | 27 | 1.3% |
| Log.Info | 12 | 0.6% |
File Complexity
- Simple (≤5 calls): 134 files - Quick wins
- Moderate (6-20 calls): 57 files - Standard effort
- Complex (>20 calls): 26 files - Needs review
Migration Strategy
Phase 1: Foundation (Ticket #1 - Prerequisite)
Goal: Add logging infrastructure WITHOUT breaking existing code
Tasks:
-
Add NuGet packages to ACAT.Core.csproj:
- Microsoft.Extensions.Logging (v8.0.0+)
- Microsoft.Extensions.Logging.Debug
- Microsoft.Extensions.Logging.Console
- Microsoft.Extensions.DependencyInjection
-
Create
ACAT.Core.Utility.DiagnosticWriter- Instance-based logging wrapper -
Create
ACAT.Core.Utility.DiagnosticFactory- Factory for creating loggers -
Keep existing
Log.csunchanged (backward compatibility) -
Add
[Obsolete]attributes toLog.csmethods
Phase 2: Proof of Concept (Ticket #2 - Sample Conversion)
Goal: Convert 3-5 representative files to establish pattern
Recommended starter files (simple, non-static classes):
Libraries/ACATCore/Utility/SoundManager.cs(3 calls)Libraries/ACATCore/Utility/ImageUtils.cs(4 calls)Libraries/ACATCore/Utility/ResourceUtils.cs(5 calls)
Conversion Pattern:
// BEFORE
public class SoundManager
{
public static void PlaySound()
{
Log.Debug("Playing sound");
}
}
// AFTER
public class SoundManager
{
private readonly IDiagnosticWriter _diagnostics;
public SoundManager(IDiagnosticWriter diagnostics = null)
{
_diagnostics = diagnostics ?? DiagnosticFactory.CreateForType<SoundManager>();
}
public void PlaySound()
{
_diagnostics.WriteDebugMessage("Playing sound");
}
}
Phase 3: Batch Conversion (Ticket #2 - Mass Migration)
Goal: Convert remaining 134 simple files, then 57 moderate files
Approach: Semi-automated using custom tooling
- Use Roslyn API or regex-based tool for mechanical conversion
- Human review for each file
- Test after each batch of 10-20 files
Conversion Rules:
| Old Pattern | New Pattern |
|---|---|
Log.Debug(msg) | _diagnostics.WriteDebugMessage(msg) |
Log.Error(msg) | _diagnostics.WriteErrorMessage(msg) |
Log.Info(msg) | _diagnostics.WriteInfoMessage(msg) |
Log.Exception(ex) | _diagnostics.WriteExceptionDetails(ex) |
Log.Verbose(msg) | _diagnostics.WriteDebugMessage(msg) |
Log.Warn(msg) | _diagnostics.WriteErrorMessage(msg) |
Phase 4: Complex Files (Ticket #2 - Manual Review)
Goal: Convert 26 complex files with >20 calls each
Top 5 Priority Files:
BCIActuator.cs(111 calls)AnimationPlayer.cs(107 calls)AgentManager.cs(79 calls)PanelStack.cs(77 calls)TextUtils.cs(66 calls - static utility class)
Special Cases:
- Static utility classes: Consider making them instantiable or using static factory
- Singleton managers: May need constructor parameter added
- Legacy code: May require architectural discussion
Phase 5: Application Entry Points (Ticket #3)
Goal: Setup dependency injection in application startup
Entry Points to Update:
Applications/ACATApp/Program.csApplications/ACATWatch/Program.csApplications/ACATTalk/Program.csApplications/ACATConfig/Program.csApplications/ACATConfigNext/Program.csApplications/ConvAssistTerminate/Program.cs
Startup Pattern:
static void Main(string[] args)
{
var diagnosticsFactory = DiagnosticFactory.Initialize();
// Existing initialization code...
InitializeGlobals();
InitializeLogging(); // Enhanced to use diagnosticsFactory
// Rest of application...
}
Phase 6: Testing & Validation (Ticket #4)
Goal: Ensure no regressions, all logs still work
Validation Steps:
-
Run grep validation:
# Should show only Log.cs itself grep -r "Log\.Debug" --include="*.cs" | grep -v "Log.cs:" -
Build solution:
dotnet build ACAT.sln -
Manual testing:
- Launch each application
- Verify log files created
- Check log content matches old format
-
Create unit tests for DiagnosticWriter
-
Document edge cases and known issues
Timeline Estimate
| Phase | Effort | Dependencies |
|---|---|---|
| Phase 1: Foundation | 4 hours | None |
| Phase 2: POC (3-5 files) | 4 hours | Phase 1 |
| Phase 3: Simple files (134) | 16 hours | Phase 2 |
| Phase 3: Moderate files (57) | 12 hours | Phase 3 (simple) |
| Phase 4: Complex files (26) | 12 hours | Phase 3 (moderate) |
| Phase 5: Entry points (6) | 4 hours | Phase 4 |
| Phase 6: Testing | 8 hours | Phase 5 |
| Total | 60 hours (7.5 days) |
Risk Mitigation
High Risk Items
-
Static utility classes: 60+ classes can't use constructor injection
- Mitigation: Keep as static, use factory pattern internally
-
Breaking changes: Existing code expects static Log access
- Mitigation: Keep Log.cs as thin wrapper during transition
-
Test coverage: No existing logging tests
- Mitigation: Add tests before making changes
Success Criteria
✅ All 2,044 Log calls converted
✅ Solution builds without errors
✅ All applications launch successfully
✅ Log files generated correctly
✅ No performance degradation
✅ Zero remaining Log.Debug/Error/Info calls (except in Log.cs)
Appendix: Automation Tool
A Python analysis tool has been created at /tmp/log_migration_tool.py that:
- Scans codebase for Log usage
- Generates statistics and reports
- Identifies files by complexity
- Can be extended for automated conversion
Usage:
python3 /tmp/log_migration_tool.py /path/to/acat/src
Next Steps
- Review and approve this migration strategy
- Execute Phase 1 (Foundation setup)
- Complete Phase 2 (POC with 3 files)
- Review POC and adjust pattern if needed
- Proceed with remaining phases
Document Version: 1.0
Last Updated: 2026-02-05