Skip to content

[java] Make selenium.debug/webdriver.verbose configure the real logger - #17832

Open
MohabMohie wants to merge 18 commits into
SeleniumHQ:trunkfrom
MohabMohie:debug-logging-consistency-mechanism
Open

[java] Make selenium.debug/webdriver.verbose configure the real logger#17832
MohabMohie wants to merge 18 commits into
SeleniumHQ:trunkfrom
MohabMohie:debug-logging-consistency-mechanism

Conversation

@MohabMohie

@MohabMohie MohabMohie commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

📋 Executive Summary

(kept up to date after every commit on this PR)

What changed: -Dselenium.debug=true, its legacy twin -Dselenium.webdriver.verbose=true,
and SE_DEBUG now all do the same real thing — raise the actual org.openqa.selenium JUL logger
to FINE and attach a Selenium-owned handler, instead of each switch silently changing what a
handful of hand-picked call sites individually decide to report. The switch is live: flipping it
mid-run takes effect for every driver constructed afterward, not just ones created before the
JVM's first driver class loaded.

Why it's worth merging: it closes the long-standing inconsistency from #12892 ("some things
are logged this way and some things aren't") with one real mechanism instead of another one-off
patch, fixes a genuine duplicate-INFO-output bug for existing SE_DEBUG users, and — across two
rounds of review on this PR — also fixes several independently-discovered real bugs it would
otherwise have introduced or left standing: an already-more-verbose logger level getting silently
demoted to FINE; RetryRequest's log level going stale once the switch became toggleable at
runtime; a null-Capabilities NPE in RemoteWebDriver's 3-arg constructor that contradicted its
own documented "null means empty" contract; and two classes (bidi/devtools Connection) plus
Grid's external-JUL-config startup path that could construct without ever raising the logger at
all.

How to use it: nothing changes for existing users of either switch — same properties, same
SE_DEBUG variable, just more consistent and more visible output. Set -Dselenium.debug=true (or
SE_DEBUG) and read Selenium's own FINE-level diagnostics through whatever logging setup you
already have; no new API surface, no migration needed.

Status: mechanism + all 9 original automated review findings addressed, plus both follow-ups
tracked at #17833 landed on this same PR as additional commits: the pre-existing second-driver
discovery-logging gap (#17834, fixed at the single DriverFinder.getBinaryPaths() chokepoint every
driver construction path — including InternetExplorerDriver, previously uncovered even for the
first driver — funnels through) and the full mechanical migration of the remaining
getDebugLogLevel() call sites across 14 files (#17835) off the deprecated method onto a fixed
Level.FINE. A second review round then surfaced 10 more findings, now also landed on this PR: the
RemoteWebDriver null-capabilities NPE fix (with regression test), two retry/registration-failure
log sites bumped from FINE to WARNING since they're bounded, actionable, operationally-visible
events rather than routine chatter, Debug.configureLogger() added to bidi/devtools
Connection's constructors and to Grid's external-JUL-config startup path (both previously able to
run with the logger never raised), and property-fixture hygiene fixes across five test files so
selenium.webdriver.verbose is cleared/restored alongside selenium.debug everywhere. One
adjacent, out-of-scope fixture-hygiene gap in DriverFinderTest found during that pass is tracked
separately at #17836.

An independent third-pass review then surfaced one more real bug and three test-coverage gaps, now
also landed on this PR: LoggingOptions.configureLogging()'s pre-existing handler-cleanup loop
(enumerates every registered logger and strips its handlers) was silently removing the handler
Debug.configureLogger() had just installed one line above, since Debug holds a strong static
reference that keeps org.openqa.selenium registered too -- fixed by having that loop skip it by
name, rather than reordering the call (reordering would have broken the existing
external-JUL-config early-return case). Regression tests were added proving
RedisBackedNodeRegistry's WARNING-level registration-failure log (already correct, just untested)
actually fires, proving devtools.Connection's constructor actually configures the debug logger
when built directly (bypassing RemoteWebDriver/DriverFinder), and de-mocking
RemoteWebDriverInitializationTest's null-capabilities regression test onto a plain
CommandExecutor lambda, matching this file's other de-mocked test. One qodo finding remains open
on this PR (DriverFinderTest's discovery-regression test using a Mockito-backed DriverService):
it does not actually fall under #17836 as this PR previously assumed -- #17836 tracks an unrelated
selenium.webdriver.verbose fixture-hygiene gap in the same file, not the mocking-style finding.
Left unresolved pending a decision on how to track it. Otherwise nothing further planned on this
PR; ready for another review pass.

🔗 Related Issues

Closes #12892
Closes #17834
Closes #17835

Design rationale (the five-options analysis behind choosing option 4) was
worked through in ShaftHQ/SHAFT_ENGINE#4307; linked for reviewer context
only.

💥 What does this PR do?

Selenium Java currently has two separate, disconnected answers to "how do I
turn on debug logging?" -Dselenium.debug=true (and its older twin
-Dselenium.webdriver.verbose=true) changes what severity roughly 64
hand-picked log statements report at — INFO instead of FINE — without
touching the real logger at all. SE_DEBUG does something completely
different: it raises the actual org.openqa.selenium logger to FINE and
attaches a handler. Titus put it plainly when he opened #12892: "right now
some things are logged this way and some things aren't and I think we need
to be consistent one way or another."
This PR makes them consistent by
making -Dselenium.debug=true/-Dselenium.webdriver.verbose=true do what
SE_DEBUG already does.

Of the five options Titus laid out in #12892 — (1) deprecate both properties
and delete Debug entirely, (2) move all general-debug logging onto
getDebugLogLevel(), (3) drop the -agentlib:jdwp debugger auto-detection,
(4) change the real logger level instead of the reported level, (5) make the
switch work if flipped mid-run — this PR adopts option 4 as the
mechanism. Option 5 comes along for free as a consequence. Option 2 does
not: the ~64 getDebugLogLevel() call sites still report at INFO while
everything else reports at FINE, so what they log is now consistently
visible but not consistently levelled — migrating them is the mechanical
follow-up noted below. Option 3 is already merged, separately, in #16584.
Option 1 is not adopted; see Implementation Notes.

Behavior changes — several are real and deliberate:

You're already using SE_DEBUG:

  • Selenium's own added handler now filters out INFO-and-above records.
    Previously it had no filter, so if you were relying on the default JVM
    root ConsoleHandler, you'd have seen every INFO+ record from
    org.openqa.selenium printed twice (once from the root handler, once
    from Selenium's own unfiltered one). That duplicate is gone — no visible
    change for the common case.
  • If you have your own logging setup — e.g. you called
    Logger.getLogger("org.openqa.selenium").setUseParentHandlers(false), or
    stripped the root logger's handlers — you were relying on Selenium's own
    (previously unfiltered) handler as your only source of INFO+ output from
    this logger. You will now see less output than before: Selenium's
    handler only surfaces FINE-and-below. This is a real, if narrow, behavior
    change, not just a bugfix.
  • Driver-discovery logging (Selenium Manager / driver download diagnostics)
    is now reliably visible again for the first driver constructed in a JVM
    when SE_DEBUG is set at JVM start (see Implementation Notes for the
    precise limit of this).

You're using -Dselenium.debug=true or -Dselenium.webdriver.verbose=true
today:

  • Your debug output gets louder: every FINE-level record under
    org.openqa.selenium is now visible, not just the ~64 lines previously
    promoted to INFO. Deliberate, but a real, noticeable change in output
    volume.
  • A property change made after the JVM has already loaded
    RemoteWebDriver now actually takes effect for drivers constructed
    afterward (previously impossible: frozen in a static block at
    class-load time).
  • On Grid, this switch now also forces the Grid log level to FINE
    (previously only SE_DEBUG did) — otherwise Grid operators using this
    property would silently lose Grid diagnostics under the new mechanism.

Calling the deprecated getDebugLogLevel() directly: no change. Marked
@Deprecated(forRemoval = true) but returns exactly what it always did.

Testing:

New DebugTest, no mocks, real Logger/Handler/System.setProperty with
save-and-restore: live property read, legacy selenium.webdriver.verbose,
level raising, reversibility (including the compare-and-restore fix, proven
by changing the level a second time after turning debugging on),
idempotency, user-installed handlers left alone, INFO-and-above records not
duplicated (proven by capturing actual published records through a stub
handler, not just asserting the filter's own verdict against itself), and
the deprecated method's unchanged return values.

New RemoteWebDriverInitializationTest case proving the constructor-level
fix specifically (constructs twice, since the static block only fires once
per JVM).

New LoggingOptionsTest (this class had zero coverage before), proving
-Dselenium.debug=true now also forces Grid's log level to FINE.

Not unit-tested (needs a real browser): manually verify
System.setProperty("selenium.debug","true"); new ChromeDriver(); prints
FINE records to stderr.

🔧 Implementation Notes

Why option 4, not option 1 (deleting Debug)? Titus attached a
reservation to option 4 itself: "this could break things for users if they
have other implementations."
Read at face value that applies to any
implementation of option 4, including this one, so it's worth stating
exactly how far this PR goes. The sketch in the issue sets the level on
every handler of the root logger, globally and irreversibly. This PR
doesn't do that: it only touches the org.openqa.selenium logger by name,
adds one handler Selenium owns and can remove again, and never mutates a
handler it didn't create. It's also not new: this is exactly what
Debug.configureLogger() has already been doing for SE_DEBUG since
#16816/#16900/#17009. This PR's claim is "stop
maintaining a second, Java-only mechanism next to the one already shipped
and working," not "introduce something new."

@asolntsev, who wrote the prior-art PR #16584 in this same area, has said
he'd prefer deleting Debug outright (option 1). This PR goes with option 4
instead because the selenium.debug/
selenium.webdriver.verbose properties are the shipped, user-facing surface
(the class itself lives in org.openqa.selenium.internal), isDebugging()
gates a security-relevant branch (see Additional Considerations), and
removing the properties would take away the documented easy switch with
nothing to migrate users to. Titus himself called option 1 "too drastic" in
the issue, while staying open to it if agreed.

Known gaps:

  1. The reversibility guarantee has one inherent edge case.
    configureLogger() restores the pre-debug level on turn-off unless
    something else changed the level in between (in which case that external
    change is correctly left alone — the compare-and-restore fix in this
    PR). But JUL has no level-change listener, so if that external override
    happens to set the level to exactly Level.FINE (the same value Debug
    itself sets), configureLogger() can't tell the two apart. In that one
    case, turn-off still restores the pre-debug level and silently overrides
    that deliberate FINE. Inherent to a snapshot-based approach without a
    real listener API; not fixed by this PR.

  2. The static-initializer fix for early driver-discovery logging only
    covers the first driver built in a JVM. RemoteWebDriver's static
    initializer (JLS 12.4.2) is guaranteed to run once, before any subclass
    constructor body — including argument expressions passed to a
    subclass's own super(...) call, which is where
    ChromeDriver/FirefoxDriver perform DriverFinder/SeleniumManager
    discovery logging. That's covered for the first driver instance. For a
    second driver, if the debug switch gets flipped between the first and
    second construction, that second driver's own discovery logging still
    runs before configureLogger() is reached via the instance constructor
    — still missed. Same gap that has always existed on trunk; this PR
    narrows it (first-driver case now works), doesn't close it.

  3. Grid stdout/stderr routing is now inconsistent between the two
    switches. LoggingOptions.setLoggingLevel() now honors both
    -Dselenium.debug=true and SE_DEBUG for the FINE level.
    LoggingOptions.getOutputStream() (unchanged by this PR) still keys
    only on SE_DEBUG for stdout vs. stderr. Net effect: on Grid,
    -Dselenium.debug=true sends FINE output to stdout while
    SE_DEBUG=true sends it to stderr. Not a regression; not fixed here.

🤖 AI assistance

  • No substantial AI assistance used
  • AI assisted (complete below)
    • Tool(s): Claude (Anthropic)
    • What was generated: initial implementation, an independent adversarial
      code-review pass that found the two defects fixed in the second
      commit (stale-snapshot clobbering on turn-off, and the dropped
      static-initializer coverage for driver-discovery logging), the
      follow-up fix pass for those defects, and this PR description.
      Human-directed and human-reviewed throughout; I own the design
      decisions and can explain every change in this diff.
    • I reviewed all AI output and can explain the change

💡 Additional Considerations

🔄 Types of changes

  • Bug fix (backwards compatible)
  • New feature (non-breaking change which adds functionality and tests!)

Bug fix: the debug properties now control the real logger, and SE_DEBUG's
duplicate INFO output is gone. New feature: flipping the switch mid-run now
works, and -Dselenium.debug=true now also raises Grid's log level — both
tested. Not marked breaking: no API surface changes; the shifts under the
existing switches are in output volume/visibility, with the one narrow
exception (custom logging setups relying on Selenium's previously
unfiltered handler) called out under Behavior changes above.

Debug.isDebugging() was cached in a static block at class-load time, so
changing selenium.debug or selenium.webdriver.verbose mid-run had no
effect, and getDebugLogLevel() shifted individual log statements between
INFO and FINE instead of touching the logger itself. This was a second,
Java-only mechanism alongside SE_DEBUG's Debug.configureLogger(), which
already does the right thing: raise the real org.openqa.selenium logger
to FINE and attach a handler.

Make isDebugging() a live property read instead of a cached static
field. Widen configureLogger() to fire for isDebugging() as well as
isDebugAll(), and make it idempotent (tracks the handler it installed)
and reversible (removes exactly that handler and restores the previous
logger level when every switch turns back off). Attach the handler at
FINE with a filter that excludes INFO-and-above so it never duplicates
records the caller's own handlers already print. Move the
configureLogger() call out of RemoteWebDriver's static initializer and
into its canonical constructor so a property change made after the
class has already loaded still takes effect for drivers constructed
afterwards. Extend LoggingOptions.setLoggingLevel() to also honor
isDebugging(), so Grid operators using -Dselenium.debug=true don't lose
Grid diagnostic output now that SE_DEBUG is no longer the only switch
configureLogger() reacts to.

getDebugLogLevel() is deprecated for removal; its behavior is
unchanged (still INFO while debugging, FINE otherwise) and existing
call sites keep working, pointing callers at the logger-based
mechanism instead.

Adds DebugTest with no mocks, exercising the live property read, the
legacy verbose property, idempotency, reversibility, and that the
installed handler leaves the caller's own handlers untouched.
Two defects found by review of the previous commit, both reproduced
with a failing test first:

Debug.configureLogger() clobbered a logger level set by something
else after debugging was turned on. Turning debugging back off
restored a stale snapshot taken when debugging was turned on, even if
the level had since changed again in between. Now it only restores the
snapshot if the logger's current level still matches the FINE it set;
otherwise something else already overrode it and that override is left
alone.

RemoteWebDriver's static initializer was dropped in the earlier commit
in favor of calling configureLogger() from the canonical constructor.
That regresses coverage: driver subclasses like ChromeDriver and
FirefoxDriver perform driver-discovery logging (DriverFinder,
SeleniumManager) as part of computing arguments to their own super(...)
call, which runs before RemoteWebDriver's constructor body ever
executes. Only the class's static initializer, guaranteed by JLS
12.4.2 to run before any subclass constructor body, catches that.
Restored the static initializer alongside the constructor call;
configureLogger() is idempotent so both are safe to keep, each
covering a different gap.

Also strengthens the test suite: the reversibility test now changes
the level a second time after turning debugging on and asserts the
newer value survives, instead of setting it before turning on, which
made the bug impossible to observe. The INFO-duplication test now
captures and counts actual published records through a stub handler
plus captured stderr output, instead of only asserting the handler's
own isLoggable() result against its own filter. Adds a constructor
wiring test for RemoteWebDriver and a small new test package for
LoggingOptions, which had no coverage before this change.
@selenium-ci selenium-ci added B-grid Everything grid and server related C-java Java Bindings B-build Includes scripting, bazel and CI integrations labels Jul 28, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

[Java] Unify debug switches with Selenium logger configuration

🐞 Bug fix ✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Unifies Java debug switches by configuring the Selenium logger at FINE.
• Supports runtime property changes while preserving user logger levels and handlers.
• Aligns Grid logging and adds lifecycle, filtering, and initialization regression coverage.
Diagram

graph TD
  A["Debug switches"] --> B["Debug state"] --> C{"Debug enabled?"}
  C -->|Yes| D["FINE logger"] --> E["Filtered handler"]
  C -->|No| F["Restore logger"]
  G["Driver creation"] --> B
  B --> H["Grid logging"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Remove legacy debug properties
  • ➕ Eliminates the duplicate Java-specific debug mechanism.
  • ➕ Reduces global logger mutation and long-term maintenance.
  • ➖ Breaks users relying on established system properties.
  • ➖ Requires a deprecation cycle and migration guidance.
2. Migrate every debug call site
  • ➕ Makes all debug records consistently use FINE.
  • ➕ Removes the need for getDebugLogLevel entirely.
  • ➖ Creates a much larger mechanical change across many call sites.
  • ➖ Raises review scope and regression risk beyond the logger consistency fix.

Recommendation: Adopt the PR's centralized, reversible logger configuration as the compatibility-preserving fix. It aligns existing switches with standard JUL behavior without deleting supported properties; migrating remaining getDebugLogLevel call sites should remain a focused follow-up.

Files changed (8) +452 / -19

Bug fix (3) +69 / -19
LoggingOptions.javaHonor Java debug properties in Grid logging +3/-2

Honor Java debug properties in Grid logging

• Forces Grid logging to FINE when either Java debug property or SE_DEBUG is enabled. Expands the warning to identify every supported debug switch.

java/src/org/openqa/selenium/grid/log/LoggingOptions.java

Debug.javaMake debug logger configuration live and reversible +55/-16

Make debug logger configuration live and reversible

• Reads debug properties dynamically and configures the real org.openqa.selenium logger for every supported switch. Logger changes are synchronized, idempotent, reversible, preserve external level overrides, and use a Selenium-owned handler filtered below INFO to prevent duplicate output. Deprecates getDebugLogLevel for eventual removal while retaining its current behavior.

java/src/org/openqa/selenium/internal/Debug.java

RemoteWebDriver.javaReconcile debug logging during driver construction +11/-1

Reconcile debug logging during driver construction

• Retains early static logger setup for subclass initialization and adds configuration to the canonical constructor. Newly constructed drivers therefore observe debug properties changed after RemoteWebDriver was loaded.

java/src/org/openqa/selenium/remote/RemoteWebDriver.java

Tests (3) +368 / -0
LoggingOptionsTest.javaVerify Grid handling of selenium.debug +86/-0

Verify Grid handling of selenium.debug

• Tests that selenium.debug forces Grid logging to FINE and emits the warning, while an inactive switch does not. Restores the process-wide property after each test.

java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java

DebugTest.javaCover dynamic and reversible debug logger behavior +235/-0

Cover dynamic and reversible debug logger behavior

• Adds unit coverage for live property reads, legacy property support, FINE configuration, idempotence, restoration, external overrides, and user-handler preservation. Also verifies Selenium's handler excludes INFO records and the deprecated level helper remains compatible.

java/test/org/openqa/selenium/internal/DebugTest.java

RemoteWebDriverInitializationTest.javaTest post-load debug activation for new drivers +47/-0

Test post-load debug activation for new drivers

• Verifies a second RemoteWebDriver construction activates FINE logging after selenium.debug changes at runtime. Adds setup and teardown that isolate global property and logger state.

java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java

Other (2) +15 / -0
BUILD.bazelExpose Grid logging library to its unit tests +1/-0

Expose Grid logging library to its unit tests

• Adds package-level test visibility so the new Grid logging tests can depend on the production logging target.

java/src/org/openqa/selenium/grid/log/BUILD.bazel

BUILD.bazelDefine the Grid logging unit-test suite +14/-0

Define the Grid logging unit-test suite

• Adds a Bazel small-test target with Grid configuration, logging, AssertJ, and JUnit dependencies.

java/test/org/openqa/selenium/grid/log/BUILD.bazel

@qodo-code-review

qodo-code-review Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (7) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 18 rules

Grey Divider


Remediation recommended

1. Live toggle drops logs 📘 Rule violation ▣ Testability
Description
isHandledBySeleniumDebugHandler() reports records as handled based only on the live debug
property, even when configureLogger() has not yet installed its handler. After Grid logging is
configured, toggling debug before the next configuration call can suppress FINE records from Grid’s
root handler or duplicate them when toggled off, and the new test does not cover either transition.
Code

java/src/org/openqa/selenium/internal/Debug.java[R87-89]

+  public static boolean isHandledBySeleniumDebugHandler(String loggerName, Level level) {
+    if (!(isDebugging() || isDebugAll())) {
+      return false;
Evidence
Rule 389273 requires automated tests for all new behavior and bug fixes. The helper at
Debug.java[87-98] equates a live switch with an installed handler, while
LoggingOptionsTest.java[143-185] only tests the steady state where the switch is enabled before
configuration and therefore misses the newly introduced toggle-transition behavior.

Rule 389273: Require tests for all new functionality and bug fixes
java/src/org/openqa/selenium/internal/Debug.java[87-98]
java/src/org/openqa/selenium/grid/log/LoggingOptions.java[206-214]
java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[143-185]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The duplicate-suppression helper uses live debug switches instead of checking whether Selenium's debug handler is currently installed. This can suppress unhandled records or allow duplicates during the interval between a property change and the next `configureLogger()` call.

## Issue Context
The helper's Javadoc promises `true` only when the installed handler already covers the record. The regression test sets the property before configuring logging, so it does not exercise runtime transitions after Grid handlers are installed.

## Fix Focus Areas
- java/src/org/openqa/selenium/internal/Debug.java[87-98]
- java/src/org/openqa/selenium/grid/log/LoggingOptions.java[206-214]
- java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[143-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Debug logs bypass Grid sink 🐞 Bug ◔ Observability
Description
The new root-handler filter rejects Selenium-hierarchy FINE/CONFIG records when debugging is
enabled, leaving Debug's ConsoleHandler to emit them only to stderr. Consequently, these diagnostics
are absent from Grid's configured log file and bypass structured JSON formatting.
Code

java/src/org/openqa/selenium/grid/log/LoggingOptions.java[193]

+      handler.setFilter(NOT_ALREADY_HANDLED_BY_SELENIUM_DEBUG_HANDLER);
Evidence
LoggingOptions creates its configured terse or JSON handler over the selected output stream, then
attaches the rejecting filter. Debug handles the rejected records with a plain ConsoleHandler, and
the new test explicitly verifies that a Selenium FINE marker appears on stderr but not in the
configured log file.

java/src/org/openqa/selenium/grid/log/LoggingOptions.java[186-213]
java/src/org/openqa/selenium/internal/Debug.java[158-163]
java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[154-177]
java/src/org/openqa/selenium/grid/log/LoggingFlags.java[67-84]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The duplicate-suppression filter removes Selenium FINE/CONFIG records from Grid's configured file or structured handler. Those records are instead emitted only through Debug's plain stderr ConsoleHandler, changing their configured destination and format.

## Issue Context
Duplicate output should be prevented without excluding debug diagnostics from the operator-selected Grid sink. Update the interaction between LoggingOptions and Debug so Grid-owned logging receives each record exactly once.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/log/LoggingOptions.java[189-213]
- java/src/org/openqa/selenium/internal/Debug.java[72-99]
- java/src/org/openqa/selenium/internal/Debug.java[158-163]
- java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[143-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Debug records emitted twice ✓ Resolved 🐞 Bug ◔ Observability
Description
With Selenium debug enabled and normal Grid logging configured, skipping org.openqa.selenium
preserves its FINE handler while Grid also installs a FINE root handler. Normal parent propagation
therefore emits Selenium FINE records through both handlers, duplicating high-volume wire
diagnostics.
Code

java/src/org/openqa/selenium/grid/log/LoggingOptions.java[R169-170]

+      if ("org.openqa.selenium".equals(name)) {
+        continue;
Evidence
Debug.configureLogger() attaches a FINE ConsoleHandler directly to org.openqa.selenium, and
the focused skip keeps it attached. LoggingOptions then forces Grid to FINE and installs another
FINE handler on the root logger; no code disables parent propagation, while the new test only
verifies the direct handler accepts FINE and does not check emitted output across both handlers.

java/src/org/openqa/selenium/internal/Debug.java[130-135]
java/src/org/openqa/selenium/grid/log/LoggingOptions.java[97-105]
java/src/org/openqa/selenium/grid/log/LoggingOptions.java[181-199]
java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[127-135]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Normal Grid debug configuration retains Selenium's direct FINE handler and also installs a FINE root handler. Since Selenium loggers propagate records to the root logger, FINE diagnostics are emitted twice.

## Issue Context
Preserve Debug's internal handler bookkeeping without creating two output paths for the same Selenium records. Add a regression test that publishes a FINE record under normal Grid debug configuration and verifies it is emitted exactly once.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/log/LoggingOptions.java[159-199]
- java/src/org/openqa/selenium/internal/Debug.java[107-151]
- java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[115-137]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (21)
4. Null-capabilities test uses Mockito ✓ Resolved 📘 Rule violation ▣ Testability
Description
The new null-capabilities regression test obtains its CommandExecutor from prepareExecutorMock,
which creates a Mockito mock for the remote command boundary without a machine-checked protocol
contract. A recording in-memory CommandExecutor fake can capture the new-session command and
provide the response without a mocking framework.
Code

java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[R227-228]

+    CommandExecutor executor =
+        WebDriverFixture.prepareExecutorMock(echoCapabilities, nullValueResponder);
Evidence
Rule 389270 disallows hand-configured mocking-framework substitutes for external service boundaries
without a machine-checked contract. The changed test calls prepareExecutorMock, and that helper
explicitly creates mock(CommandExecutor.class) and stubs execute(any()).

Rule 389270: Avoid mocks in tests; use real or contract-driven integrations
java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[227-240]
java/test/org/openqa/selenium/remote/WebDriverFixture.java[63-70]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Replace the Mockito-backed executor in the null-capabilities regression test with a small in-memory recording `CommandExecutor`.

## Issue Context
`WebDriverFixture.prepareExecutorMock()` delegates to Mockito. The test only needs to record the `NEW_SESSION` command, return a deterministic response, and assert that empty capabilities were supplied.

## Fix Focus Areas
- java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[227-240]
- java/test/org/openqa/selenium/remote/WebDriverFixture.java[63-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Direct connection fixes untested 📘 Rule violation ▣ Testability
Description
The new BiDi and DevTools constructor calls fix direct-connection debug logging, but no automated
regression test constructs either connection and verifies that the debug switch configures the
shared logger. These code paths could regress without failing the existing test suite.
Code

java/src/org/openqa/selenium/bidi/Connection.java[R81-85]

+    // Reflect the current debug switches before this connection starts logging its wire
+    // diagnostics at FINE -- callers that construct a Connection directly (never going through
+    // RemoteWebDriver or DriverFinder) would otherwise never trigger the raise. Idempotent and
+    // cheap, same pattern as DriverFinder.getBinaryPaths().
+    Debug.configureLogger();
Evidence
Compliance rule 389273 requires automated tests for every bug fix. Both constructors now invoke
Debug.configureLogger() to address direct callers, while project searches found no corresponding
configureLogger regression coverage in the BiDi or DevTools test packages.

Rule 389273: Require tests for all new functionality and bug fixes
java/src/org/openqa/selenium/bidi/Connection.java[81-85]
java/src/org/openqa/selenium/devtools/Connection.java[95-100]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Add regression tests proving direct BiDi and DevTools connection construction invokes the debug logger configuration behavior.

## Issue Context
These constructor calls fix direct callers that do not pass through `RemoteWebDriver` or `DriverFinder`, but no changed test exercises either path or would fail if the calls were removed.

## Fix Focus Areas
- java/src/org/openqa/selenium/bidi/Connection.java[81-85]
- java/src/org/openqa/selenium/devtools/Connection.java[95-100]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Redis warning fix untested 📘 Rule violation ▣ Testability
Description
The Redis node-registration failure was corrected to log at WARNING, but no Redis registry test
exercises a throwing getStatus() call and asserts the emitted level. The local registry has
regression coverage for the equivalent fix, while the Redis path remains unprotected.
Code

java/src/org/openqa/selenium/grid/distributor/redis/RedisBackedNodeRegistry.java[294]

+          Level.WARNING, String.format("Exception while adding Node %s", node.getUri()), e);
Evidence
Rule 389273 requires a test that exercises each bug fix and fails against the previous behavior. The
changed Redis catch block now uses Level.WARNING, but RedisBackedNodeRegistryTest contains no
corresponding warning-level assertion.

Rule 389273: Require tests for all new functionality and bug fixes
java/src/org/openqa/selenium/grid/distributor/redis/RedisBackedNodeRegistry.java[294-294]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Add a regression test for the Redis-backed node-registration failure log level.

## Issue Context
The production fix changes an actionable registration failure to `Level.WARNING`, but the Redis-backed code path has no assertion that would fail if it reverted to a debug level.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/distributor/redis/RedisBackedNodeRegistry.java[294-294]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Local node-add failure hidden ✓ Resolved 📘 Rule violation ◔ Observability
Description
LocalNodeRegistry.add() logs an exception that aborts node registration at FINE, hiding an
actionable failure from warning-level monitoring. The failure should be logged at WARNING.
Code

java/src/org/openqa/selenium/grid/distributor/local/LocalNodeRegistry.java[230]

+          Level.FINE, String.format("Exception while adding Node %s", node.getUri()), e);
Evidence
The compliance rule requires problematic conditions to use warning-level logging. The cited catch
block logs at Level.FINE and immediately returns, leaving the node unregistered without
warning-level visibility.

Rule 330199: Use appropriate log levels for message intent
java/src/org/openqa/selenium/grid/distributor/local/LocalNodeRegistry.java[228-231]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The local node registry logs a node-registration exception at `FINE`, even though the exception causes registration to abort.

## Issue Context
PR Compliance ID 330199 requires failures that may need intervention to use `WARNING` rather than a diagnostic level.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/distributor/local/LocalNodeRegistry.java[230-230]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Direct connections lose debug logs ✓ Resolved 🐞 Bug ◔ Observability
Description
BiDi and DevTools connection records now always report at FINE, but their public constructors do not
activate Debug.configureLogger(). Callers constructing either connection directly with
-Dselenium.debug=true therefore lose wire diagnostics that previously emitted at INFO.
Code

java/src/org/openqa/selenium/bidi/Connection.java[149]

+    LOG.log(Level.FINE, "-> {0}", json);
Evidence
The public BiDi constructor performs no logger activation before its send path emits at FINE;
DevTools has the same direct-construction pattern. Debug.configureLogger() only changes logger
state when explicitly invoked, so setting the property alone no longer makes these standalone
connection records visible.

java/src/org/openqa/selenium/bidi/Connection.java[79-85]
java/src/org/openqa/selenium/bidi/Connection.java[139-150]
java/src/org/openqa/selenium/devtools/Connection.java[89-98]
java/src/org/openqa/selenium/devtools/Connection.java[180-185]
java/src/org/openqa/selenium/internal/Debug.java[103-131]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Direct BiDi and DevTools connection construction does not activate the logger mechanism, so their newly fixed-FINE diagnostics remain suppressed despite an enabled Selenium debug property.

## Issue Context
Previously, `getDebugLogLevel()` made these records INFO while debugging. Ensure standalone connection usage activates the new logger mechanism without requiring `RemoteWebDriver` or `DriverFinder` construction.

## Fix Focus Areas
- java/src/org/openqa/selenium/bidi/Connection.java[79-85]
- java/src/org/openqa/selenium/devtools/Connection.java[89-98]
- java/src/org/openqa/selenium/internal/Debug.java[103-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Discovery regression uses Mockito ✓ Resolved 📘 Rule violation ▣ Testability
Description
The new discovery regression test exercises DriverFinder through the Mockito-backed service
instead of a real or in-memory DriverService implementation. This leaves the test dependent on a
hand-configured mock without a machine-checked contract.
Code

java/test/org/openqa/selenium/remote/service/DriverFinderTest.java[104]

+    when(service.getExecutable()).thenReturn(driverFile.toString());
Evidence
PR Compliance ID 389270 disallows hand-written mocks without a machine-checked contract. service
is declared through Mockito, and the new test adds a Mockito stub before invoking the changed
discovery path.

Rule 389270: Avoid mocks in tests; use real or contract-driven integrations
java/test/org/openqa/selenium/remote/service/DriverFinderTest.java[58-58]
java/test/org/openqa/selenium/remote/service/DriverFinderTest.java[102-117]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new discovery regression test uses a Mockito-backed `DriverService` to exercise the changed path.

## Issue Context
Use a small in-memory `DriverService` fake that returns the executable path required by the test, avoiding generic mocking for the new behavior.

## Fix Focus Areas
- java/test/org/openqa/selenium/remote/service/DriverFinderTest.java[102-117]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Redis node-add failure hidden ✓ Resolved 📘 Rule violation ◔ Observability
Description
RedisBackedNodeRegistry.add() logs an exception that aborts node registration at FINE, hiding an
actionable failure from warning-level monitoring. The failure should be logged at WARNING.
Code

java/src/org/openqa/selenium/grid/distributor/redis/RedisBackedNodeRegistry.java[294]

+          Level.FINE, String.format("Exception while adding Node %s", node.getUri()), e);
Evidence
The compliance rule requires problematic conditions to use warning-level logging. The cited catch
block logs at Level.FINE and immediately returns, leaving the node unregistered without
warning-level visibility.

Rule 330199: Use appropriate log levels for message intent
java/src/org/openqa/selenium/grid/distributor/redis/RedisBackedNodeRegistry.java[292-295]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Redis-backed node registry logs a node-registration exception at `FINE`, even though the exception causes registration to abort.

## Issue Context
PR Compliance ID 330199 requires failures that may need intervention to use `WARNING` rather than a diagnostic level.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/distributor/redis/RedisBackedNodeRegistry.java[294-294]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. External Grid config hides debug ✓ Resolved 🐞 Bug ◔ Observability
Description
Migrated Grid server diagnostics now always report at FINE, but the existing external-JUL branch
returns before Grid applies its debug-level override. A standalone Grid using an INFO-level JUL
config therefore suppresses diagnostics that selenium.debug=true previously raised to INFO.
Code

java/src/org/openqa/selenium/netty/server/RequestConverter.java[61]

+    LOG.log(Level.FINE, "Incoming message: {0}", msg);
Evidence
Grid startup calls configureLogging(), but that method returns immediately when a JUL config class
or file is supplied, before setLoggingLevel() can force FINE. Since RequestConverter's migrated
records are now FINE rather than INFO-under-debug, an external INFO configuration filters them out.

java/src/org/openqa/selenium/netty/server/RequestConverter.java[59-64]
java/src/org/openqa/selenium/grid/log/LoggingOptions.java[136-147]
java/src/org/openqa/selenium/grid/log/LoggingOptions.java[162-165]
java/src/org/openqa/selenium/grid/TemplateGridCommand.java[120-123]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Fixed-FINE Grid diagnostics are hidden when an external JUL configuration is present because Grid returns before applying the Selenium debug switch and does not invoke `Debug.configureLogger()`.

## Issue Context
The external-config bypass is pre-existing; the regression is introduced by migrating records that previously became INFO under `selenium.debug=true` to unconditional FINE.

## Fix Focus Areas
- java/src/org/openqa/selenium/netty/server/RequestConverter.java[59-64]
- java/src/org/openqa/selenium/grid/log/LoggingOptions.java[136-147]
- java/src/org/openqa/selenium/grid/TemplateGridCommand.java[120-123]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Runtime toggle misses discovery ✓ Resolved 🐞 Bug ◔ Observability
Description
The constructor-time Debug.configureLogger() call runs after subclass super(...) arguments, so
toggling debug after class initialization does not affect DriverFinder/Selenium Manager
diagnostics emitted while constructing the next browser driver. Disabling debug similarly leaves
those pre-constructor diagnostics enabled until the base constructor runs.
Code

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[230]

+    Debug.configureLogger();
Evidence
ChromeDriver evaluates generateExecutor(...) as a superclass-constructor argument, and that
method invokes DriverFinder, whose discovery path emits FINE records. The added refresh is not
reached until all of that work has completed, while the static initializer cannot react to a
property changed after initial class loading.

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[125-134]
java/src/org/openqa/selenium/remote/RemoteWebDriver.java[226-230]
java/src/org/openqa/selenium/chrome/ChromeDriver.java[90-112]
java/src/org/openqa/selenium/remote/service/DriverFinder.java[93-118]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Runtime debug-property changes are synchronized only after subclass constructor arguments have performed driver discovery, causing discovery logs to use stale logger configuration.

## Issue Context
The static initializer covers only the first class initialization. Later `ChromeDriver` constructions evaluate `generateExecutor(...)` and run `DriverFinder` before entering the `RemoteWebDriver` constructor.

## Fix Focus Areas
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[125-134]
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[226-230]
- java/src/org/openqa/selenium/chrome/ChromeDriver.java[90-112]
- java/src/org/openqa/selenium/remote/service/DriverFinder.java[93-118]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. getDebugLogLevel() Javadoc incomplete ✓ Resolved 📘 Rule violation ✧ Quality
Description
The added Javadoc contains only an @deprecated tag and omits both a free-text purpose description
and the required @return documentation. This leaves the modified public API method incompletely
documented.
Code

java/src/org/openqa/selenium/internal/Debug.java[R54-63]

+  /**
+   * @deprecated Individual log statements no longer change what severity they report at based on
+   *     this switch; {@link #configureLogger()} raises the real {@code org.openqa.selenium} logger
+   *     to {@link Level#FINE} instead, which is the ordinary way to see Selenium's debug output.
+   *     Enable it with {@code -Dselenium.debug=true}, the {@code SE_DEBUG} environment variable, or
+   *     directly via {@code Logger.getLogger("org.openqa.selenium").setLevel(Level.FINE)}. This
+   *     method's own behavior is unchanged and kept only for existing call sites still comparing
+   *     against it.
+   */
+  @Deprecated(forRemoval = true)
Evidence
PR Compliance ID 330201 requires every changed public method to have free-text purpose documentation
and a non-empty @return tag for non-void return types. The added Javadoc for getDebugLogLevel()
consists entirely of the @deprecated tag and provides no @return tag.

Rule 330201: Require complete Javadoc on public API methods
java/src/org/openqa/selenium/internal/Debug.java[54-65]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Complete the Javadoc for the public `getDebugLogLevel()` method by adding a free-text purpose sentence and a non-empty `@return` tag while retaining the existing deprecation guidance.

## Issue Context
The method returns a `Level`, so the public-method documentation rule requires a purpose description and return-value documentation in addition to the `@deprecated` tag.

## Fix Focus Areas
- java/src/org/openqa/selenium/internal/Debug.java[54-65]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. RetryRequest retries use debug levels ✓ Resolved 📘 Rule violation ◔ Observability
Description
The modified connection and server-error retry statements use Debug.getDebugLogLevel(), which
resolves to INFO or FINE rather than WARNING. Under-leveling these transient failures can hide
actionable retry conditions from warning-based monitoring.
Code

java/src/org/openqa/selenium/remote/http/RetryRequest.java[51]

+            LOG.log(Debug.getDebugLogLevel(), "Retry #" + (i + 1) + " on ConnectException", ex);
Evidence
PR Compliance ID 330199 explicitly classifies retries and transient failures as conditions that
should use warning. Both changed statements select Debug.getDebugLogLevel(), and that method
returns either INFO or FINE, so neither retry path emits at WARNING.

Rule 330199: Use appropriate log levels for message intent
java/src/org/openqa/selenium/remote/http/RetryRequest.java[49-51]
java/src/org/openqa/selenium/remote/http/RetryRequest.java[64-68]
java/src/org/openqa/selenium/internal/Debug.java[64-65]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The retry log statements use a dynamic debug level even though they report connection failures and server errors that trigger retries.

## Issue Context
PR Compliance ID 330199 requires retry and transient-failure messages to use `WARNING`. Update both retry paths while preserving their messages and exception context.

## Fix Focus Areas
- java/src/org/openqa/selenium/remote/http/RetryRequest.java[49-51]
- java/src/org/openqa/selenium/remote/http/RetryRequest.java[64-68]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. Null capabilities contract broken ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new constructor documentation permits null capabilities, but the constructor passes the original
null parameter to startSession(), where it is dereferenced. Callers following this newly
documented contract receive a NullPointerException rather than an empty capability set.
Code

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[R222-223]

+   * @param capabilities the capabilities requested for the new session; null is treated as an
+   *     empty set of capabilities
Evidence
Although the field is normalized with requireNonNullElseGet, startSession(capabilities) receives
the original parameter. Its validation path calls capabilities.asMap(), proving that a documented
null argument is dereferenced.

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[220-236]
java/src/org/openqa/selenium/remote/RemoteWebDriver.java[286-291]
java/src/org/openqa/selenium/remote/RemoteWebDriver.java[993-997]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The constructor's new Javadoc says null capabilities are treated as empty, while session startup still receives and dereferences the original null argument.

## Issue Context
Either normalize capabilities before both field assignment and `startSession()`, with a regression test for null input, or correct the documentation if null is intentionally unsupported.

## Fix Focus Areas
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[220-236]
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[286-291]
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[993-997]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. Initialization test logger nonstandard ✓ Resolved 📘 Rule violation ✧ Quality
Description
The added logger field is named SELENIUM_LOGGER and initialized with a literal logger category
rather than RemoteWebDriverInitializationTest.class.getName(). It therefore does not meet the
standardized logger-field requirements.
Code

java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[66]

+  private static final Logger SELENIUM_LOGGER = Logger.getLogger("org.openqa.selenium");
Evidence
Rule 330198 requires a logger field named LOG, initialized from its enclosing class; this field is
named SELENIUM_LOGGER and uses the literal "org.openqa.selenium".

Rule 330198: Standardize logger declaration and initialization in Java classes
java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[66-66]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RemoteWebDriverInitializationTest` adds a logger field that violates the required logger name and initialization pattern.

## Issue Context
The test needs access to the shared Selenium logger, so use a helper or local lookup instead of retaining a nonconforming logger field.

## Fix Focus Areas
- java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[66-66]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


17. Changed constructor lacks Javadoc 📘 Rule violation ✧ Quality
Description
The modified public three-argument RemoteWebDriver constructor has no immediately preceding
Javadoc. All three constructor parameters are therefore undocumented in the public API.
Code

java/src/org/openqa/selenium/remote/RemoteWebDriver.java[R215-217]

+    // Instance-time (not class-load-time) so a property change made after this class has already
+    // loaded still takes effect for drivers constructed afterwards.
+    Debug.configureLogger();
Evidence
Rule 330200 explicitly requires Javadoc and complete parameter tags for modified public
constructors; the constructor has three parameters and no preceding Javadoc.

Rule 330200: Require Javadoc for all public API types and methods
java/src/org/openqa/selenium/remote/RemoteWebDriver.java[213-217]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The changed public `RemoteWebDriver` constructor lacks API Javadoc.

## Issue Context
Add an immediately preceding Javadoc block describing the constructor and include `@param` tags for `executor`, `capabilities`, and `clientConfig`.

## Fix Focus Areas
- java/src/org/openqa/selenium/remote/RemoteWebDriver.java[213-217]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


18. isDebugging() lacks Javadoc 📘 Rule violation ✧ Quality
Description
The changed public isDebugging() method has no immediately preceding Javadoc and no @return
documentation. Public methods changed under src/main/java must have complete Javadoc.
Code

java/src/org/openqa/selenium/internal/Debug.java[42]

+    return Boolean.getBoolean("selenium.debug") || Boolean.getBoolean("selenium.webdriver.verbose");
Evidence
Rule 330201 requires complete Javadoc for every changed public method in non-test Java code, while
isDebugging() is immediately preceded only by the previous member and has no method documentation.

Rule 330201: Require complete Javadoc on public API methods
java/src/org/openqa/selenium/internal/Debug.java[41-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The modified public `isDebugging()` method lacks complete Javadoc.

## Issue Context
Add a purpose sentence and a non-empty `@return` tag describing when debug mode is considered enabled.

## Fix Focus Areas
- java/src/org/openqa/selenium/internal/Debug.java[41-43]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


19. Regression test uses Mockito executor ✓ Resolved 📘 Rule violation ▣ Testability
Description
The new regression test constructs drivers with WebDriverFixture.prepareExecutorMock, which is a
Mockito-backed CommandExecutor rather than a real or contract-driven integration. A small
in-memory CommandExecutor fake can exercise this logger behavior without a mocking framework.
Code

java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[R94-96]

+    new RemoteWebDriver(
+        WebDriverFixture.prepareExecutorMock(echoCapabilities, nullValueResponder),
+        new ImmutableCapabilities());
Evidence
Rule 389270 permits simple in-memory interface implementations but disallows generic framework mocks
without a machine-checked external contract. The added test invokes prepareExecutorMock, whose
implementation creates CommandExecutor through Mockito.

Rule 389270: Avoid mocks in tests; use real or contract-driven integrations
java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[94-105]
java/test/org/openqa/selenium/remote/WebDriverFixture.java[63-70]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new logger regression test relies on a Mockito-backed command executor.

## Issue Context
`WebDriverFixture.prepareExecutorMock` calls Mockito's `mock(CommandExecutor.class)`. Replace its use in this test with a small in-memory `CommandExecutor` implementation returning the required new-session response.

## Fix Focus Areas
- java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java[94-105]
- java/test/org/openqa/selenium/remote/WebDriverFixture.java[63-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


20. Debug lowers existing verbosity ✓ Resolved 🐞 Bug ◔ Observability
Description
configureLogger() unconditionally replaces the org.openqa.selenium logger level with FINE,
suppressing FINER/FINEST records when an application already configured a more verbose level. For
example, W3CHttpResponseCodec's FINER response-decoding diagnostics become unloggable after enabling
debug.
Code

java/src/org/openqa/selenium/internal/Debug.java[91]

+      SELENIUM_LOGGER.setLevel(Level.FINE);
Evidence
Debug unconditionally assigns FINE to the package logger, while W3CHttpResponseCodec emits concrete
diagnostics at FINER and guards them with isLoggable(FINER). Child loggers inheriting the new
explicit FINE level reject those records before handlers can publish them.

java/src/org/openqa/selenium/internal/Debug.java[89-98]
java/src/org/openqa/selenium/remote/codec/w3c/W3CHttpResponseCodec.java[67-84]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Enabling Selenium debug logging unconditionally sets the `org.openqa.selenium` logger to `FINE`. This reduces verbosity when the logger was already configured as `FINER`, `FINEST`, or `ALL`.

## Issue Context
The logger level should only be changed when its current level is less verbose than `FINE`. Preserve more verbose explicit levels and ensure disabling debug restores only levels actually changed by `Debug`.

## Fix Focus Areas
- java/src/org/openqa/selenium/internal/Debug.java[83-111]
- java/test/org/openqa/selenium/internal/DebugTest.java[94-120]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


21. Cached level survives disable ✓ Resolved 🐞 Bug ◔ Observability
Description
isDebugging() now changes at runtime, but RetryRequest caches getDebugLogLevel() in a static final
field. If RetryRequest initializes while debugging is enabled, its retry diagnostics remain at INFO
after the property is cleared and configureLogger() restores normal logging.
Code

java/src/org/openqa/selenium/internal/Debug.java[42]

+    return Boolean.getBoolean("selenium.debug") || Boolean.getBoolean("selenium.webdriver.verbose");
Evidence
Debug now reads the system properties on every call and supports reversing logger configuration, but
RetryRequest evaluates getDebugLogLevel() only once and reuses that cached level for all subsequent
retry records.

java/src/org/openqa/selenium/internal/Debug.java[41-56]
java/src/org/openqa/selenium/internal/Debug.java[99-111]
java/src/org/openqa/selenium/remote/http/RetryRequest.java[28-68]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Debug.isDebugging()` now reflects runtime property changes, but `RetryRequest` snapshots `Debug.getDebugLogLevel()` during class initialization. Disabling debug therefore leaves retry diagnostics permanently promoted to `INFO` for that JVM.

## Issue Context
Resolve the log level at each logging operation, or migrate these statements to a fixed debug severity controlled by the real logger. Add coverage for initializing `RetryRequest` while debug is enabled and then disabling debug.

## Fix Focus Areas
- java/src/org/openqa/selenium/internal/Debug.java[41-56]
- java/src/org/openqa/selenium/remote/http/RetryRequest.java[28-68]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


22. Cross-binding comparison undocumented 📘 Rule violation ≡ Correctness
Description
The change makes Java system properties alter the real logger, but neither the changed code nor PR
description identifies another language binding used for comparison. The analogous Python behavior
exists and should be cited to demonstrate that logger-level and handler semantics were considered.
Code

java/src/org/openqa/selenium/internal/Debug.java[R41-42]

  public static boolean isDebugging() {
-    return IS_DEBUG;
+    return Boolean.getBoolean("selenium.debug") || Boolean.getBoolean("selenium.webdriver.verbose");
Evidence
Rule 389265 requires evidence identifying another binding when user-visible binding behavior
changes. Java now evaluates debug properties dynamically, while Python contains analogous debug
logger configuration, but the submitted change provides no cross-binding comparison or documented
divergence.

Rule 389265: Compare cross-language bindings when changing user-visible behavior
java/src/org/openqa/selenium/internal/Debug.java[41-42]
py/selenium/webdriver/init.py[22-30]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The user-visible debug-configuration change lacks evidence of comparison with another Selenium language binding.

## Issue Context
Python has analogous `SE_DEBUG` behavior that changes the `selenium` logger level and installs a handler. Document the binding and comparison in the PR description or nearby user documentation, including any intentional differences for Java system properties and handler filtering.

## Fix Focus Areas
- java/src/org/openqa/selenium/internal/Debug.java[41-42]
- py/selenium/webdriver/__init__.py[22-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


23. setLoggingLevel() lacks Javadoc 📘 Rule violation ✧ Quality
Description
The modified public setLoggingLevel() method has no immediately preceding Javadoc. Its non-void
return value is consequently also missing the required @return documentation.
Code

java/src/org/openqa/selenium/grid/log/LoggingOptions.java[90]

+    if (Debug.isDebugAll() || Debug.isDebugging()) {
Evidence
The branch file shows a changed public, non-void method without an immediately preceding Javadoc
block, violating both public API documentation requirements.

Rule 330200: Require Javadoc for all public API types and methods
Rule 330201: Require complete Javadoc on public API methods
java/src/org/openqa/selenium/grid/log/LoggingOptions.java[88-111]

Agent prompt

[Comment truncated to fit github's 65,536-char limit.]

Comment thread java/test/org/openqa/selenium/internal/DebugTest.java Outdated
Comment thread java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java Outdated
Comment thread java/src/org/openqa/selenium/internal/Debug.java
Comment thread java/src/org/openqa/selenium/grid/log/LoggingOptions.java
Comment thread java/src/org/openqa/selenium/remote/RemoteWebDriver.java
Comment thread java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java Outdated
Comment thread java/src/org/openqa/selenium/internal/Debug.java
Comment thread java/src/org/openqa/selenium/internal/Debug.java Outdated
Comment thread java/src/org/openqa/selenium/internal/Debug.java
…ver 3-arg ctor

Documents the debug-switch override behavior (SE_DEBUG / -Dselenium.debug=true
/ -Dselenium.webdriver.verbose=true) on the two methods added by the debug
logging consistency mechanism, so API consumers see the effect from Javadoc
without reading the implementation.
MohabMohie and others added 2 commits July 28, 2026 19:55
…uest stale log level

- DebugTest: replace SELENIUM_LOGGER field with seleniumLogger() helper so
  the linter's per-class logger-naming check stops flagging a deliberate
  shared-category logger.
- Debug#isDebugging(): add missing Javadoc.
- Debug#configureLogger(): only raise the selenium logger to FINE when it
  is currently less verbose than FINE, so an already more-verbose level
  (e.g. FINER from W3CHttpResponseCodec) is never clobbered; only restore
  the pre-debug level when this method was the one that raised it. Adds a
  cross-binding Javadoc comparison against Python's SE_DEBUG import-time
  behavior (py/selenium/webdriver/__init__.py).
- RetryRequest: stop caching Debug.getDebugLogLevel() in a static field at
  class-init -- now that the debug switch is live/toggleable at runtime,
  the snapshot went stale forever after the first read. Call it live at
  each log site instead, matching every other of the 64 call sites in
  java/src except this one.

New/updated tests:
- DebugTest: configureLoggerDoesNotLowerAnAlreadyMoreVerboseLevel,
  configureLoggerDoesNotRestoreALevelItNeverChanged.
- RetryRequestTest: retryLogLevelTracksDebugToggleAtEachLogSite.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG
- Replace the SELENIUM_LOGGER static field with a seleniumLogger() helper
  in RemoteWebDriverInitializationTest, documenting why the test
  deliberately reads the shared org.openqa.selenium logger category
  rather than its own class logger.
- Rewrite constructingASecondDriverPicksUpADebugPropertyChangedAfterTheFirst
  to use a plain lambda CommandExecutor instead of a Mockito mock, since
  the test makes no verify()/interaction assertions.
Comment thread java/src/org/openqa/selenium/remote/http/RetryRequest.java Outdated
Comment thread java/src/org/openqa/selenium/remote/RemoteWebDriver.java
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 31ea2ca

Comment thread java/src/org/openqa/selenium/internal/Debug.java
Comment thread java/src/org/openqa/selenium/remote/RemoteWebDriver.java
Comment thread java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit d44ad4e

MohabMohie and others added 5 commits July 28, 2026 21:41
DriverFinder.getBinaryPaths() is the single funnel all browser driver
classes (including InternetExplorerDriver, which never reaches
RemoteWebDriver's instance constructor at all) go through for discovery
logging, before RemoteWebDriver's own constructor-level Debug.configureLogger()
call is reached. Call it there instead, fixing the second-driver-onward gap
for every construction path in one place.

Closes SeleniumHQ#17834

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG
…el()

LocalGridModel, LocalNodeRegistry, LocalDistributor, RedisBackedGridModel,
RedisBackedNodeRegistry, and RedisBackedDistributor now log at a fixed
Level.FINE instead of Debug.getDebugLogLevel()'s deprecated INFO/FINE dance
-- Debug.configureLogger() already makes FINE visible when debugging, so
nothing is lost. Also collapses two now-pointless isLoggable(FINE) guards
in the two Distributor classes.

Part of SeleniumHQ#17835

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG
…vel()

LocalNode, ProxyNodeWebsockets, RelaySessionFactory, RequestConverter,
RemoteWebDriverBuilder, and RetryRequest now log at a fixed Level.FINE
instead of Debug.getDebugLogLevel()'s deprecated INFO/FINE dance --
Debug.configureLogger() already makes FINE visible when debugging, so
nothing is lost.

Part of SeleniumHQ#17835

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG
…ugLogLevel()

devtools.Connection and bidi.Connection now log at a fixed Level.FINE
instead of Debug.getDebugLogLevel()'s deprecated INFO/FINE dance --
Debug.configureLogger() already makes FINE visible when debugging, so
nothing is lost.

This is the last of the three parallel migration groups (grid distributor,
node/netty/remote, protocols) that together complete the full
getDebugLogLevel() call-site migration.

Closes SeleniumHQ#17835

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG
retryLogLevelTracksDebugToggleAtEachLogSite locked in the pre-migration
behavior (report level toggles INFO/FINE with the debug switch). Now that
RetryRequest always logs at a fixed Level.FINE (part of SeleniumHQ#17835's migration,
previous commit), that assertion is obsolete, not a regression -- rewritten
as retryLogsAtFineRegardlessOfDebugToggle to lock in the new invariant on
both sides of the switch instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG
Comment thread java/src/org/openqa/selenium/grid/distributor/local/LocalNodeRegistry.java Outdated
Comment thread java/src/org/openqa/selenium/grid/distributor/redis/RedisBackedNodeRegistry.java Outdated
Comment thread java/test/org/openqa/selenium/remote/service/DriverFinderTest.java Outdated
Comment thread java/src/org/openqa/selenium/bidi/Connection.java
Comment thread java/src/org/openqa/selenium/netty/server/RequestConverter.java
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 9c3f4ff

…egistration log

visibility, and BiDi/CDP/Grid debug-logging gaps

- RemoteWebDriver: startSession() now receives the coalesced this.capabilities instead
  of the raw (possibly null) constructor parameter, fixing an NPE when constructing with
  null capabilities and honoring the constructor's own "null is treated as empty" contract.
- Debug.getDebugLogLevel(): complete the Javadoc with a purpose sentence and @return.
- RetryRequest: bump both retry log statements from FINE to WARNING -- a connection-failure
  or server-error retry is operationally significant and bounded to a handful of attempts,
  not routine diagnostics that should require debug mode to see.
- LocalNodeRegistry / RedisBackedNodeRegistry: bump the add() exception log (which aborts
  node registration) from FINE to WARNING.
- bidi.Connection / devtools.Connection: call Debug.configureLogger() as the first
  constructor statement so wire diagnostics are visible under -Dselenium.debug=true even
  when a Connection is constructed directly, without going through RemoteWebDriver or
  DriverFinder.
- LoggingOptions.configureLogging(): call Debug.configureLogger() before the
  external-JUL-config early return, so Grid's own FINE-level wire diagnostics
  (RequestConverter, bidi/devtools Connection) stay visible under -Dselenium.debug=true
  even when an external java.util.logging.config.* property is set.
- Test fixtures (LoggingOptionsTest, RemoteWebDriverInitializationTest, RetryRequestTest):
  symmetrically save/clear/restore the legacy selenium.webdriver.verbose property alongside
  selenium.debug, so an externally-set legacy property can't leak into "no switch" baseline
  assertions.

Adds regression tests for the null-capabilities fix, the node-registry log level, and the
Grid external-JUL-config log visibility gap; dismisses the DriverFinderTest mock-vs-real
DriverService suggestion as inconsistent with the file's established convention (verifies
the already-fixed DriverFinder.getBinaryPaths() Debug.configureLogger() call needs no
further change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG
Comment thread java/src/org/openqa/selenium/bidi/Connection.java
Comment thread java/test/org/openqa/selenium/remote/RemoteWebDriverInitializationTest.java Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 6b86a19

MohabMohie added a commit to ShaftHQ/SHAFT_ENGINE that referenced this pull request Jul 28, 2026
… run (#4353)

Surfaced while independently re-verifying a delegate coder's claimed
test results on Selenium PR SeleniumHQ/selenium#17832 round 2 -- a
first re-run silently returned cached greens before catching itself
and forcing --nocache_test_results.


Claude-Session: https://claude.ai/code/session_01LfxetzdJtF13MCJDRNQwgG

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…nstalled handler

The handler-stripping loop in configureLogging() enumerates every registered
logger and removes its handlers so Grid's own console setup starts from a
clean slate. org.openqa.selenium stays registered throughout (Debug holds a
strong static reference to it), so the handler Debug.configureLogger() had
just installed one line above was getting swept up in that too -- removed
before configureLogging() returned. Debug's installed-handler bookkeeping has
no way to learn a handler was removed out from under it, so once stripped its
idempotency guard prevented ever reinstalling one until the debug switch was
toggled off and back on.

The loop now skips the org.openqa.selenium logger by name. Reordering
Debug.configureLogger() to run after the loop instead was considered and
rejected: it must still run before the external-JUL-config early return a few
lines below, or the existing
configureLoggingRaisesSeleniumLoggerEvenWithExternalJulConfigSet regression
test breaks.

Found in an independent third-pass review, not previously reported on the PR.
… debug logger

qodo-code-review thread databaseId 3668700786 flagged that no test constructs
bidi.Connection or devtools.Connection directly and verifies the constructor
actually calls Debug.configureLogger() -- both were fixed to call it (so
direct construction, bypassing RemoteWebDriver/DriverFinder, still gets FINE
diagnostics under -Dselenium.debug=true), but neither had a test proving it.

Adds ConnectionTest to devtools' existing small-tests unit suite (extending
it rather than bidi's, which only has heavyweight real-browser large-tests
already set up) using a minimal hand-written HttpClient fake -- no Mockito,
consistent with this PR's real-Logger/real-Handler test style throughout.
Temporarily commented out the constructor's Debug.configureLogger() call to
watch the test fail for the right reason (logger level null instead of
FINE), then restored it and watched the test pass.
qodo-code-review thread databaseId 3668700801 flagged that this regression
test still pulled its CommandExecutor from WebDriverFixture.prepareExecutorMock()
(Mockito-backed) where every other test-quality finding on this PR was fixed
the same way -- e.g. constructingASecondDriverPicksUpADebugPropertyChangedAfterTheFirst
in this same file, already fixed in commit 31ea2ca, replaced a Mockito
executor with a plain lambda since CommandExecutor is a @FunctionalInterface.

Applies the identical pattern here: an AtomicReference<Command>-capturing
lambda records the single NEW_SESSION command and answers it by echoing the
requested capabilities back (echoCapabilities), replacing the
verify()/argThat() Mockito assertion with plain field assertions on the
captured command. Behavior asserted is unchanged; full class re-run green.
…on add() failure

qodo-code-review thread databaseId 3668700792 ("Redis warning fix untested")
flagged that RedisBackedNodeRegistry.add() already logs at Level.WARNING when
node.getStatus() throws during registration (RedisBackedNodeRegistry.java:293-294,
already shipped/correct), but unlike its sibling LocalNodeRegistry -- which has
LocalNodeRegistryTest.addLogsAtWarningWhenNodeStatusThrows -- this path had zero
test coverage.

Mirrors the Local test's real-Logger/real-Handler style, adapted to this file's
existing testcontainers-backed Redis fixture. Watched RED first (temporarily
downgraded the log call to Level.FINE, confirmed the test fails with "expected
WARNING but was FINE"), then restored and watched GREEN.
Comment thread java/src/org/openqa/selenium/grid/log/LoggingOptions.java
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit b030733

…root handler

qodo re-reviewed the Bug A fix from commit f46f340 (skip org.openqa.selenium
in configureLogging()'s handler-stripping loop) and found it exposes a genuine
duplicate-output bug once combined with Grid's own logging setup: it's correct
in isolation, but Debug.configureLogger()'s handler on org.openqa.selenium
never disables useParentHandlers, so a FINE/CONFIG-range org.openqa.selenium
record now reaches BOTH that handler (prints it, unchanged) AND, via normal
JUL propagation, whatever handler configureLogging() then attaches to the
ROOT logger a few lines later -- which forces the root logger to FINE too and
was previously unfiltered by logger name. Same record, printed twice. This is
new: pre-PR, Grid never called Debug.configureLogger() at all; mid-PR before
the Bug A fix, Debug's handler got stripped immediately so the duplication
never had a chance to manifest.

Disabling propagation on org.openqa.selenium was considered and rejected:
Debug's handler explicitly filters OUT everything INFO-and-above, so cutting
propagation too would silently drop every INFO/WARNING/SEVERE
org.openqa.selenium record from Grid's own formatted output -- a worse
regression than the one being fixed.

Fix: Debug.isHandledBySeleniumDebugHandler(loggerName, level) (Debug.java) is
a new shared predicate exposing exactly the range Debug's own handler covers
(FINE/CONFIG, org.openqa.selenium or a descendant, while a debug switch is
on) -- kept next to the handler it describes rather than duplicated. Grid's
own root handlers (plain-log and structured-log, LoggingOptions.java) now
carry a filter built on that predicate, so they skip exactly the records
Debug's handler already prints and pass everything else through unchanged,
including INFO+ org.openqa.selenium output and all non-Selenium logging.

TDD: new configureLoggingDoesNotDuplicateSeleniumDebugRecordsThroughGridsRootHandler
in LoggingOptionsTest publishes a real FINE record through both real handlers
(Debug's, captured via redirected stderr; Grid's, routed to a temp file via
log-file config) and asserts it's captured by Debug's handler but not
duplicated into Grid's, while an existing INFO line still reaches the file.
Watched RED first (marker present in the Grid log file), then GREEN after the
fix. Full existing scoped suite re-run clean: DebugTest, LoggingOptionsTest,
RemoteWebDriverInitializationTest, RetryRequestTest, LocalNodeRegistryTest,
RedisBackedNodeRegistryTest, ConnectionTest, DriverFinderTest.
Comment on lines +87 to +89
public static boolean isHandledBySeleniumDebugHandler(String loggerName, Level level) {
if (!(isDebugging() || isDebugAll())) {
return false;

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.

Remediation recommended

1. Live toggle drops logs 📘 Rule violation ▣ Testability

isHandledBySeleniumDebugHandler() reports records as handled based only on the live debug
property, even when configureLogger() has not yet installed its handler. After Grid logging is
configured, toggling debug before the next configuration call can suppress FINE records from Grid’s
root handler or duplicate them when toggled off, and the new test does not cover either transition.
Agent Prompt
## Issue description
The duplicate-suppression helper uses live debug switches instead of checking whether Selenium's debug handler is currently installed. This can suppress unhandled records or allow duplicates during the interval between a property change and the next `configureLogger()` call.

## Issue Context
The helper's Javadoc promises `true` only when the installed handler already covers the record. The regression test sets the property before configuring logging, so it does not exercise runtime transitions after Grid handlers are installed.

## Fix Focus Areas
- java/src/org/openqa/selenium/internal/Debug.java[87-98]
- java/src/org/openqa/selenium/grid/log/LoggingOptions.java[206-214]
- java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[143-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Handler handler = new FlushingHandler(out);
handler.setFormatter(new TerseFormatter(getLogTimestampFormat()));
handler.setLevel(level);
handler.setFilter(NOT_ALREADY_HANDLED_BY_SELENIUM_DEBUG_HANDLER);

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.

Remediation recommended

2. Debug logs bypass grid sink 🐞 Bug ◔ Observability

The new root-handler filter rejects Selenium-hierarchy FINE/CONFIG records when debugging is
enabled, leaving Debug's ConsoleHandler to emit them only to stderr. Consequently, these diagnostics
are absent from Grid's configured log file and bypass structured JSON formatting.
Agent Prompt
## Issue description
The duplicate-suppression filter removes Selenium FINE/CONFIG records from Grid's configured file or structured handler. Those records are instead emitted only through Debug's plain stderr ConsoleHandler, changing their configured destination and format.

## Issue Context
Duplicate output should be prevented without excluding debug diagnostics from the operator-selected Grid sink. Update the interaction between LoggingOptions and Debug so Grid-owned logging receives each record exactly once.

## Fix Focus Areas
- java/src/org/openqa/selenium/grid/log/LoggingOptions.java[189-213]
- java/src/org/openqa/selenium/internal/Debug.java[72-99]
- java/src/org/openqa/selenium/internal/Debug.java[158-163]
- java/test/org/openqa/selenium/grid/log/LoggingOptionsTest.java[143-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

qodo-code-review thread databaseId 3668308297 ("Discovery regression uses
mockito") flagged that this test exercises DriverFinder through a
Mockito-backed DriverService instead of a real/in-memory implementation. It
was initially scoped to defer to SeleniumHQ#17836, but that issue turns out to track an
unrelated selenium.webdriver.verbose fixture-hygiene gap in this same file,
not this finding -- so fixing it directly instead, matching the same category
of fix already applied three times elsewhere on this PR (Mockito executor ->
plain fake, matching this codebase's own established convention).

Adds a small in-memory InMemoryDriverService (extends the real, abstract
DriverService, port 0, no real I/O) local to this one test only -- the other
tests in this file make real verify()/interaction assertions on the shared
Mockito service field and are unaffected. This test makes no such
assertions, only checking the shared org.openqa.selenium logger's level, so
it needs no mocking framework: getExecutable() answers straight from the
constructor-set path (inherited, not overridden), getDriverName() returns a
fixed name, and the two abstract accessors throw since getBinaryPaths()
never reaches them once getExecutable() already resolves a path. Full class
re-run green (10/10).
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit a3e7dc3

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 2fba7ef

@titusfortner

Copy link
Copy Markdown
Member

This PR has too large of scope, and now references five separate issues, which makes it quite challenging to review

Maybe limit this PR to just the debug-logger mechanism and tests and then you can follow up with the migration and other bug fixes in future PRs after it is merged?

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

Labels

B-build Includes scripting, bazel and CI integrations B-grid Everything grid and server related C-java Java Bindings

Projects

None yet

3 participants