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:
@@ -0,0 +1,60 @@
|
||||
namespace Mbproxy.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// The platform diagnostic sink to wire for <c>Error</c>+ events — picked once,
|
||||
/// at the composition root, by <see cref="DiagnosticSinkSelector"/>.
|
||||
/// </summary>
|
||||
internal enum DiagnosticSink
|
||||
{
|
||||
/// <summary>
|
||||
/// No platform diagnostic sink — console (and rolling-file) sinks only. Used
|
||||
/// for interactive / dev runs on every OS.
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Windows Application Event Log, via <see cref="EventLogBridge"/>. Selected
|
||||
/// only when the process is hosted as a Windows Service.
|
||||
/// </summary>
|
||||
EventLog,
|
||||
|
||||
/// <summary>
|
||||
/// Local syslog, via <see cref="SyslogBridge"/>. Selected only when the
|
||||
/// process is hosted as a systemd service on Linux.
|
||||
/// </summary>
|
||||
Syslog,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pure platform-selection logic for the <c>Error</c>+ diagnostic sink. Holds no
|
||||
/// I/O and no host APIs so it is unit-testable for every OS / host combination;
|
||||
/// the host detection itself happens in <see cref="HostingExtensions.AddMbproxySerilog"/>.
|
||||
/// </summary>
|
||||
internal static class DiagnosticSinkSelector
|
||||
{
|
||||
/// <summary>
|
||||
/// Picks the diagnostic sink for the current host:
|
||||
/// <list type="bullet">
|
||||
/// <item>Windows hosted as a Windows Service → <see cref="DiagnosticSink.EventLog"/>.</item>
|
||||
/// <item>Linux hosted as a systemd service → <see cref="DiagnosticSink.Syslog"/>.</item>
|
||||
/// <item>Everything else — interactive / dev runs, macOS, launches not owned
|
||||
/// by an init system → <see cref="DiagnosticSink.None"/>.</item>
|
||||
/// </list>
|
||||
/// The managed-service gate mirrors the original <see cref="EventLogBridge"/>
|
||||
/// contract: a diagnostic sink is wired only when an init system actually owns
|
||||
/// the process, so dev / console runs never need an Event Log source registered
|
||||
/// or a syslog socket reachable.
|
||||
/// </summary>
|
||||
/// <param name="isWindows">Running on Windows.</param>
|
||||
/// <param name="isWindowsService">Hosted by the Windows Service Control Manager.</param>
|
||||
/// <param name="isSystemd">Hosted by systemd.</param>
|
||||
public static DiagnosticSink Select(bool isWindows, bool isWindowsService, bool isSystemd)
|
||||
{
|
||||
// Windows takes precedence: isSystemd is meaningless there, and on
|
||||
// non-Windows isWindowsService is always false.
|
||||
if (isWindows)
|
||||
return isWindowsService ? DiagnosticSink.EventLog : DiagnosticSink.None;
|
||||
|
||||
return isSystemd ? DiagnosticSink.Syslog : DiagnosticSink.None;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user