Skip to content

Suppress duplicate warning log for same application logger factory class - #19088

Merged
trask merged 16 commits into
open-telemetry:mainfrom
bhuvan-somisetty:fix/application-logging-warning
Jul 13, 2026
Merged

trask merged 16 commits into
open-telemetry:mainfrom
bhuvan-somisetty:fix/application-logging-warning

Conversation

@bhuvan-somisetty

@bhuvan-somisetty bhuvan-somisetty commented Jun 26, 2026 •

Copy link
Copy Markdown

Fixes #14889

Problem

When running a Spring Boot app with -Dotel.javaagent.logging=application, the following warning appears spuriously at startup:

WARN - ApplicationLoggerBridge - Multiple application logger implementations were provided. \
The javaagent will use the first bridge provided and ignore the following ones (this one).

Both the SLF4J LoggerFactory instrumentation point and Spring Boot's LoggingApplicationListener instrumentation point can independently call Slf4jApplicationLoggerBridge.install(), and LoggingApplicationListener#initialize() can itself run more than once during startup (e.g. for ApplicationEnvironmentPreparedEvent and ApplicationStartedEvent). Each call to install() creates a new Slf4jApplicationLoggerBridge instance and hands it to ApplicationLoggerBridge.installApplicationLogger(...), which only recognizes the first installed instance as legitimate — any subsequent install (even one backed by the exact same implementation) is treated as a conflicting bridge and logs the warning.

Fix

Guard Slf4jApplicationLoggerBridge.install() itself with a static AtomicBoolean, so it only ever hands a single instance off to ApplicationLoggerBridge.installApplicationLogger(...), no matter how many times SLF4J's LoggerFactory or Spring Boot's LoggingApplicationListener trigger it. This dedups at the source rather than asking ApplicationLoggerBridge/ApplicationLoggerFactory to recognize repeat installs of the same implementation — ApplicationLoggerFactory#install(...) is unchanged, so a second install there still correctly means a genuinely different implementation was provided and still logs the warning.

Changes

  • Slf4jApplicationLoggerBridge.java: add a static AtomicBoolean installed gate in install() so ApplicationLoggerBridge.installApplicationLogger(...) is only ever called once, regardless of how many times install() itself is invoked.
  • ApplicationLoggerInstrumentationTest.java: assert that the "Multiple application logger implementations were provided" warning never appears in the fork-based TestSpringApp output.

In Spring Boot, LoggingApplicationListener can initialize the logging
system multiple times. When the Java agent hooks into the initialization,
this triggers multiple registration calls of Slf4jApplicationLoggerBridge,
causing a warning log that multiple application logger implementations were provided.

Track the class of the registered factory and return early if a subsequent
registration is for the same factory class. A warning is still logged if
a different factory class is provided.

Fixes open-telemetry#14889

Signed-off-by: bhuvan-somisetty <somisettybhuvan5@gmail.com>
Copilot AI review requested due to automatic review settings June 26, 2026 18:44
@bhuvan-somisetty
bhuvan-somisetty requested a review from a team as a code owner June 26, 2026 18:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR suppresses a spurious WARN log emitted by the javaagent's application-logger bridge. In Spring Boot apps, LoggingApplicationListener#initialize (and/or the SLF4J LoggerFactory path) can drive multiple registration calls of the same Slf4jApplicationLoggerBridge into ApplicationLoggerFactory. Previously, every install after the first logged "Multiple application logger implementations were provided…", even when the registering factory was the identical class. The change records the class of the first successfully installed factory and short-circuits subsequent installs of the same class without warning, while still warning when a genuinely different factory class is provided. This addresses issue #14889.

Changes:

  • Track the installed factory's class (actualFactoryClass) and return early on repeat installs of the same class instead of logging a warning.
  • Preserve the existing warning behavior when a different factory class attempts to install after the first.
  • Update/add unit tests to distinguish same-class repeated installs (no warning) from different-class installs (warning), using concrete FirstFactory/SecondFactory mock targets.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
javaagent-internal-logging-application/src/main/java/io/opentelemetry/javaagent/logging/application/ApplicationLoggerFactory.java Adds actualFactoryClass field and same-class early-return in install(...) to suppress the duplicate warning.
javaagent-internal-logging-application/src/test/java/io/opentelemetry/javaagent/logging/application/ApplicationLoggerFactoryTest.java Updates the first-bridge test to use distinct factory classes and adds a test asserting same-class re-install logs no warning; introduces FirstFactory/SecondFactory test helpers.

Replace AtomicBoolean + separate volatile field with a single
AtomicReference<Class<?>> so the winning factory class is stored
atomically as part of the CAS gate. Any thread that loses the race
now always reads a non-null value from installedFactoryClass.get(),
closing the narrow window where a same-class re-install could still
emit the spurious warning.
@opentelemetry-pr-dashboard

Copy link
Copy Markdown

This PR has review comments. Review suggestions, whether from maintainers or automated reviewers, aren't always correct or required. Please evaluate each comment on its merits, then make sure each thread has a clear outcome.

For example, link to the commit if you applied a suggestion, explain why it wasn't applied, or ask a follow-up question.

Automation flags a PR for human review once every review thread has a reply or is marked as resolved.

Status across open PRs is visible on the pull request dashboard.

@laurit laurit added this to the v2.30.0 milestone Jun 30, 2026
@bhuvan-somisetty

bhuvan-somisetty commented Jul 3, 2026 •

Copy link
Copy Markdown
Author

@laurit, @trask I have updated the branch with the latest changes from main and all checks are passing. The PR is ready. Thank you!

@bhuvan-somisetty

Copy link
Copy Markdown
Author

Hi @laurit @trask — just a gentle bump on this one. It's approved and CI is green; let me know if there's anything else needed before it can be merged. Thanks for your time!

Suppressing the warning by comparing factory classes in
ApplicationLoggerFactory was checking identity at the wrong layer --
Slf4jApplicationLoggerBridge.install() always constructs a fresh
instance, so there's no meaningful "same instance" to compare there
anyway. Instead, guard install() itself with a static AtomicBoolean so
repeat calls from the slf4j LoggerFactory and Spring Boot
LoggingApplicationListener instrumentation points only ever hand off
one bridge instance downstream. ApplicationLoggerFactory goes back to
its original shape, since a second install() call now always means a
genuinely different implementation was provided.
@bhuvan-somisetty

Copy link
Copy Markdown
Author

Hey @trask @laurit, this should be good to go now — all checks are green and the earlier discussion thread is resolved. Would appreciate a look when you get a chance!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

@bhuvan-somisetty

Copy link
Copy Markdown
Author

@trask I've updated the PR description to accurately reflect the current implementation (the Copilot review flagged that it was stale, describing an earlier iteration). All CI checks are green. Ready for another look whenever you have a chance — thanks!

@trask trask left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@trask

trask commented Jul 10, 2026

Copy link
Copy Markdown
Member

@bhuvan-somisetty no need to continue merging main into your branch, we'll get this merged before the next release!

@bhuvan-somisetty

Copy link
Copy Markdown
Author

Thanks for the update! I appreciate it.

@trask

trask commented Jul 10, 2026

Copy link
Copy Markdown
Member

@bhuvan-somisetty please ask your AI to stop merging main, it's just wasting CI minutes, thanks!

@bhuvan-somisetty

bhuvan-somisetty commented Jul 10, 2026 •

Copy link
Copy Markdown
Author

Got it, will stop, sorry for the noise on CI. Thanks for your patience @trask.

@trask
trask merged commit 1575524 into open-telemetry:main Jul 13, 2026
95 checks passed
@otelbot

otelbot Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution @bhuvan-somisetty! 🎉 We would like to hear from you about your experience contributing to OpenTelemetry by taking a few minutes to fill out this survey.

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.

otel.javaagent.logging=application causes warning log

4 participants