Skip to content

Structured log can emit a duplicate "event" key when the event-name tag collides with a user key #116

@OmarAlJarrah

Description

@OmarAlJarrah

Summary

LoggingEvent.log() always emits the event-name tag under the reserved EVENT_KEY ("event") key via addKeyValue(EVENT_KEY, …) whenever .event(name) was called with a non-empty name. Unlike the other three key sources (global context, MDC, and per-event field(...)), this emission is not de-duplicated against anything.

Because SLF4J's addKeyValue appends rather than replaces, a user-supplied key named "event" produces a second KeyValuePair with the same name on the event, which serializes to invalid duplicate-key JSON in JSON appenders.

This is the same failure class as #12 (fixed for the global-context/field overlap in #81), but on the event-name code path, which no dedup guard covers.

Reproduction

// event-name tag + a field named "event" → two `event` entries
logger.atInfo().event("request.start").field("event", "override").log()

It also happens when the logger's global context carries an "event" key and .event(name) is called: the global-context loop emits one event entry and the name tag emits another.

Expected

The "event" key appears at most once on an event, consistent with the guarantee #81 established for the global-context / MDC / field sources.

Notes

EVENT_KEY is a public constant ("event"), so user code can legitimately collide with it. A fix needs a precedence decision:

  • the event-name tag wins (skip any user "event" key), or
  • treat "event" as reserved — reject/ignore it from field(...) and the context, or
  • the per-event field wins (mirroring the existing "fields win" semantics), emitting the name tag only when no "event" key is otherwise present.

Whichever is chosen, the dedup should cover all sources plus the name tag, with a regression test alongside the existing …emitted exactly once tests in LoggingEventTest.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsdk-coresdk-core toolkit

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions