mbproxy: cross-platform support — Linux/systemd alongside Windows
Make the service build, run, and install on Linux as a first-class target while keeping the Windows Service + Event Log behaviour intact. - Build: drop the hardcoded win-x64 RID — single-file publish now works for any RID. publish.ps1 gains -Rid; new publish.sh for Linux hosts. - Diagnostics: DiagnosticSinkSelector picks the Error+ sink per host — Windows Event Log under the SCM, local syslog under systemd (Serilog.Sinks.SyslogMessages), none for interactive runs. The EventLog truncation helper is extracted so it is testable cross-OS. - Host: Program.cs registers AddSystemd() alongside AddWindowsService(). - Config: a RID-conditioned appsettings template ships Windows or Unix paths; both templates are schema-validated by a test. - Install: systemd unit (Type=exec) plus install.sh / uninstall.sh. Also fixes two cross-platform bugs found while testing: install.ps1 and uninstall.ps1 used New-EventLog / Remove-EventLog (absent in PowerShell 7), and the E2E sim launcher hardcoded Windows venv paths. - Docs updated across README, CLAUDE.md, and docs/ for dual-platform. 413 tests pass on Windows; 374 (all non-simulator) on Linux. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,9 @@ The stable catalog of every `mbproxy.*` event name the service emits, with its l
|
||||
|
||||
The service uses [Serilog](https://serilog.net/) wired through the `Microsoft.Extensions.Logging` bridge. Three sinks are configured (see `src/Mbproxy/HostingExtensions.cs`):
|
||||
|
||||
- **Console** — written to stdout for interactive `--console` runs and for the SCM stdout capture.
|
||||
- **Rolling file** — under `%ProgramData%\mbproxy\logs\` (`mbproxy-<date>.log`).
|
||||
- **Windows Event Log** — only when running as a Windows Service, and only for events at `Error` and above (see `src/Mbproxy/Diagnostics/EventLogBridge.cs`).
|
||||
- **Console** — stdout; captured by the Windows SCM or by systemd-journald.
|
||||
- **Rolling file** — `%ProgramData%\mbproxy\logs\` on Windows, `/var/log/mbproxy/` on Linux (`mbproxy-<date>.log`).
|
||||
- **Platform diagnostic sink** — `Error`+ events only. `DiagnosticSinkSelector` picks it once at the composition root: the **Windows Application Event Log** under the SCM (`EventLogBridge`), **local syslog** under systemd (`SyslogBridge`), or none for interactive/dev runs.
|
||||
|
||||
Every event uses source-generated `[LoggerMessage]` definitions, so the property names below match the message template token-for-token. The default minimum level is `Information`; lower the floor for `Mbproxy.*` categories via the standard `Logging:LogLevel` configuration to surface `Debug` events such as the coalesce and cache traces.
|
||||
|
||||
@@ -385,6 +385,51 @@ Fires whenever the entire per-PLC cache is wiped at once — primarily after a b
|
||||
|
||||
**Operator action:** none unless flushes happen on a tight loop, which would indicate the backend connection itself is unstable.
|
||||
|
||||
## Keepalive
|
||||
|
||||
See [`../Architecture/Keepalive.md`](../Architecture/Keepalive.md) for the backend heartbeat design.
|
||||
|
||||
### mbproxy.keepalive.heartbeat.sent
|
||||
|
||||
**Level:** Debug · **EventId:** 150 · **Source:** `src/Mbproxy/Proxy/Multiplexing/KeepaliveLogEvents.cs`
|
||||
|
||||
| Property | Type | Meaning |
|
||||
|----------|------|---------|
|
||||
| `Plc` | `string` | Configured PLC name. |
|
||||
| `ProxyTxId` | `ushort` | Proxy-allocated TxId carrying the synthetic FC03 probe. |
|
||||
| `Address` | `ushort` | Modbus address the probe reads (`BackendHeartbeatProbeAddress`). |
|
||||
|
||||
Fires each time the heartbeat loop issues a probe on an idle backend socket — at most one per `BackendHeartbeatIdleMs` per idle PLC.
|
||||
|
||||
**Operator action:** none. Debug-level; useful only when confirming the heartbeat is alive.
|
||||
|
||||
### mbproxy.keepalive.heartbeat.timeout
|
||||
|
||||
**Level:** Warning · **EventId:** 151 · **Source:** `src/Mbproxy/Proxy/Multiplexing/KeepaliveLogEvents.cs`
|
||||
|
||||
| Property | Type | Meaning |
|
||||
|----------|------|---------|
|
||||
| `Plc` | `string` | Configured PLC name. |
|
||||
| `ProxyTxId` | `ushort` | Proxy TxId of the unanswered probe. |
|
||||
| `ElapsedMs` | `long` | Milliseconds from probe send to timeout. |
|
||||
|
||||
Fires when a heartbeat probe is not answered within `BackendRequestTimeoutMs` — the backend is connected but no longer answering Modbus.
|
||||
|
||||
**Operator action:** check the PLC and the network path. Paired with `mbproxy.keepalive.backend.idle_disconnect` for the same PLC.
|
||||
|
||||
### mbproxy.keepalive.backend.idle_disconnect
|
||||
|
||||
**Level:** Information · **EventId:** 152 · **Source:** `src/Mbproxy/Proxy/Multiplexing/KeepaliveLogEvents.cs`
|
||||
|
||||
| Property | Type | Meaning |
|
||||
|----------|------|---------|
|
||||
| `Plc` | `string` | Configured PLC name. |
|
||||
| `ElapsedMs` | `long` | Milliseconds the failed heartbeat waited before the teardown. |
|
||||
|
||||
Fires when a failed heartbeat triggers a proactive backend teardown. Every attached upstream pipe is cascaded; clients reconnect on their next request. This is the keepalive feature doing its job — finding a dead path during idle instead of on the next real request.
|
||||
|
||||
**Operator action:** none if isolated. Repeated idle-disconnects on one PLC indicate it keeps going dark while idle — investigate the device or the network path.
|
||||
|
||||
## BCD Rewriter
|
||||
|
||||
### mbproxy.rewrite.partial_bcd
|
||||
@@ -495,5 +540,6 @@ Lifecycle events (`startup.*`, `listener.*`, `admin.*`, `shutdown.*`, `config.re
|
||||
- [Response Cache](../Architecture/ResponseCache.md) — context for the `mbproxy.cache.*` events.
|
||||
- [Status Page](../Operations/StatusPage.md) — counter equivalents for the high-volume Debug-level events.
|
||||
- [Read Coalescing](../Architecture/ReadCoalescing.md) — context for the `mbproxy.coalesce.*` events.
|
||||
- [Keepalive](../Architecture/Keepalive.md) — context for the `mbproxy.keepalive.*` events.
|
||||
- [BCD Rewriting](../Features/BcdRewriting.md) — context for the `mbproxy.rewrite.*` and `mbproxy.exception.passthrough` events.
|
||||
- [Hot Reload](../Features/HotReload.md) — context for the `mbproxy.config.reload.*` events.
|
||||
|
||||
Reference in New Issue
Block a user