diff --git a/Directory.Packages.props b/Directory.Packages.props index 0dd9f386..460f35ac 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,6 +8,7 @@ + diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf index 1ab20df7..d64cbf11 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf @@ -7,6 +7,12 @@ # Any divergence from these defaults must be deliberate and recorded in docs/v2/Architecture.md. akka { + # Akka logger wiring (route ILoggingAdapter → Serilog) is configured via Akka.Hosting's + # ConfigureLoggers in ServiceCollectionExtensions.WithOtOpcUaClusterBootstrap — HOCON + # `akka.loggers` alone is not honored by Akka.Hosting. logger-startup-timeout is kept here + # since the Serilog logger can be slow to initialize at startup. + logger-startup-timeout = 30s + extensions = [ "Akka.Cluster.Tools.PublishSubscribe.DistributedPubSubExtensionProvider, Akka.Cluster.Tools" ] diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs index e2bab992..ad99b780 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs @@ -1,5 +1,7 @@ using Akka.Cluster.Hosting; +using Akka.Event; using Akka.Hosting; +using Akka.Logger.Serilog; using Akka.Remote.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -53,6 +55,19 @@ public static class ServiceCollectionExtensions builder.AddHocon(HoconLoader.LoadBaseConfig(), HoconAddMode.Append); + // Route Akka's internal ILoggingAdapter (DriverHostActor, DriverInstanceActor, cluster + // events, …) into Serilog so those logs reach the same sinks as the MEL/Serilog application + // logs. Akka.Hosting owns logger setup, so HOCON `akka.loggers` alone is not honored — the + // logger must be registered through ConfigureLoggers. Without this the actor graph logs only + // to the default StandardOutLogger (discarded under the Windows service host), which is why + // the driver-role actors were invisible during the 2026-06 data-plane investigation. + builder.ConfigureLoggers(setup => + { + setup.LogLevel = LogLevel.DebugLevel; + setup.ClearLoggers(); + setup.AddLogger(); + }); + builder.WithRemoting(new RemoteOptions { HostName = options.Hostname, diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ZB.MOM.WW.OtOpcUa.Cluster.csproj b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ZB.MOM.WW.OtOpcUa.Cluster.csproj index d180ed68..ccfd258f 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ZB.MOM.WW.OtOpcUa.Cluster.csproj +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ZB.MOM.WW.OtOpcUa.Cluster.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Program.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Program.cs index 256777e9..59a824a2 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Program.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Program.cs @@ -228,6 +228,14 @@ builder.Services.AddOtOpcUaHealth(); builder.Services.AddOtOpcUaObservability(builder.Configuration); var app = builder.Build(); + +// AddZbSerilog registers Serilog as the MEL logging provider but does NOT assign the static +// Serilog.Log.Logger. Set it from the DI root logger so (1) static Log.* calls like the startup +// banner below emit, and (2) Akka.Logger.Serilog's SerilogLogger — which writes to Log.Logger — +// routes the actor graph's logs (DriverHostActor et al.) to the configured sinks. Must run before +// app.RunAsync() starts the ActorSystem (the Akka logger captures Log.Logger at system start). +Serilog.Log.Logger = app.Services.GetRequiredService(); + app.UseSerilogRequestLogging(); // Razor class library static assets (_content//...) are served via endpoint