Phase 15 complete (2 plans):
- 15-01: NLog 5.2.8 + nlog.config (rolling file daily/7d + console); logger fields in
FanucMachine, HeidenhainMachine, SiemensMachine, MitsubishiMachine, Lsv2Client, Program.cs;
SetState event handler catches → _log.Warn; cleanup catches annotated; ISS-003/ISS-004 closed
- 15-02: All Console.Write/WriteLine in Program.cs replaced with _log.Info (103 calls);
nlog.config console target layout=${message}, levels=Info only — Warn/Error file-only;
operator console output identical; every interaction now timestamped in log file
Milestone v0.5 Operational Quality complete.
Co-Authored-By: Claude <noreply@anthropic.com>
194 lines
6.9 KiB
Markdown
194 lines
6.9 KiB
Markdown
---
|
|
phase: 15-logging
|
|
plan: 02
|
|
type: execute
|
|
wave: 1
|
|
depends_on: ["15-01"]
|
|
files_modified:
|
|
- nlog.config
|
|
- Program.cs
|
|
autonomous: true
|
|
---
|
|
|
|
<objective>
|
|
## Goal
|
|
Replace all `Console.Write`/`Console.WriteLine` calls in Program.cs with `_log.Info(...)` and reconfigure the NLog console target so operator output is plain text (Info only), while Warn/Error routes to logfile only.
|
|
|
|
## Purpose
|
|
Operator output currently bypasses NLog — no timestamps, no log file record of what was shown on screen. Moving all output through NLog means every operator interaction is in the log file with a timestamp, while the console still shows plain text identical to the current experience.
|
|
|
|
## Output
|
|
- `nlog.config` — console target: layout=`${message}`, rule limited to Info level only
|
|
- `Program.cs` — zero `Console.Write`/`Console.WriteLine` calls; all replaced with `_log.Info(...)`
|
|
</objective>
|
|
|
|
<context>
|
|
@.paul/PROJECT.md
|
|
@.paul/phases/15-logging/15-01-SUMMARY.md
|
|
@nlog.config
|
|
@Program.cs
|
|
</context>
|
|
|
|
<acceptance_criteria>
|
|
|
|
## AC-1: Console output unchanged for operator
|
|
```gherkin
|
|
Given Program.cs has no Console.Write/Console.WriteLine calls
|
|
When any operator-facing message is emitted (startup, progress, error text)
|
|
Then operator sees exactly the same text on screen as before
|
|
And no level/logger prefix appears on any message
|
|
```
|
|
|
|
## AC-2: All operator output recorded in log file
|
|
```gherkin
|
|
Given nlog.config file target captures Info+
|
|
When any operator-facing message is emitted
|
|
Then that same message appears in logs/nc_program_manager.log with timestamp
|
|
```
|
|
|
|
## AC-3: Warn/Error stay out of operator console
|
|
```gherkin
|
|
Given _log.Warn and _log.Error calls in machine classes and Program.cs
|
|
When those calls execute
|
|
Then they do NOT appear on the operator console (file only)
|
|
And they DO appear in the log file
|
|
```
|
|
|
|
</acceptance_criteria>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Reconfigure nlog.config console target to Info-only plain layout</name>
|
|
<files>nlog.config</files>
|
|
<action>
|
|
Make two changes to nlog.config:
|
|
|
|
**A. Console target layout** — change from level+logger prefix to plain message:
|
|
Current:
|
|
```xml
|
|
<target xsi:type="Console"
|
|
name="console"
|
|
layout="${level:uppercase=true:padding=5} [${logger:shortName=true}] ${message}" />
|
|
```
|
|
Replace with:
|
|
```xml
|
|
<target xsi:type="Console"
|
|
name="console"
|
|
layout="${message}" />
|
|
```
|
|
|
|
**B. Console rule** — restrict to Info level only (not Warn/Error):
|
|
Current:
|
|
```xml
|
|
<logger name="*" minlevel="Warn" writeTo="console" />
|
|
```
|
|
Replace with:
|
|
```xml
|
|
<logger name="*" levels="Info" writeTo="console" />
|
|
```
|
|
|
|
Constraints:
|
|
- File target and its rule (`minlevel="Debug" writeTo="logfile"`) MUST NOT change — file still captures everything
|
|
- `levels="Info"` (not `minlevel`) — this restricts console to exactly Info, so Warn/Error go to file only
|
|
- Layout `${message}` with no newline suffix — NLog appends newline automatically
|
|
</action>
|
|
<verify>
|
|
- Read nlog.config: console target layout is `${message}`
|
|
- Read nlog.config: console rule uses `levels="Info"`
|
|
- Read nlog.config: file target rule unchanged (`minlevel="Debug"`)
|
|
</verify>
|
|
<done>AC-1 partial (layout ready), AC-3 satisfied: Warn/Error no longer route to console</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Replace all Console.Write/WriteLine with _log.Info in Program.cs</name>
|
|
<files>Program.cs</files>
|
|
<action>
|
|
Replace every `Console.Write` and `Console.WriteLine` call with `_log.Info(...)`.
|
|
|
|
**Step 1 — Merge the one Console.Write (non-Line) pair at lines 25-26:**
|
|
Current:
|
|
```csharp
|
|
Console.Write("Gestore Programmi FANUC: ");
|
|
Console.WriteLine(e.Message);
|
|
```
|
|
Replace with:
|
|
```csharp
|
|
_log.Info("Gestore Programmi FANUC: {0}", e.Message);
|
|
```
|
|
|
|
**Step 2 — Replace all remaining Console.WriteLine calls:**
|
|
|
|
Pattern rules:
|
|
- `Console.WriteLine("literal string")` → `_log.Info("literal string")`
|
|
- `Console.WriteLine(variable)` → `_log.Info("{0}", variable)` — safe against variables containing `{`
|
|
- `Console.WriteLine("literal {0}", arg)` → `_log.Info("literal {0}", arg)` — format args pass through unchanged
|
|
- `Console.WriteLine()` (empty — blank line) → `_log.Info("")`
|
|
|
|
**Step 3 — For the 3 existing error catch blocks** (lines ~163, ~259 after prior edits):
|
|
The pattern is now:
|
|
```csharp
|
|
_log.Error(ex, "Scarica failed");
|
|
Console.WriteLine(ex.Message);
|
|
```
|
|
`Console.WriteLine(ex.Message)` → `_log.Info("{0}", ex.Message)`
|
|
|
|
This is correct: _log.Error goes to file only (Warn/Error not on console per Task 1); _log.Info shows ex.Message on console — same behavior as the original Console.WriteLine.
|
|
|
|
Constraints:
|
|
- Do NOT change `_log.Error(...)` or `_log.Warn(...)` calls — those were added in 15-01 and must stay
|
|
- Do NOT change `VediErrore(...)` calls
|
|
- Do NOT change `MostraAiuto()` or any non-Console calls
|
|
- `Console.WriteLine()` with no args (blank separator lines, if any) → `_log.Info("")`
|
|
- After replacement, `grep -c "Console\." Program.cs` MUST return 0
|
|
</action>
|
|
<verify>
|
|
- `grep -c "Console\." Program.cs` → 0
|
|
- `grep -c "_log.Info" Program.cs` → 98 (97 former WriteLine + 1 merged from Console.Write pair)
|
|
- Read lines 22-30 Program.cs: single `_log.Info("Gestore Programmi FANUC: {0}", e.Message)` present; no Console.Write calls
|
|
</verify>
|
|
<done>AC-1 satisfied: all operator output through NLog; AC-2 satisfied: Info goes to file target too</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<boundaries>
|
|
|
|
## DO NOT CHANGE
|
|
- `nlog.config` file target and its rule — file still captures Debug+
|
|
- `_log.Error(...)` and `_log.Warn(...)` calls added in 15-01 — correct, leave alone
|
|
- `NcProgramManager.Tests/` — no test changes
|
|
- All machine classes — no changes needed (they have no Console.WriteLine)
|
|
- `Licensing/`, `Cnc/`, `ArgParser.cs`, `InputArgs.cs` — not in scope
|
|
|
|
## SCOPE LIMITS
|
|
- Only `nlog.config` and `Program.cs` modified
|
|
- No new NLog targets beyond updating the existing console target
|
|
- No changes to log levels on the file target
|
|
- No changes to the `_log` field or `using NLog` already in Program.cs
|
|
|
|
</boundaries>
|
|
|
|
<verification>
|
|
Before declaring plan complete:
|
|
- [ ] `grep -c "Console\." Program.cs` → 0
|
|
- [ ] `grep -c "_log.Info" Program.cs` → 98
|
|
- [ ] `grep -c "_log.Error" Program.cs` → 3 (unchanged from 15-01)
|
|
- [ ] nlog.config console target: layout=`${message}`
|
|
- [ ] nlog.config console rule: `levels="Info"` (not minlevel)
|
|
- [ ] nlog.config file rule: `minlevel="Debug"` (unchanged)
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- Both tasks completed
|
|
- All 3 ACs covered
|
|
- Zero Console.Write/Console.WriteLine remain in Program.cs
|
|
- Operator console experience identical (plain text, no level prefix)
|
|
- All output now in log file
|
|
- No existing _log.Error/_log.Warn calls modified
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.paul/phases/15-logging/15-02-SUMMARY.md`
|
|
</output>
|