138 lines
4.4 KiB
Markdown
138 lines
4.4 KiB
Markdown
# logging.fallback.ps1
|
||
|
||
This file implements SAMY’s fallback logging functions used across the project.
|
||
|
||
It supports:
|
||
- Console logging (color-coded)
|
||
- In-memory log caching (for UI/diagnostics)
|
||
- Optional file logging (UTF-8 **without BOM**)
|
||
- Optional Windows Event Log logging, including:
|
||
- first-run creation of the log/source (when elevated)
|
||
- resolving “source bound to the wrong log” problems
|
||
|
||
---
|
||
|
||
## Regions overview
|
||
|
||
### Globals
|
||
**What it does**
|
||
- Initializes shared global state used by logging:
|
||
- `LogCache`: an `ArrayList` of log entries created during execution.
|
||
- `EventSinkCache`: a `Hashtable` caching resolved Event Log sinks so we do not repeatedly initialize/bind.
|
||
|
||
**Why it exists**
|
||
- Makes log output available to UI or post-run summaries.
|
||
- Prevents repeated Event Log setup attempts and repeated warnings.
|
||
|
||
---
|
||
|
||
### Helpers: Formatting + File
|
||
**What it does**
|
||
- `Get-LogColor(Level)`: maps `Info/Warning/Error/Success/General` to console colors.
|
||
- `Get-EventIdForLevel(Level, CustomEventID)`: returns default Event IDs by level unless overridden.
|
||
- `Get-EventEntryTypeForLevel(Level)`: maps levels to Event Log entry types.
|
||
- `Append-Utf8NoBomLine(Path, Line)`: appends a line to a file using UTF-8 **without BOM**.
|
||
|
||
**Why it exists**
|
||
- Keeps the main logging functions readable.
|
||
- Ensures runtime log files comply with the repository encoding rule (UTF-8 no BOM).
|
||
|
||
---
|
||
|
||
### Helpers: Event Log Binding
|
||
**Background**
|
||
Windows Event Log has a key constraint:
|
||
|
||
A **Source** can only be registered to **one** Log at a time.
|
||
|
||
Example:
|
||
- If source `SVMSP_Module` is registered to `Application`,
|
||
you cannot write with:
|
||
`Write-EventLog -LogName "SVSMSP Events" -Source "SVMSP_Module"`
|
||
until that binding is repaired or avoided.
|
||
|
||
**What it does**
|
||
- `Test-IsAdmin()`: checks if the current PowerShell session is elevated.
|
||
- `Initialize-EventLogBinding(DesiredLog, DesiredSource, ConflictPolicy)`:
|
||
returns an effective `{ LogName, Source, IsAdmin }` that is safe to use for `Write-EventLog`.
|
||
|
||
**ConflictPolicy**
|
||
If `DesiredSource` exists but is bound to a different log, one of these policies applies:
|
||
|
||
- `Repair` (default)
|
||
- Removes the existing source registration from its current log
|
||
- Recreates it under `DesiredLog`
|
||
- Requires elevation
|
||
- Best when you want **all SAMY logs in one custom log**
|
||
|
||
- `Unique`
|
||
- Creates a new SAMY-specific source under `DesiredLog`
|
||
(e.g., `SVMSP_Module.SAMY`, `SVMSP_Module.SAMY2`, etc.)
|
||
- Does not delete anything
|
||
- Requires elevation to create the new source
|
||
- Best when you want **no deletion / no rebinding risk**
|
||
|
||
- `Follow`
|
||
- Uses whichever log the source is already bound to
|
||
- Never deletes anything
|
||
- May log to `Application` if that’s where the source already exists
|
||
- Best when you want **maximum safety and minimum changes**
|
||
|
||
**Non-admin behavior**
|
||
If not elevated and the desired source does not exist, the code falls back to:
|
||
- `LogName = Application`
|
||
- `Source = Windows PowerShell`
|
||
|
||
This avoids trying to create custom Event Log sources without admin rights.
|
||
|
||
---
|
||
|
||
### Public: Write-LogHelper
|
||
**What it does**
|
||
This is the core fallback logger.
|
||
|
||
Always does:
|
||
- Writes a formatted message to console (with color)
|
||
- Adds an entry to `Global:LogCache`
|
||
|
||
Optionally does:
|
||
- File logging (when `-LogFile` is provided)
|
||
- Event Log logging (when `-LogToEvent` is set)
|
||
|
||
**Event Log caching**
|
||
To avoid repeating setup work, the function caches the resolved Event Log sink:
|
||
- Key format: `"$EventLog|$EventSource|$EventLogConflictPolicy"`
|
||
- Cached value includes:
|
||
- `Ready` (boolean)
|
||
- `LogName` (effective log to write to)
|
||
- `Source` (effective source to write with)
|
||
|
||
**Parameters that matter most**
|
||
- `-Message`: text to log
|
||
- `-Level`: affects console color, EventId, EntryType
|
||
- `-TaskCategory`: included in formatted message and event message
|
||
- `-LogToEvent`: enable/disable Event Log writes
|
||
- `-EventLog`, `-EventSource`: desired Event Log sink
|
||
- `-EventLogConflictPolicy`: `Repair`, `Unique`, or `Follow`
|
||
|
||
---
|
||
|
||
### Public: Write-LogHybrid
|
||
**What it does**
|
||
A wrapper for compatibility.
|
||
|
||
Behavior:
|
||
- If a preferred logger function `Write-Log` exists, it calls that.
|
||
- Otherwise it calls `Write-LogHelper`.
|
||
|
||
**Why it exists**
|
||
- Lets SAMY swap logging implementations without changing all call sites.
|
||
|
||
---
|
||
|
||
## Typical usage examples
|
||
|
||
### Console only
|
||
```powershell
|
||
Write-LogHybrid -Message "Starting SAMY" -Level Info -TaskCategory "Startup"
|