Skip to content

Fix SimpleLoggingAdvice configuration breakage from the MS logging migration - #346

Merged
lahma merged 1 commit into
mainfrom
simple-logging-advice
Aug 8, 2026
Merged

Fix SimpleLoggingAdvice configuration breakage from the MS logging migration#346
lahma merged 1 commit into
mainfrom
simple-logging-advice

Conversation

@lahma

@lahma lahma commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Fixes #341.

The Common.Logging → Microsoft.Extensions.Logging migration (fda46d9, #267) broke SimpleLoggingAdvice in two ways for anyone upgrading from ≤3.0.2:

  1. Legacy level names rejected. <property name="LogLevel" value="Info"/> throws TypeMismatchException, because MEL's LogLevel has Information/Warning/Critical/None where Common.Logging had Info/Warn/Fatal/Off/All. The reference docs and example configs still use the old spellings.
  2. Silent advice. AbstractLoggingAdvice resolved its static logger eagerly in the constructor. With LogManager.LoggerFactory typically still unset while the container builds the advice, that cached NullLogger.Instance forever — assigning the factory afterwards had no effect. The default log category was also always AbstractLoggingAdvice (a MethodBase.GetCurrentMethod().DeclaringType accident), never the concrete advice type, so category-based filter rules didn't match.

Changes

  • New LogLevelConverter (Spring.Core, registered in TypeConverterRegistry): accepts the legacy Common.Logging names case-insensitively — AllTrace, InfoInformation, WarnWarning, FatalCritical, OffNone — and delegates everything else to EnumConverter. Pre-3.0 XML configs (and the shipped reference docs/examples using value="Info") work again. LogExceptionHandler.LogLevel gains the same support for free.
  • Lazy logger resolution in AbstractLoggingAdvice: SetDefaultLogger now only stores the category name; the logger is resolved through LogManager per invocation (MEL's LoggerFactory caches loggers by category, so this matches the cost profile dynamic mode always had). A LogManager.LoggerFactory assigned any time before the first intercepted call now takes effect. This also keeps a deserialized static-mode advice in static mode (defaultLogger is [NonSerialized]; the name survives).
  • Default category is now the concrete advice type (e.g. Spring.Aspects.Logging.SimpleLoggingAdvice), consistent with what the UseDynamicLogger = false setter path already did and with Java Spring's getClass() behavior.

Behavior changes to be aware of

  • The static-mode default category changes from Spring.Aspects.Logging.AbstractLoggingAdvice (accidental) to the concrete advice type's full name. Filter rules keyed on the old name need adjusting.
  • The protected defaultLogger field now strictly means "explicitly supplied logger"; in named-logger mode it stays null and resolution goes through LogManager per invocation.

Note for the issue reporter

The other half of #341 — no output even with Information — is expected in 3.x until Spring.LogManager.LoggerFactory is assigned (Common.Logging's app.config auto-configuration is gone). E.g. for log4net: LogManager.LoggerFactory = LoggerFactory.Create(b => b.AddLog4Net());. With this PR a factory assigned even after the context is built is picked up.

Follow-up (not in this PR)

LogExceptionHandler builds a SpEL expression #log.Information(...) etc. — those instance methods don't exist on MEL ILogger (they're LogXxx extension methods), so its log action silently fails; needs a separate fix.

Verification

  • New unit tests: converter (legacy/canonical/case-insensitive/numeric/invalid names), registry lookup, TypeConversionUtils end-to-end, late LoggerFactory wiring, default category, and an XmlObjectFactory repro of the exact config from the issue.
  • dotnet build Spring.Net.sln clean; full Spring.Aop.Tests and Spring.Core.Tests suites green on net8.0 and net462 (only known-local-env failure FormatUsingDefaults unrelated to this change).

🤖 Generated with Claude Code

- Accept legacy Common.Logging level names (All, Info, Warn, Fatal, Off)
  when converting strings to Microsoft.Extensions.Logging.LogLevel via a
  new LogLevelConverter registered in TypeConverterRegistry
- Resolve named advice loggers lazily so a LogManager.LoggerFactory
  assigned after the advice was constructed still takes effect (also
  keeps a deserialized static-mode advice in static mode)
- Use the concrete advice type as the default log category instead of
  always AbstractLoggingAdvice

Fixes #341

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lahma
lahma merged commit 10ba4cb into main Aug 8, 2026
2 of 3 checks passed
@lahma
lahma deleted the simple-logging-advice branch August 8, 2026 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to configure simpleLoggingAdvice in latest version

1 participant