--- applyTo: "Fuchs/**,Fuchs_DataService/**,MFR_RESTClient/**,MT940Parser/**" --- # Logging Instructions ## Overview All logging in this solution uses `Microsoft.Extensions.Logging.ILogger`. **Never use** `System.Diagnostics.Debug.Print`, `Debug.WriteLine`, `Console.WriteLine`, or `OCMS.ocms_debug.debug_log` in business or library code. ## Providers ### Fuchs_DataService — `FdsLoggerProvider` - Location: `Fuchs_DataService/Logging/FdsLoggerProvider.cs` - Always active: **Debug output** (`System.Diagnostics.Debug.WriteLine`) + **file** (`tmp/DebugLog.txt`, `tmp/ErrorLog.txt`) - Database logging: prepared via `WriteToDatabase()` but **disabled by default**. Activate with `FdsLoggerProvider.DatabaseLoggingEnabled = true`. - Registered in `FdsMain.cs` via `LoggerFactory.Create(b => b.SetMinimumLevel(LogLevel.Debug).AddFdsLogging())`. ### Fuchs — `FuchsLoggerProvider` - Location: `Fuchs/Logging/FuchsLoggerProvider.cs` - Always active: **Debug output** + **file** (`logs/AppLog.txt`, `logs/ErrorLog.txt`) - Database logging: prepared but **disabled by default**. Activate with `FuchsLoggerProvider.DatabaseLoggingEnabled = true`. - Registered in `Program.cs` via `builder.Logging.SetMinimumLevel(LogLevel.Debug).AddFuchsLogging()`. ### MFR_RESTClient — Library (no provider) - No logging provider — purely a library. - `MFRClient` accepts `ILogger?` as an optional constructor parameter. - Defaults to `NullLogger.Instance` when no logger is provided. - Callers supply a logger from the host's `ILoggerFactory`. ### MT940Parser — Library (no provider) - Location: `../../WebProjectComponents/MT940Parser/` (shared external component) - No logging provider — purely a library. - **Public entry point only**: `Parser` accepts `ILogger?` as an optional constructor parameter and defaults to `NullLogger.Instance`. - **Internal sub-parsers** (`StatementParser`, `BalanceParser`, `StatementLineParser`, `AdditionalInfoParser`) are pure algorithmic classes. They **do not hold logger fields**. Parse errors are thrown as exceptions (`InvalidDataException`, `FormatException`) and caught by `Parser.Parse()`, which logs them at `LogWarning`. - Callers supply a logger when constructing `Parser`; the sub-parsers never need one directly. ## Rules - **DI classes** (singletons, scoped): receive `ILogger` via constructor injection. - **Library classes** (`MFRClient`, `Parser`): accept `ILogger?` as an optional constructor parameter, default to `NullLogger.Instance`. - **Internal library helpers** (`StatementParser`, `BalanceParser`, `StatementLineParser`, `AdditionalInfoParser`): pure algorithmic, no logger field. Throw exceptions; the public entry-point catches and logs. - **Static helpers** (`FdsShared`, `Banking`): accept `ILogger?` as an optional method parameter, or delegate to `FdsDebug.DebugLog` for infrastructure-level errors. - `FdsDebug` remains the **fallback for static infrastructure code only** (stream helpers, etc.). Do not use it in new class-level code. - Use structured logging parameters: `_logger.LogError(ex, "Message {Param}", value)` — never string interpolation in the message template. ## Log Levels | Level | Use for | |-------|---------| | `LogDebug` | Timing, row counts, progress traces | | `LogInformation` | Service start/stop, significant state changes | | `LogWarning` | Recoverable issues, skipped items | | `LogError` | Caught exceptions, data sync failures | | `LogCritical` | Unrecoverable failures that stop a job | ## Enabling Database Logging ```csharp // Fuchs_DataService FdsLoggerProvider.DatabaseLoggingEnabled = true; // Fuchs web FuchsLoggerProvider.DatabaseLoggingEnabled = true; ``` Uncomment the body of `WriteToDatabase()` in the respective provider and adjust the stored procedure name.