# Logger — TODO

## Priority legend
- **P0** blocker · **P1** important · **P2** nice-to-have · **P3** idea

---

## ACCORE-LOG-T-H6Y4: Fix the writer-ctor mismatch for DI-injected writers
**Priority:** P2 · **Type:** Bug fix · **Related:** `LOGGING_ISSUES.md#accore-log-i-k7m2`

Options:
- **A)** Provide a fallback `(AppType, LogLevel, string?)` ctor on consumer writers that have DI-heavy primary ctors, with DI resolution via service-locator
- **B)** Skip writers that don't match the `Activator`-ctor signature, with a single consolidated warning (not per-init spam)
- **C)** Deprecate the config-reading writer-instantiation path entirely in favour of DI registration

Eliminate the per-startup Console.Error noise regardless.

## ACCORE-LOG-T-N2D8: Expose `AcEnv.AppConfiguration` setter for consumer init
**Priority:** P2 · **Type:** Feature · **Related:** `LOGGING_ISSUES.md#accore-log-i-r9p3`

Allow `AcEnv.SetConfiguration(IConfiguration)` so consumer `Program.cs` can do `AcEnv.SetConfiguration(builder.Configuration)` at startup. Enables config-reading pattern on MAUI/WASM without filesystem assumptions. Backward-compat: fall back to filesystem if no explicit set.

## ACCORE-LOG-T-R7L3: Unify or clearly separate config-reading and DI-based patterns
**Priority:** P2 · **Type:** Docs / Refactor · **Related:** `LOGGING_ISSUES.md#accore-log-i-l4n8`

Decide the canonical direction:
- **(a)** Deprecate config-reading pattern → all consumers migrate to DI factory
- **(b)** Keep both, with compile-time guidance (analyzer / XML doc `[Obsolete]` hints / decision tree in LOGGING.md)
- **(c)** Merge: DI-factory internally falls back to config-reading when `TLogger` doesn't match the `Activator` ctor shape

## ACCORE-LOG-T-F4S6: Per-writer LogLevel via appsettings
**Priority:** P2 · **Type:** Feature

Extend `AcLoggerOptions` with per-writer LogLevel overrides. Example shape:
```json
"AyCode": {
    "Logger": {
        "LogLevel": "Info",
        "WriterLevels": { "BrowserConsoleLogWriter": "Debug", "SignaRClientLogItemWriter": "Warning" }
    }
}
```
Factory applies overrides when constructing writers. Currently writer-LogLevel is hardcoded in writer ctors.

## ACCORE-LOG-T-J9G2: Unify default LogLevel across setup paths
**Priority:** P1 · **Type:** Behaviour decision + cleanup · **Related:** `LOGGING_ISSUES.md#accore-log-i-b2h5`

Decide which default wins (`AcLoggerBase.cs:18` = `Error` vs `AcLoggerOptions.cs:27` = `Info`) and make both paths consistent. Recommendation: **`Info`** — matches the DI/Options path already in use for modern consumers (MAUI, WASM, ASP.NET Core) and is the common developer expectation.

Change: drop the field initializer in `AcLoggerBase` (or set it to `Info`). Update LOGGING.md with a single "Default LogLevel = Info" line so this can't drift again.

## ACCORE-LOG-T-B8K5: Fix `AcConsoleLogWriter.Initialize()` double-run
**Priority:** P3 · **Type:** Bug fix · **Related:** `LOGGING_ISSUES.md#accore-log-i-x7q1`

Remove the redundant `Initialize()` call from the parameterless ctor body — the `: this(null)` chain already invokes it. No behaviour change; removes wasted `Console.ForegroundColor` assignment.

## ACCORE-LOG-T-X1V4: Fix `ILogger.IsEnabled(MsLogLevel.None)` wrongly reporting enabled
**Priority:** P2 · **Type:** Bug fix · **Related:** `LOGGING_ISSUES.md#accore-log-i-v3j6`

Add `if (logLevel == MsLogLevel.None) return false;` at the top of `AcLoggerBase.IsEnabled`. One-line fix. Optionally add a unit test covering all six MS LogLevel values → expected bool.

## ACCORE-LOG-T-M7P2: Cleanup batch (low-risk micro-refactor, one commit)
**Priority:** P3 · **Type:** Cleanup · **Related:** `LOGGING_ISSUES.md#accore-log-i-t8f2`

Single commit covering:
- Remove unused usings in `AcLoggerBase.cs` (`System.Security.AccessControl`, `System.Net.Mime.MediaTypeNames`)
- Extract the default-category magic string `"..."` (at least 3 occurrences — `AcLoggerBase.cs:36,76`, writer side) into a public const `AcLoggerBase.DefaultCategory = "..."` with XML doc explaining it's the "unknown category" sentinel, NOT a magic string. Update all call-sites.
- Fix misleading comment at `AcLoggerBase.cs:210` — current comment says "fallback null" but code assigns `"Log"`. Make comment match code.
- Decide on the commented-out batch block in `AcLogItemWriterBase.cs:90-119`: either delete (git history preserves) or convert to a single `// TODO: see LOGGING_TODO.md#todo-XX` marker with a new TODO entry for the batch work.

## ACCORE-LOG-T-L3T8: Fail-fast ctor validation in `AddAcLoggerFactory<TLogger>`
**Priority:** P2 · **Type:** Feature

`AcLoggerServiceExtensions.AddAcLoggerFactory<TLogger>` uses `Activator.CreateInstance(typeof(TLogger), AppType, LogLevel, categoryName, writers)` only on first logger resolution. Ctor-mismatch therefore surfaces only at first log call, not at `services.BuildServiceProvider()` time.

Add a one-time reflection check at registration: `typeof(TLogger).GetConstructor([typeof(AppType), typeof(LogLevel), typeof(string), typeof(IAcLogWriterBase[])])` — if null, throw `InvalidOperationException` with the expected signature in the message. Cost: one reflection call per registration. Benefit: app fails to start (loud) instead of logging being silently broken (quiet).

## ACCORE-LOG-T-Q6Z1: Writer exception isolation
**Priority:** P2 · **Type:** Resilience

Currently `AcLoggerBase.Info(...)` and friends do `LogWriters.ForEach(x => x.Info(...))`. A throwing writer (e.g. `SignaRClientLogItemWriter` during network blip, `AcDbLogItemWriter` during a DB outage) takes down the fan-out → subsequent writers in the list never see the message.

Wrap each writer invocation in `try { ... } catch (Exception ex) { Console.Error.WriteLine($"Writer {x.GetType().Name} failed: {ex.Message}"); }`. Optional: escalate to a circuit-breaker pattern (N failures → disable that writer for M seconds) to avoid Console.Error flood on persistent outages.

Must NOT log to `AcLoggerBase` itself inside the catch (reentrancy / infinite loop risk).

## ACCORE-LOG-T-W4H9: Migrate server-side NopCommerce plugin logger setup to DI-factory
**Priority:** P2 · **Type:** Consumer refactor · **Related:** `LOGGING_ISSUES.md#accore-log-i-m4c9`, `../../../AyCode.Services/docs/SIGNALR/SIGNALR_TODO.md#accore-sig-t-m5l6`

Align the server-side plugin (`Nop.Plugin.Misc.AIPlugin/Infrastructure/PluginNopStartup.cs`) with the client-side setup pattern already used by MAUI / Web / Web.Client consumers.

### Target diff
```csharp
// In PluginNopStartup.ConfigureServices:

// 1. Bind Logger options from appsettings.json (replaces AcEnv.AppConfiguration path)
services.Configure<AcLoggerOptions>(configuration.GetSection("AyCode:Logger"));

// 2. Register writers (already present)
services.AddScoped<IAcLogWriterBase, ConsoleLogWriter>();
services.AddScoped<IAcLogWriterBase, NopLogWriter>();

// 3. Register the logger factory — replaces direct `new Logger(...)` calls
services.AddAcLoggerFactory<Logger>();

// 4. In the SignalR registration — drop the manual Logger construction
.AddAcBinaryProtocol(opts =>
{
    opts.ProtocolMode = BinaryProtocolMode.AsyncSegment;
    // Remove:  opts.Logger = new Logger(nameof(AyCodeBinaryHubProtocol));
    //         — AcSignalRProtocolExtensions.BuildProtocol auto-resolves ILogger<AcBinaryHubProtocol> from DI
});
```

### Consequences / checklist
- [ ] Consumers of `new Logger(...)` elsewhere in the plugin code must switch to injecting `Func<string, Logger>` (DI factory).
- [ ] ACCORE-LOG-I-K7M2 Console.Error noise disappears once the config-reading path is no longer invoked.
- [ ] Legacy `AyCode:Logger:LogWriters[]` array in `appsettings.json` becomes unused — decide: **(a)** remove (breaking if any other consumer still reads it), **(b)** keep for back-compat with a comment "superseded by DI, see LOGGING.md".
- [ ] Update `Nop.Plugin.Misc.AIPlugin/docs/SIGNALR/README.md:22` — current text still describes `services.AddSingleton<IHubProtocol>(new AcBinaryHubProtocol())` which has NOT been the actual registration for months.
- [ ] Verify server startup log — `AcLoggerOptions` must bind cleanly (no "missing section" warnings from `IOptionsMonitor`).

### Why this is a separate TODO from ACCORE-LOG-T-R7L3
ACCORE-LOG-T-R7L3 is about the **framework-level decision** (keep both patterns vs deprecate legacy). ACCORE-LOG-T-W4H9 is the **consumer-level execution** of that decision for the server plugin — independent of whether ACCORE-LOG-T-R7L3 ultimately deprecates the legacy path or keeps it alive. Migrating the server plugin removes ACCORE-LOG-I-K7M2 noise regardless of ACCORE-LOG-T-R7L3's outcome.

## ACCORE-LOG-T-D7S3: A SignalR log-feltöltő writer diagnosztikai loggere (szűrt writer-lista) — ⚠️ ÁTGONDOLANDÓ
**Priority:** P3 · **Type:** Feature (döntés függőben) · **Related:** `../../../AyCode.Services/docs/SIGNALR_BINARY_PROTOCOL/SIGNALR_BINARY_PROTOCOL_TODO.md#accore-sbp-t-t5r2`

**Státusz: ÁTGONDOLANDÓ — még kérdéses, kell-e egyáltalán. A jelenlegi megoldás (a hívó süket loggert — `NullLogger.Instance` — ad a writer kapcsolat-protokolljának) alapvetően jó:** a hiba-út már látható (a writer `ReportFailureOnce` Console.Error-jelentése a `SendAsync`-kivételeknél a serializer-hibákat is elkapja), csak a mély diagnosztikai trace néma.

**Cél (ha bevezetjük):** az `AcSignaRClientLogItemWriter<TLogItem>` kapcsolat-diagnosztikája süket logger helyett olyan loggert kapjon, amiből a feltöltő writer **strukturálisan ki van szűrve** — a visszacsatolási hurok (log → sorosítás → diagnosztika-log → feltöltés → …) bekötése így lehetetlen marad, a diagnosztika viszont a host TÖBBI writerére (konzol, fájl, DB — bármi regisztrált) kimegy, és automatikusan követi a jövőbeli writer-regisztrációkat.

**Megbeszélt terv (2026-07):**
1. `IAcSignalRLogWriter` marker-interfész az `AcSignaRClientLogItemWriter<TLogItem>`-re — a szűrés típus-alapú: `writers.Where(w => w is not IAcSignalRLogWriter).ToList()` (saját, materializált lista az új loggernek).
2. A diagnosztikai logger **üresen** születik — a szűrt lista a feltöltő ctorába NEM injektálható (körkörös DI: a feltöltő maga is eleme az `IEnumerable<IAcLogWriterClientBase>`-nek). A host `Build()` után tölti fel: `GetServices<IAcLogWriterClientBase>().Where(…).ToList()` → `SetWriters(…)`.
3. Keret-kiegészítés kell: `AcLoggerBase.SetWriters`/`AddWriters` (a `LogWriters` jelenleg protected).
4. Default szint: Debug — a soronkénti trace zajszintje protokoll-oldali kérdés, ld. ACCORE-SBP-T-T5R2.

**Ismert apró rés:** a kapcsolat-felépítés első diagnosztika-sorai még az üres loggert látják — elhanyagolható.
