C# 自定义Windows.Extensions.Logging记录器未在Akka.NET参与者日志中使用

C# 自定义Windows.Extensions.Logging记录器未在Akka.NET参与者日志中使用,c#,azure,logging,.net-core,akka.net,C#,Azure,Logging,.net Core,Akka.net,我已经在Akka.NET中创建了一个自定义日志记录器来记录参与者事件,并在web.config HOCON部分进行了设置。使用自定义日志记录程序的原因是,我可以将日志事件与我们使用的Microsoft.Extensions.Logging日志记录程序生成的其他日志一起写入Azure blob存储。我已经在Azure web应用程序设置中设置了此设置。但是,记录器默认为总线日志记录,不会写入AzureWebAppDiagnostics。我不知道如何强制它使用自定义记录器 我的web.config如

我已经在Akka.NET中创建了一个自定义日志记录器来记录参与者事件,并在web.config HOCON部分进行了设置。使用自定义日志记录程序的原因是,我可以将日志事件与我们使用的
Microsoft.Extensions.Logging
日志记录程序生成的其他日志一起写入Azure blob存储。我已经在Azure web应用程序设置中设置了此设置。但是,记录器默认为总线日志记录,不会写入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 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;
            }
        }
    }
}
在actors系统的入口点,我设置了如下日志:

<?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 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;
            }
        }
    }
}
使用Akka.Actor;
使用Akka.Configuration;
使用Microsoft.Extensions.Configuration;
使用Microsoft.Extensions.DependencyInjection;
使用Microsoft.Extensions.Logging;
使用FooProject.Actors;
使用制度;
命名空间FooProject.Actors.System
{
公共类ActorSystemPoint:IDisposable
{
public const string SystemName=“FooProject”;
private bool_disposed=false;
公共ActorSystem系统{get;private set;}
公共ActorDirectory启动()
{
var configuration=new ConfigurationBuilder()
.AddXmlFile(“web.config”)
.Build();
var container=newservicecolection()
.AddLogging()
.BuildServiceProvider();
//将Microsoft.Extensions.Logging中的iLogger工厂设置为静态属性
//因此,在创建ActorSystem之前,它可以在参与者之间共享
//当自定义记录器参与者被实例化时。
LoggerFactoryManager.LoggerFactoryInstance=container.GetService();
//加载自定义Akka配置以覆盖默认记录器参与者。
var akkaConfigString=configuration.GetSection(“akka”).GetValue(“hocon”);
var akkaConfig=ConfigurationFactory.ParseString(akkaConfigString);
System=ActorSystem.Create(SystemName,akkaConfig);
返回新的ActorDirectory();
}
公共空间关闭()
{
系统终止();
}
公共空间处置()
{
处置(真实);
}
公共无效处置(bool处置)
{
如果(!\u已处置)
{
如果(处置)
{
这是Shutdown();
}
_这是真的;
}
}
}
}
System=ActorSystem.Create(SystemName,akkaConfig)应设置日志记录。但是,当我在此之后放置断点并检查
系统
变量(类型为
Akka.Actor.Internal.ActorSystemImpl
)时,使用的记录器是
Akka.Event.busloging

我看了一下,看看是否可以理解为什么它没有使用我的自定义记录器,在第441行,我看到记录器被设置为总线日志记录-它似乎根本没有考虑配置中传递的自定义记录器


如何确保将日志写入Azure Web App Diagnostics?

我注意到您正在使用.NET Core,请注意,ASP.NET Core应用程序不会从
Web.config
(或
App.config
)读取任何配置。您应该将其用于hocon配置,并在启动时加载。Hi@FedericoDipuma,
web.config
添加到
ActorSystemPoint
中,当我在
System=ActorSystem.Create(SystemName,akkaConfig)上放置断点时,它肯定会工作行我可以看到配置已正确加载。与您的其他SO问题相同: