Skip to content

Sentry.Log4Net silently drops log property attributes on log4net 3.x #5557

Description

@jamescrosswell

Description

Sentry.Log4Net is not compatible with log4net 3.x: every log4net event property is silently dropped from structured logs, so no property.* attributes are ever attached to a SentryLog. There is no exception and no warning — the attributes simply aren't there.

This affects the shipped package, not just the test suite. Sentry.Log4Net compiles against log4net 2.0.12, and log4net 3.x loads happily against that assembly, so any user on log4net 3.x with EnableLogs loses all their event properties today.

Root cause

SentryAppender.Structured.cs:43-45 enumerates the properties dictionary and pattern-matches each element as a DictionaryEntry:

foreach (var property in properties)
{
    if (property is DictionaryEntry { Key: string key, Value: { } value })

That shape changed between log4net majors. In 2.x, log4net.Util.PropertiesDictionary implements only the non-generic IDictionary, so IEnumerable.GetEnumerator() yields boxed DictionaryEntry. In 3.x it additionally implements IDictionary<string, object?>, and the non-generic enumerator now yields boxed KeyValuePair<string, object?>. Confirmed by reflecting over both packages:

log4net 2.0.12  PropertiesDictionary : ISerializable, IDictionary, ICollection, IEnumerable
                IEnumerable.GetEnumerator() element -> System.Collections.DictionaryEntry

log4net 3.4.0   PropertiesDictionary : IEmptyInterface, IDictionary, ICollection, IEnumerable,
                                       IDictionary<string, object>, ICollection<KVP>, IEnumerable<KVP>
                IEnumerable.GetEnumerator() element -> System.Collections.Generic.KeyValuePair<string, object>

Because the already-compiled appender walks the non-generic enumerator, the is DictionaryEntry test never matches under 3.x, the loop body never runs, and no attribute is set.

Worth noting for whoever picks this up: bumping the PackageReference alone doesn't fix it — it converts the silent failure into a compile error, because foreach (var property in properties) then binds to the generic IEnumerable<KeyValuePair<string, object?>>:

error CS8121: An expression of type 'KeyValuePair<string, object?>' cannot be handled by a pattern of type 'DictionaryEntry'

The SentryEvent path is unaffected: GetLoggingEventProperties reads via GetKeys() + the indexer, which behave identically on both majors.

Reproduction

In a checkout of main, change test/Sentry.Log4Net.Tests/Sentry.Log4Net.Tests.csproj from <PackageReference Include="log4net" Version="2.0.15" /> to Version="3.4.0", then:

dotnet test test/Sentry.Log4Net.Tests

Three tests fail (55 pass), all in the structured-logging path:

  • SentryAppenderTests.DoAppend_StructuredLogging_Properties"Expected log.Attributes to contain a single item matching attribute.Key.StartsWith("property."), but no such item was found."
  • SentryAppenderTests.DoAppend_StructuredLogging_LogEvent(withActiveSpan: False)
  • SentryAppenderTests.DoAppend_StructuredLogging_LogEvent(withActiveSpan: True) — both fail asserting property.Text-Property via test/Sentry.Testing/SentryAttributesExtensions.cs:7.

Suggested fix

Read the dictionary through GetKeys() + the indexer, the way the sibling GetLoggingEventProperties already does. That API is stable across both majors, so the appender stays version-agnostic and keeps working whether the consumer resolves log4net 2.x or 3.x.

Two follow-ups worth deciding at the same time:

  • Add coverage for log4net 3.x (a test matrix over both majors, or a second test project) so this can't silently regress again.
  • Decide whether src/Sentry.Log4Net's own PackageReference floor should move off 2.0.12 — separate from the fix above, since the fix should make the appender work on both without raising the floor.

Found while investigating log4net 3.x support; root cause verified locally against log4net 2.0.12 and 3.4.0 at 0004ef86.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETPull requests that update .net codeBugSomething isn't workingLogslog4net

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions