---
title: "OP-12: Dispose and flush a configured logger"
summary: How a host-owned logger instance releases its Serilog resources on shutdown.
status: draft
owner: SAIF Platform Team
last_reviewed: 2026-10-02
library: SAIF.NetCore.Logging
reference_type: package
operation_id: OP-12
trigger: Host application disposes the logger instance (SaifLog, SaifWindowsServiceLog, or ConsoleLogService), typically during process shutdown.
---

# OP-12: Dispose and flush a configured logger

| Field | Value |
| --- | --- |
| Operation ID | OP-12 |
| Trigger | The host disposes the logger instance — directly, or via DI container teardown when the logger is registered with a disposable lifetime. |
| Inputs | None beyond the logger instance's own configured state. |
| Outputs | The process-global Serilog logger (`Log.Logger`) flushed and closed; for `ConsoleLogService`, every auxiliary `LogWriter` disposed first. |
| Primary components | `SaifLogBase.Dispose`, `ConsoleLogService.Dispose` (override) |
| Entry point | `Dispose()` |

## Steps
1. `SaifLogBase.Dispose()` (public virtual) calls `Log.CloseAndFlush()` on the process-global Serilog logger, flushing buffered output for synchronous sinks (Console, Event Log). This does **not** wait for or flush an in-flight `LoggingApiSink` POST: `Emit` is `async void` with no completion signal exposed to the caller, so `CloseAndFlush()` has no awaitable handle to that in-flight call and cannot block on it.
2. `ConsoleLogService.Dispose()` (public override) first disposes every registered auxiliary `LogWriter` in `_loggers` — releasing each file writer's own independent Serilog logger and file handle — and only then calls `Log.CloseAndFlush()` if the service `IsConfigured`.
3. `SaifLog` and `SaifWindowsServiceLog` do not override `Dispose`; they use the base `SaifLogBase.Dispose()` behavior directly.

## Process flow

```mermaid
flowchart TD
    A[Host disposes logger instance] --> B{Logger type}
    B -->|SaifLog / SaifWindowsServiceLog| C["SaifLogBase.Dispose: Log.CloseAndFlush()"]
    B -->|ConsoleLogService| D["Dispose each auxiliary LogWriter first"]
    D --> E{IsConfigured?}
    E -->|Yes| F["Then Log.CloseAndFlush()"]
    E -->|No| G[Skip Log.CloseAndFlush]
```

## Failure and edge-case behavior
- `Log.CloseAndFlush()` acts on the single process-global `Serilog.Log.Logger`; disposing one logger instance in a process that hosts multiple `SaifLogBase`-derived loggers flushes/closes the shared static logger for all of them, not just the instance being disposed.
- `ConsoleLogService.Dispose()` disposes auxiliary `LogWriter` instances unconditionally, even if the service itself was never successfully configured; it only conditions the `Log.CloseAndFlush()` call on `IsConfigured`.
- Disposal does not flush any in-flight `LoggingApiSink.Emit` call; because `Emit` is `async void` with no awaited completion signal exposed to the caller, a POST in progress at shutdown may be abandoned.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `src/SAIF.NetCore.Logging/SAIF.NetCore.Logging/SAIF.NetCore.Logging/SaifLogBase.cs`
- `src/SAIF.NetCore.Logging/SAIF.NetCore.Logging/SAIF.NetCore.Logging/ConsoleLogService.cs`
- `src/SAIF.NetCore.Logging/SAIF.NetCore.Logging/SAIF.NetCore.Logging/Console/LogWriter.cs`
