Пользовательский регистратор Windows.Extensions.Logging не используется при ведении журнала Akka.NET actor - PullRequest
0 голосов
/ 26 июня 2018

Я создал собственный регистратор для регистрации событий актера в 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?

...