Repository navigation
Add LoggerSetup for AOT-compatible custom logger registration (#7902) - #8218
Merged
Aaronontheweb merged 9 commits intoSep 30, 2026
Merged
Conversation
ArinF1
force-pushed
the
feature/logger-setup-aot-7902
branch
2 times, most recently
from
May 20, 2026 19:31
1c03a87 to
6b8eeb2
Compare
…tnet#7902) - Add LoggerSetup, LoggerRegistration, LoggerSetupBuilder to Akka.Event - Modify LoggingBus.StartDefaultLoggers to check LoggerSetup before HOCON - Add unit tests in LoggerSetupSpec - Update API approval files
ArinF1
force-pushed
the
feature/logger-setup-aot-7902
branch
from
July 21, 2026 20:00
74eda91 to
2c0b994
Compare
# Conflicts: # src/core/Akka/Event/LoggingBus.cs
…afety in tests and API approvals Adds specs for a LoggerSetup logger running alongside a HOCON logger, the same type appearing in both starting once, and a LoggerSetup logger working with Akka.DynamicTypeLoading switched off. Updates the LoggerRegistration/LoggerSetupBuilder API approval entries for the ExtendedActorSystem factory type and the DynamicallyAccessedMembers annotations added during the dev merge.
Member
|
Thanks for this, @ArinF1 —
Everything's green: build, the logger/event tests, the AOT feature specs, and the API approval tests. Details are in the PR description under "Maintainer changes." Nice work, and thanks for your patience while this sat in the queue. |
…edup, generic-safe logger names Address review feedback on the additive LoggerSetup design: - LoggerSetup now mirrors ExtensionsSetup - a private constructor, an IReadOnlyList<Props>, and Create(params Props[]) / Create(IEnumerable<Props>) factories. Drops LoggerRegistration and LoggerSetupBuilder; Props.Create<T>() already carries the trimming annotations, so the extra wrapper types and DynamicallyAccessedMembers plumbing added no value. - StartDefaultLoggers checks the LoggerSetup before akka.loggers, so a type named by both is the LoggerSetup's instance that survives, matching the order ActorSystemImpl.LoadExtensions uses for ExtensionsSetup versus akka.extensions. Merges the two AddLogger overloads into one that takes Props directly; the HOCON path now builds Props.Create(type) itself. Documents the loggers-dispatcher override that applies to every logger regardless of source. - Fixes CreateLoggerName for a generic logger type: Type.Name carries a backtick-arity marker (e.g. MyLogger`1) that is not a legal actor-path character. - Replaces LoggerSetupSpec with a single generic CapturingLogger<TMarker> (a static per-closed-type instance counter, no polling) and two specs: a HOCON logger plus a LoggerSetup logger that also repeats the HOCON type, and a LoggerSetup logger starting with Akka.DynamicTypeLoading switched off. - Reverts CoreAPISpec.ApproveCore.Net.verified.txt to dev's version; updates only the DotNet variant for the new surface.
Lets a LoggerSetup carry an ILogMessageFormatter, so a third-party formatter (e.g. Akka.Logger.Serilog's SerilogLogMessageFormatter) works with Akka.DynamicTypeLoading off, the same way LoggerSetup already lets a custom logger sidestep HOCON's Type.GetType resolution. - LoggerSetup.Formatter is null by default; Settings now checks it before falling back to akka.logger-formatter, so a LoggerSetup formatter wins when present and today's HOCON path is unchanged otherwise. - Adds LoggerSetup.Create(ILogMessageFormatter, params Props[]) alongside the existing Create(params Props[]) / Create(IEnumerable<Props>); all three share one internal validation path. - Updates the akka.logger-formatter NotBuiltIn message to mention a LoggerSetup formatter as the code alternative. - Extends the dynamic-type-loading-off spec to also register a formatter and check both the Settings.LogFormatter instance and the formatted log output, and adds a precedence spec confirming the LoggerSetup formatter wins over akka.logger-formatter. - Updates the DotNet API approval file for the new member and overload.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves #7902
Adds
LoggerSetupto enable programmatic, AOT-compatible custom loggerregistration — an alternative to HOCON-based logger config, which relies
on
Type.GetType()and is not safe in AOT scenarios.Changes
Akka.Event.LoggerSetup— aSetupsubclass holding an orderedlist of logger
Props, built withLoggerSetup.Create(params Props[])or
LoggerSetup.Create(IEnumerable<Props>). It mirrors the shape ofExtensionsSetup.LoggerSetup.Formatter— an optionalILogMessageFormatter, setthrough
LoggerSetup.Create(ILogMessageFormatter, params Props[]). Thesame AOT problem that applies to a custom logger type also applies to a
third-party log message formatter — for example Akka.Logger.Serilog's
SerilogLogMessageFormatteror an NLog equivalent — sinceakka.logger-formatteralso resolves byType.GetType().LoggingBus.StartDefaultLoggers— starts theLoggerSetuploggersand the HOCON
akka.loggerslist together (see "Maintainer changes"below).
Usage
A
LoggerSetupis additive, not a replacement: the defaultakka.loggers = [DefaultLogger]keeps printing to standard outputalongside
MyCustomLoggerabove, unless you also setakka.loggers = [].Formatterworks the same way forakka.logger-formatter— it wins whenset, otherwise HOCON resolves the formatter as it does today.
Maintainer changes
I made the following changes before merge, based on review feedback:
LoggerSetupused to skipakka.loggersentirely. That silently dropped any HOCON-configured logger, including
Akka.Hosting's
LoggerFactoryLogger(written byAddLoggerFactory()).StartDefaultLoggersnow starts theLoggerSetuploggers and the HOCONlist together. A logger type named by both starts once — the
LoggerSetupis checked first and wins, the same orderActorSystemImpl.LoadExtensionsuses forExtensionsSetupversusakka.extensions. One side effect: a type repeated more than oncewithin
akka.loggersitself now also starts once, not once peroccurrence.
ExtensionsSetupshape. DroppedLoggerRegistrationandLoggerSetupBuilder—LoggerSetupnow justholds
IReadOnlyList<Props>, built withCreate(params Props[])/Create(IEnumerable<Props>).Props.Create<T>()already carries thetrimming annotations Prop-based construction needs, so the extra
wrapper types and their own
[DynamicallyAccessedMembers]plumbingadded no value.
LoggingBusnow has a singleAddLogger(system, Props, ...), and the HOCON path buildsProps.Create(type)itself.logger's
Type.Namecarries a backtick and an arity digit (e.g.MyLogger`1) that isn't a legal actor-path character;CreateLoggerNamenow swaps it out.LoggerSetup.Formatter, so a customILogMessageFormatter(Serilog, NLog, etc.) has the same code-based escape hatch a custom
logger type already gets.
Settingschecks it before falling back toakka.logger-formatter, and theNotBuiltInmessage for that settingnow mentions it as the code alternative.
devinto the branch to pick up the AOT and logger-resolutionwork that landed since this PR opened, and resolved the merge conflict
in
LoggingBus.csusing the additive design above.CapturingLogger<TMarker>(a static per-closed-type instance counter, no polling loops) and specs
covering: a HOCON logger plus a
LoggerSetuplogger that also repeatsthe HOCON type (proves the additive behavior and the dedup); a
LoggerSetuplogger and formatter both working withAkka.DynamicTypeLoadingswitched off; and theLoggerSetupformatterwinning over
akka.logger-formatterwhen both are set.CoreAPISpec.ApproveCore.DotNet.verified.txtfor the finalsurface; left
CoreAPISpec.ApproveCore.Net.verified.txtmatchingdev,since this environment can't build or verify that target.
Verified:
dotnet build -warnaserroronAkka.csproj; the Logger specs3 times each (no flakes); the Logger, Event, and
AkkaFeaturesSpecspecsin
Akka.Tests(235 passed);Akka.API.Tests(24 passed); and the trimanalyzer, which reports the same warnings as
devwith none new fromLoggerSetup.cs,LoggingBus.cs, orSettings.cs.Follow-up
Not part of this PR, but worth tracking separately:
LoggerConfigBuilder.AddLogger<T>writes a type nameinto HOCON today. It should route through
LoggerSetupinstead, nowthat one exists.
LoggerSetupexists per system — like anySetup, a secondone passed to
ActorSystemSetup.Andreplaces the first rather thanmerging with it. That is consistent with
ExtensionsSetuptoday, butit means two libraries that both want to register a logger through
LoggerSetupwill need to coordinate.