
后端微服务【免费下载链接】akka.netCanonical actor model implementation for .NET with local distributed actors in C# and F#.项目地址https://gitcode.com/gh_mirrors/ak/akka.net点击查看免费下载在 Akka.NET 应用中ActorSystem 的日志输出通常由 Akka.NET 自身的日志事件流EventStream驱动而现代 .NET 应用往往已经统一使用Microsoft.Extensions.Logging或 Serilog 作为宿主日志框架。本文基于 Akka.Hosting 官方的 Microsoft.Extensions.Logging Integration 文档讲解如何通过AkkaConfigurationBuilder.ConfigureLoggers扩展方法统一配置 Akka.NET 的最低日志级别、日志输出器Logger、日志消息格式化器Formatter与日志过滤规则并结合src/contrib/hosting/Akka.Hosting下的源码说明每一项配置最终是如何落到 HOCON 与ActorSystem启动参数上的。读完本文你将能够把 Akka.NET 的日志完整桥接到宿主ILoggerFactory、启用 Serilog 语义日志并利用LogFilterBuilder在 Debug 级别下屏蔽无关日志噪音。一、ConfigureLoggers声明式配置 Akka.NET 日志Akka.Hosting 的核心是AkkaConfigurationBuilder定义于 AkkaConfigurationBuilder.cs它对外的日志配置入口是扩展方法ConfigureLoggers(ActionLoggerConfigBuilder)实现位于 LoggingExtensions.cs。其工作方式非常直接内部先new LoggerConfigBuilder(builder)把该 builder 交给用户的 lambda 修改最后调用setup.Build(builder)把配置结果应用到AkkaConfigurationBuilder上。官方文档给出的标准示例如下builder.Services.AddAkka(MyActorSystem, configurationBuilder { configurationBuilder .ConfigureLoggers(setup { // Example: This sets the minimum log level setup.LogLevel LogLevel.DebugLevel; // Example: Clear all loggers setup.ClearLoggers(); // Example: Add the default logger // NOTE: You can also use setup.AddLoggerDefaultLogger(); setup.AddDefaultLogger(); // Example: Add the ILoggerFactory logger // NOTE: // - You can also use setup.AddLoggerLoggerFactoryLogger(); // - To use a specific ILoggerFactory instance, you can use setup.AddLoggerFactory(myILoggerFactory); setup.AddLoggerFactory(); // Example: Adding a serilog logger setup.AddLoggerSerilogLogger(); }) .WithActors((system, registry) { var echo system.ActorOf(act { act.ReceiveAny((o, context) { Logging.GetLogger(context.System, echo).Info($Actor received {o}); context.Sender.Tell(${context.Self} rcv {o}); }); }, echo); registry.TryRegisterEcho(echo); // register for DI }); });完整的可运行示例位于仓库中的 Akka.Hosting.LoggingDemo该示例使用Host.CreateDefaultBuilder构建宿主在AddAkka中通过ConfigureLoggers设置LogLevel.DebugLevel、ClearLoggers()后AddLoggerFactory()把 Akka.NET 的全部日志事件桥接到宿主ILoggerFactory。可暴露的配置属性LoggerConfigBuilder定义于 LoggerConfigBuilder.cs文档中说明的两个关键属性在源码中的默认行为与 Akka.NET 核心默认值完全一致属性类型/默认值说明LogLevelLogLevel?默认InfoLevelAkka.NET 最低日志级别过滤器。生成 HOCON 时映射为akka.loglevelDebug/Info/Warning/Error与 akka.conf 中loglevel INFO的默认值对应LogConfigOnStartbool?默认false为true时ActorSystem 启动时以 INFO 级别输出完整 HOCON 配置便于排查到底用了哪份配置。对应 akka.conf 中的log-config-on-start off此外源码中还暴露了DeadLetterOptions、DebugOptions和LogFilterBuilder属性分别控制死信日志、调试开关与日志过滤后文详述。受支持的 Logger 注册方法文档列出的四个方法在 LoggingExtensions.cs 与 LoggerConfigBuilder.cs 中的实现如下ClearLoggers()清空已注册的 logger 类型列表。注意其效果是替换而非删除——由于生成的akka.loggers[...]以HoconAddMode.Prepend模式合并见LoggerConfigBuilder.Build清空后若不添加任何 logger核心默认值loggers [Akka.Event.DefaultLogger]仍可能作为 fallback 生效实际使用中的惯用法是ClearLoggers() 添加目标 logger使最终akka.loggers只包含你指定的类型。AddLoggerTLogger()按类型注册 logger。约束为T : IRequiresMessageQueueILoggerMessageQueueSemantics即必须是符合 Akka.NET logger actor 语义的 actor 类型如DefaultLogger、SerilogLogger。AddDefaultLogger()等价于AddLoggerDefaultLogger()即 Akka.NET 内置的控制台日志器与 akka.conf 默认注册的一致。AddLoggerFactory()添加ILoggerFactory桥接 logger下文第二节详述等价于AddLoggerLoggerFactoryLogger()。从LoggerConfigBuilder的内部实现ToConfig()LoggerConfigBuilder.cs可以看清这套 fluent API 与 HOCON 的精确对应关系// 伪代码还原ToConfig() 生成的 HOCON 片段 if (LogLevel is not null) sb.Append(akka.loglevel).AppendLine(ParseLogLevel(LogLevel).ToHocon()); if (_loggers.Count 0) sb.Append(akka.loggers[).Append(string.Join(,, _loggers.Select(t $\{t.AssemblyQualifiedName}\))).AppendLine(]); if (LogConfigOnStart is not null) sb.Append(akka.log-config-on-start).AppendLine(LogConfigOnStart.Value.ToHocon()); if (_logMessageFormatter is not null) sb.Append(akka.logger-formatter).AppendLine(_logMessageFormatter.AssemblyQualifiedName.ToHocon());也就是说fluent API 的每一次调用最终都会编译成一段 HOCON并以HoconAddMode.Prepend优先于默认配置合并进AkkaConfigurationBuilder随后由AkkaHostedService在宿主启动时用于创建ActorSystem。这解释了为什么ClearLoggers()AddLoggerFactory()能独占日志输出Prepend 合并让生成的akka.loggers覆盖了 akka.conf 的默认值。二、ILoggerFactory 桥接把 Akka.NET 日志汇入宿主日志管道Akka.Hosting 提供了一个 logger actor——LoggerFactoryLoggerLoggerFactoryLogger.cs——作为 Akka.NET 日志事件的出口把每条LogEvent转发到Microsoft.Extensions.Logging.ILoggerFactory。工作机制从源码结构看其桥接链路为工厂注入AddLoggerFactory()无参重载依赖宿主ServiceProvider中注册的ILoggerFactory带参重载AddLoggerFactory(ILoggerFactory)则会先向 builder 添加一个LoggerFactorySetupLoggerFactorySetup.cs把你显式传入的工厂实例注入ActorSystem的Setup。构造校验LoggerFactoryLogger构造函数从Context.System.Settings.Setup.GetLoggerFactorySetup()读取工厂若缺失则抛出ConfigurationException——这保证了忘记注册 factory在启动时立即失败而不是静默丢日志。级别映射GetLogLevel方法把 Akka.NET 的Event.LogLevel映射为 M.E.Logging 的LogLevelDebugLevel→Debug、InfoLevel→Information、WarningLevel→Warning、ErrorLevel→Error。结构化日志增强Log(LogEvent, ActorPath)方法中若LogEvent携带语义化属性log.TryGetProperties(out var properties)则构造AkkaLogStateAkkaLogState.cs把ActivityContextAkka.NET 1.5.59 的 OpenTelemetry 链路追踪上下文、结构化属性、ActorPath、时间戳、线程 ID、LogSource、模板与格式化消息一并传给_akkaLogger.Log(...)最终由宿主日志管道console、文件、ELK 等统一输出若消息格式化失败SafeFormat会退化为输出模板与未格式化参数避免日志本身抛异常。测试佐证仓库中的 LoggerFactoryLoggerSpec.cs 验证了端到端行为注册一个TestLoggerFactory后通过AddAkka→ConfigureLoggers→ClearLoggers()AddLoggerFactory(new TestLoggerFactory(logger))启动宿主actor 产生的日志即可被测试端捕获断言。三、Serilog 消息格式化语义日志开箱可用如果你使用Akka.Logger.Serilog包Akka.Hosting 支持把 Akka.NET 的默认 logger 与消息格式化器一次性切换为 Serilog从而全局启用 Serilog 的语义化模板式日志。文档给出的配置为builder.Services.AddAkka(MyActorSystem, configurationBuilder { configurationBuilder .ConfigureLoggers(setup { // Example: This sets the minimum log level setup.LogLevel LogLevel.DebugLevel; // Example: Clear all loggers setup.ClearLoggers(); // Add Serilog setup.AddLoggerSerilogLogger(); // use the default SerilogFormatter everywhere setup.WithDefaultLogMessageFormatterSerilogLogMessageFormatter(); }) .WithActors((system, registry) { var echo system.ActorOf(act { act.ReceiveAny((o, context) { Logging.GetLogger(context.System, echo).Info($Actor received {o}); context.Sender.Tell(${context.Self} rcv {o}); }); }, echo); registry.TryRegisterEcho(echo); // register for DI }); });这样做的好处是消除了在每个使用点写Context.GetLoggerSerilogLoggingAdapter()的需要——Logging.GetLogger(...)返回的普通 adapter 输出的消息也会经过 Serilog 模板格式化。从 LoggerConfigBuilder.cs 的源码注释还能得到一个重要的版本事实自 Akka.NET 1.5.58 起SemanticLogMessageFormatter已是ActorSystem的默认格式化器对应 akka.conf 中的logger-formatter Akka.Event.SemanticLogMessageFormatter, Akka因此WithDefaultLogMessageFormatterT()方法已被标记为[Obsolete]注释明确写道仅在拥有自定义ILogMessageFormatter实现时才需要。换句话说使用 Serilog 时WithDefaultLogMessageFormatterSerilogLogMessageFormatter()仍然必要——SerilogLogMessageFormatter不属于内置特例且必须带空构造函数ToConfig()会把它序列化为akka.logger-formatter ...与 utilities/serilog 文档 中 HOCON 方式的等价配置akka.logger-formatterAkka.Logger.Serilog.SerilogLogMessageFormatter, Akka.Logger.Serilog一致。若只是想让 Akka.NET 使用语义化日志而不引入 Serilog则无需任何额外配置SemanticLogMessageFormatter默认生效。LogMessageFormatter属性的 setter 还会做类型校验类型必须实现ILogMessageFormatter非内置类型必须提供空构造函数否则在配置阶段即抛出ConfigurationException把错误提前到启动时暴露。四、双重过滤器akka.loglevel 与 Microsoft.Extensions.Logging当LoggerFactoryLogger作为出口时日志实际上要穿过两道过滤器Akka.NET 侧的akka.loglevel即LoggerConfigBuilder.LogLevel——决定哪些LogEvent会进入 logger actor 的事件流M.E.Logging 侧的 provider/category 过滤——决定进入ILoggerFactory后哪些日志最终被 provider 输出。文档特别强调两者必须配合设置否则会出现日志莫名缺失。M.E.Logging 侧的过滤通过appsettings.json配置例如{ Logging: { LogLevel: { Default: Information, Microsoft: Warning, Microsoft.Hosting.Lifetime: Information, Akka: Debug } } }其中Akka: Debug一行很关键LoggerFactoryLogger内部使用_loggerFactory.CreateLoggerActorSystem()创建 logger其 category 归属于Akka命名空间若该命名空间被默认规则压到Information及以上即便setup.LogLevel LogLevel.DebugLevelDebug 级日志也会在第二道过滤中被丢弃。这正是两道闸门、缺一不可的典型场景。五、按 LogSource 或消息内容过滤LogFilterBuilder 的两种用法Akka.NET 1.5.21 引入了基于LogSource或消息内容的日志过滤能力见 utilities/logging 文档 的 Filtering Log Messages 一节其核心是LogFilterBuilderLogFilter.cs。在 Akka.Hosting 中文档介绍了两种等价的使用方式。方式一使用WithLogFilter()方法builder.Services.AddAkka(MyActorSystem, configurationBuilder { configurationBuilder .ConfigureLoggers(loggerConfigBuilder { loggerConfigBuilder.WithLogFilter(filterBuilder { filterBuilder.ExcludeMessageContaining(Test); }); }); });方式二直接设置LogFilterBuilder属性builder.Services.AddAkka(MyActorSystem, configurationBuilder { configurationBuilder .ConfigureLoggers(loggerConfigBuilder { loggerConfigBuilder.LogFilterBuilder new LogFilterBuilder(); loggerConfigBuilder.LogFilterBuilder.ExcludeMessageContaining(Test); }); });从 LoggerConfigBuilder.cs 的Build方法可以看出LogFilterBuilder不会生成 HOCON而是被编译为LogFilterSetup实现Akka.Actor.Setup.Setup接口通过builder.AddSetup(...)附加到 ActorSystem 的程序化配置中最终随ActorSystem创建时生效。LogFilterBuilder支持的规则分为两类ExcludeSourceExactly/ExcludeSourceStartingWith/ExcludeSourceContaining/ExcludeSourceEndingWith/ExcludeSourceRegex基于LogSource过滤无需展开消息体资源开销很小ExcludeMessageContaining/ExcludeMessageRegex/ 以及通过Add(LogFilterBase)注入自定义过滤器基于消息内容过滤需要先完整展开日志消息开销相对更大。只要任意一条规则返回LogFilterDecision.Drop该条日志即被排除。这类过滤的典型用途是把setup.LogLevel开到DebugLevel排查问题同时用ExcludeSource*/ExcludeMessage*规则屏蔽高频噪音来源做到高保真 可降噪。相关行为可由 LogFilterEvaluatorSpecs.cs 与 LoggerConfigBuilderSpecs.cs 等测试用例验证。六、小结与延伸阅读Akka.Hosting 的日志配置遵循一条清晰的主线ConfigureLoggers以 fluent 方式收集LogLevel、logger 类型、LogConfigOnStart与 formatterToConfig()将其编译为akka.loglevel/akka.loggers/akka.log-config-on-start/akka.logger-formatter四段 HOCON 并以 Prepend 模式覆盖核心默认值LoggerFactoryLoggerLoggerFactorySetup则把 Akka.NET 的LogEvent流桥接进宿主ILoggerFactory并附带级别映射、结构化属性与ActivityContext链路信息LogFilterBuilder以Setup而非 HOCON 的形式补充了按来源/内容过滤的能力。如需继续深入可参考仓库内以下资料Akka.Hosting 总览 ——AkkaConfigurationBuilder、ActorRegistry与各扩展包的完整介绍Akka.NET 日志系统文档 —— 核心日志事件流、formatter 与日志过滤机制的底层说明Serilog 集成文档 —— HOCON 方式配置SerilogLogger与SerilogLogMessageFormatter的完整对照LoggingDemo 示例 —— 可直接运行的 ILoggerFactory 桥接示例Akka.Hosting 日志测试集 —— 覆盖LoggerConfigBuilder、LoggerFactoryLogger、语义日志与上下文传递的端到端规格。赞分享后端微服务【免费下载链接】akka.netCanonical actor model implementation for .NET with local distributed actors in C# and F#.项目地址https://gitcode.com/gh_mirrors/ak/akka.net点击查看免费下载相关推荐Flecs日志系统自定义日志输出与过滤Flecs日志系统自定义日志输出与过滤 你是否在调试Flecs应用时被大量日志淹没是否需要将关键错误信息定向到特定监控系统本文将详细介绍如何通过Flecs游戏开发gh_mirrors/presentations170/presentations完全指南从会议演讲到提案的终极资源库gh_mirrors/presentations170/presentations完全指南从会议演讲到提案的终极资源库 在技术会议和开发者社区中高质量的演讲如何快速获取中小学智慧教育平台电子课本PDF下载终极指南如何快速获取中小学智慧教育平台电子课本PDF下载终极指南 还在为无法下载国家中小学智慧教育平台的电子课本而烦恼吗tchMaterial parser电子课本网页爬虫教育创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考