Я создал собственный регистратор для регистрации событий актера в Akka.NET и настроил его в разделе HOCON web.config.Причина использования специального регистратора заключается в том, что я могу записывать события журнала в хранилище BLOB-объектов Azure вместе с другими журналами, созданными используемым нами регистратором Microsoft.Extensions.Logging
.Я настроил это в настройках веб-приложения Azure.Однако по умолчанию для средства ведения журнала используется BusLogging, и запись в AzureWebAppDiagnostics не выполняется.Я не могу понять, как заставить его использовать собственный регистратор.
Мой web.config выглядит следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="akka" type="Akka.Configuration.Hocon.AkkaConfigurationSection, Akka" />
</configSections>
<akka>
<hocon>
<![CDATA[
loggers = [ "FooProject.Actors.MicrosoftExtensionsLogger, FooProject.Actors" ]
loglevel = info
log-config-on-start = on
stdout-loglevel = off
actor {
debug {
receive = on # log any received message
autoreceive = on # log automatically received messages, e.g. PoisonPill
lifecycle = on # log actor lifecycle changes
event-stream = on # log subscription changes for Akka.NET event stream
unhandled = on # log unhandled messages sent to actors
}
}
]]>
</hocon>
</akka>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" startupTimeLimit="3600" requestTimeout="23:00:00" />
</system.webServer>
</configuration>
Мой регистратор выглядит так:
using Akka.Actor;
using Akka.Dispatch;
using Akka.Event;
using Microsoft.Extensions.Logging;
using System;
namespace FooProject.Actors
{
public class MicrosoftExtensionsLogger : ReceiveActor, IRequiresMessageQueue<ILoggerMessageQueueSemantics>
{
private readonly ILoggingAdapter _log = Context.GetLogger();
private readonly ILoggerFactory _loggerFactory;
private void Log(LogEvent logEvent, Action<ILogger, string> logStatement)
{
var logger = _loggerFactory.CreateLogger(logEvent.LogClass.FullName);
logStatement(logger, logEvent.LogSource);
}
public MicrosoftExtensionsLogger()
{
_loggerFactory = LoggerFactoryManager.LoggerFactoryInstance;
_loggerFactory
.AddAzureWebAppDiagnostics()
.AddConsole()
.AddDebug();
Receive<Error>(m => Log(m, (logger, logSource) => logger.LogError(m.Cause, $"{logSource} - {m.Message}")));
Receive<Warning>(m => Log(m, (logger, logSource) => logger.LogWarning($"{logSource} - {m.Message}")));
Receive<Info>(m => Log(m, (logger, logSource) => logger.LogInformation($"{logSource} - {m.Message}")));
Receive<Debug>(m => Log(m, (logger, logSource) => logger.LogDebug($"{logSource} - {m.Message}")));
Receive<InitializeLogger>(m =>
{
var message = "MicrosoftExtensionsLogger started";
_log.Info(message);
Sender.Tell(new LoggerInitialized());
});
}
}
}
У меня есть фабрика статических регистраторов для хранения регистратора следующим образом:
using Microsoft.Extensions.Logging;
namespace FooProject.Actors
{
public class LoggerFactoryManager
{
public static ILoggerFactory LoggerFactoryInstance { get; set; }
}
}
И в точке входа для системы актеров я настроил ведение журнала следующим образом:
using Akka.Actor;
using Akka.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using FooProject.Actors;
using System;
namespace FooProject.Actors.System
{
public class ActorSystemEntrypoint : IDisposable
{
public const string SystemName = "FooProject";
private bool _disposed = false;
public ActorSystem System { get; private set; }
public ActorDirectory Startup()
{
var configuration = new ConfigurationBuilder()
.AddXmlFile("web.config")
.Build();
var container = new ServiceCollection()
.AddLogging()
.BuildServiceProvider();
// Set the ILoggerFactory from Microsoft.Extensions.Logging to a static property
// so it can be shared between actors before creating the ActorSystem, which is
// when the custom logger actor gets instantiated.
LoggerFactoryManager.LoggerFactoryInstance = container.GetService<ILoggerFactory>();
// Load custom Akka configuration to override the default logger actor.
var akkaConfigString = configuration.GetSection("akka").GetValue<string>("hocon");
var akkaConfig = ConfigurationFactory.ParseString(akkaConfigString);
System = ActorSystem.Create(SystemName, akkaConfig);
return new ActorDirectory();
}
public void Shutdown()
{
System.Terminate();
}
public void Dispose()
{
Dispose(true);
}
public void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
this.Shutdown();
}
_disposed = true;
}
}
}
}
Линия System = ActorSystem.Create(SystemName, akkaConfig);
должна настраивать ведение журнала.Однако, когда я ставлю точку останова после этого и проверяю переменную System
(типа Akka.Actor.Internal.ActorSystemImpl
), используется логгер Akka.Event.BusLogging
.
. Я посмотрел на Akka.NET источник для класса ActorSystemImpl , чтобы увидеть, смогу ли я понять, почему он не использовал мой настраиваемый регистратор, и в строке 441 я вижу, что в качестве регистратора задано значение BusLogging - похоже, он не учитывает переданный настраиваемый регистраторв конфиге вообще.
Как сделать так, чтобы мои журналы записывались в Диагностику веб-приложений Azure?