Skip to content

[java][rb][py][dotnet][js] use SE_DEBUG to enable debugging#16816

Merged
titusfortner merged 2 commits intotrunkfrom
debug
Jan 4, 2026
Merged

[java][rb][py][dotnet][js] use SE_DEBUG to enable debugging#16816
titusfortner merged 2 commits intotrunkfrom
debug

Conversation

@titusfortner
Copy link
Member

@titusfortner titusfortner commented Dec 30, 2025

User description

Most of the languages have different environment variables / system properties to enable debugging, this adds to whatever currently exists the ability to get the same functionality by setting the environment variable. Should be another option in troubleshooting to just tell people to run with the env set, or when running bazel add a quick --test_env=DEBUG=1

This standardizes on our SE_* convention, and is what Rust/Selenium Manager already use.

JS, I'm moving it from testing to lib, and opening it to all driver, not just http (doesn't seem to be that much more noise.


PR Type

Enhancement


Description

  • Standardize debugging across all language bindings using SE_DEBUG environment variable

  • Add SE_DEBUG support to Java, Python, Ruby, .NET, and JavaScript

  • Move JavaScript debug logging from test utilities to main logging library

  • Enable debug logging automatically when SE_DEBUG environment variable is set


Diagram Walkthrough

flowchart LR
  A["SE_DEBUG env var"] -->|Java| B["Debug.java checks SE_DEBUG"]
  A -->|Python| C["webdriver/__init__.py enables logging"]
  A -->|Ruby| D["webdriver.rb checks SE_DEBUG"]
  A -->|.NET| E["LogContextManager sets Debug level"]
  A -->|JavaScript| F["logging.js enables root logger"]
  B --> G["IS_DEBUG flag"]
  C --> H["selenium logger at DEBUG level"]
  D --> I["logger level set to debug"]
  E --> J["LogEventLevel.Debug"]
  F --> K["Level.ALL with console handler"]
Loading

File Walkthrough

Relevant files
Enhancement
Debug.java
Add SE_DEBUG environment variable support to Java               

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

  • Added SE_DEBUG environment variable check alongside existing system
    properties
  • Parse SE_DEBUG using Boolean.parseBoolean(System.getenv("SE_DEBUG"))
  • Include SE_DEBUG in IS_DEBUG flag evaluation with OR logic
+2/-1     
LogContextManager.cs
Add SE_DEBUG environment variable support to .NET               

dotnet/src/webdriver/Internal/Logging/LogContextManager.cs

  • Check SE_DEBUG environment variable in LogContextManager constructor
  • Dynamically set log level to Debug if SE_DEBUG is present, otherwise
    Warn
  • Apply selected level to GlobalContext initialization
+6/-1     
logging.js
Add SE_DEBUG support to JavaScript logging library             

javascript/selenium-webdriver/lib/logging.js

  • Add SE_DEBUG and SELENIUM_VERBOSE environment variable checks after
    LogManager initialization
  • Enable root logger with Level.ALL and add console handler when either
    variable is set
  • Support both SE_DEBUG and legacy SELENIUM_VERBOSE for backward
    compatibility
+6/-0     
__init__.py
Add SE_DEBUG environment variable support to Python           

py/selenium/webdriver/init.py

  • Add logging and os module imports
  • Check SE_DEBUG environment variable on module initialization
  • Configure selenium logger to DEBUG level and add StreamHandler if
    SE_DEBUG is set
+9/-0     
webdriver.rb
Add SE_DEBUG environment variable support to Ruby               

rb/lib/selenium/webdriver.rb

  • Add SE_DEBUG environment variable check to logger level determination
  • Include SE_DEBUG alongside existing $DEBUG and DEBUG env var checks
  • Set logger level to debug if any of the three conditions are true
+1/-1     
Cleanup
index.js
Remove debug setup from test utilities                                     

javascript/selenium-webdriver/lib/test/index.js

  • Remove logging module import that is no longer needed
  • Remove SELENIUM_VERBOSE debug setup code from test utilities
  • Debug logging now handled centrally in logging.js library
+0/-6     

@selenium-ci selenium-ci added C-py Python Bindings C-rb Ruby Bindings C-dotnet .NET Bindings C-java Java Bindings C-nodejs JavaScript Bindings labels Dec 30, 2025
@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Dec 30, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Sensitive log exposure

Description: Enabling global debug logging via an environment variable (SE_DEBUG/SELENIUM_VERBOSE) can
cause sensitive data (e.g., credentials, session tokens, URLs with secrets, internal
hostnames) to be written to stderr/console in production if the env var is set or
inherited unintentionally; similar debug-enablement behavior is also introduced in
py/selenium/webdriver/init.py,
dotnet/src/webdriver/Internal/Logging/LogContextManager.cs, rb/lib/selenium/webdriver.rb,
and java/src/org/openqa/selenium/internal/Debug.java.
logging.js [485-489]

Referred Code
// Enable debug logging if SE_DEBUG or SELENIUM_VERBOSE environment variable is set
if (typeof process !== 'undefined' && process.env && (process.env.SE_DEBUG || process.env.SELENIUM_VERBOSE)) {
  logManager.root_.setLevel(Level.ALL)
  logManager.root_.addHandler(consoleHandler)
}
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Debug logging exposure: Enabling root logger at Level.ALL and adding a console handler when
SE_DEBUG/SELENIUM_VERBOSE is set may cause sensitive data to be emitted to stderr/console
depending on what downstream log statements include, requiring verification that
secrets/PII are never logged even at debug/trace levels.

Referred Code
// Enable debug logging if SE_DEBUG or SELENIUM_VERBOSE environment variable is set
if (typeof process !== 'undefined' && process.env && (process.env.SE_DEBUG || process.env.SELENIUM_VERBOSE)) {
  logManager.root_.setLevel(Level.ALL)
  logManager.root_.addHandler(consoleHandler)
}

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Dec 30, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Use a more flexible environment variable check

In Debug.java, check if the SE_DEBUG environment variable is a non-empty string
instead of parsing it as a boolean, to align with implementations in other
languages in this PR.

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

-boolean envVar = Boolean.parseBoolean(System.getenv("SE_DEBUG"));
+String seDebug = System.getenv("SE_DEBUG");
+boolean envVar = seDebug != null && !seDebug.isEmpty();
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that using Boolean.parseBoolean is inconsistent with the other language implementations in this PR, which check for the variable's presence or non-empty value. Applying this change would harmonize behavior across the different Selenium language bindings.

Medium
Learned
best practice
Validate env vars before use

Parse SE_DEBUG/SELENIUM_VERBOSE explicitly (e.g., accept only "1"/"true") and
trim values; this avoids enabling debug when the variable is set to "0"/"false"
or whitespace.

javascript/selenium-webdriver/lib/logging.js [485-489]

 // Enable debug logging if SE_DEBUG or SELENIUM_VERBOSE environment variable is set
-if (typeof process !== 'undefined' && process.env && (process.env.SE_DEBUG || process.env.SELENIUM_VERBOSE)) {
+const isTruthyEnv = (name) => {
+  const v = process?.env?.[name]
+  return typeof v === 'string' && /^1|true$/i.test(v.trim())
+}
+
+if (typeof process !== 'undefined' && process.env && (isTruthyEnv('SE_DEBUG') || isTruthyEnv('SELENIUM_VERBOSE'))) {
   logManager.root_.setLevel(Level.ALL)
   logManager.root_.addHandler(consoleHandler)
 }
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Add explicit validation/guards for environment variables at integration boundaries (trim/parse), instead of relying on truthy string checks.

Low
General
Cache logger instance
Suggestion Impact:The commit replaced repeated calls to logging.getLogger("selenium") with a single cached logger variable and used it for setLevel/handlers/addHandler, improving readability. The logger is cached inside the SE_DEBUG block rather than at module scope as suggested.

code diff:

 if os.environ.get("SE_DEBUG"):
-    logging.getLogger("selenium").setLevel(logging.DEBUG)
-    if not logging.getLogger("selenium").handlers:
-        logging.getLogger("selenium").addHandler(logging.StreamHandler())
+    logger = logging.getLogger("selenium")
+    logger.setLevel(logging.DEBUG)
+    if not logger.handlers:
+        logger.addHandler(logging.StreamHandler())

In init.py, store the result of logging.getLogger("selenium") in a variable
to avoid repeated calls and improve readability.

py/selenium/webdriver/init.py [22-25]

+logger = logging.getLogger("selenium")
 if os.environ.get("SE_DEBUG"):
-    logging.getLogger("selenium").setLevel(logging.DEBUG)
-    if not logging.getLogger("selenium").handlers:
-        logging.getLogger("selenium").addHandler(logging.StreamHandler())
+    logger.setLevel(logging.DEBUG)
+    if not logger.handlers:
+        logger.addHandler(logging.StreamHandler())

[Suggestion processed]

Suggestion importance[1-10]: 4

__

Why: This is a good suggestion for improving code readability and maintainability by caching the logger instance in a variable, which is a common best practice.

Low
  • Update

Copy link
Contributor

@asolntsev asolntsev left a comment

Choose a reason for hiding this comment

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

@titusfortner This specific PR doesn't make things worse, so we can merge it.
At least in Java bindings, it adds env var "SE_DEBUG" as an alternative to the existing system property "selenium.debug".

But generally, this approach is totally wrong.

Instead of

writing "debug" or "info" log depending on the env var,

we should

always write "debug" log.
And depending on the env var, such a log should be written to file/console or ignored.

This is how logging works, at least in Java world.

@nvborisenko
Copy link
Member

Seems SE_DEBUG is boolean switch, then what if SE_DEBUG=off? IMHO SE_LOG_LEVEL=debug is better, giving more flexibility.

@titusfortner
Copy link
Member Author

@asolntsev we do that in our test suite with CaptureLoggingRule, I don't think that belongs in the library, though, does it? Also, I'm not really a fan of the Debug class approach as a whole (#12892), but it's what we have right now that would make it work.

@nvborisenko each language has idiomatic ways to customize exactly what is logged at what level. For this, we're looking for a common way to get the info most people are looking for that is good enough.

Copy link
Member

@navin772 navin772 left a comment

Choose a reason for hiding this comment

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

LGTM for the python part.

Few minor improvements:

  1. Addressing the AI bot's Cache logger instance suggestion is a good idea.
  2. Do we document the added SE_DEBUG env var anywhere? If not, we should add it to README

@titusfortner
Copy link
Member Author

@navin772 thanks! Yes, we should update it here: https://www.selenium.dev/documentation/webdriver/troubleshooting/logging/
it's already here for selenium manager: https://www.selenium.dev/documentation/selenium_manager/

@titusfortner titusfortner merged commit 309fadd into trunk Jan 4, 2026
49 checks passed
@titusfortner titusfortner deleted the debug branch January 4, 2026 20:08
@asolntsev asolntsev added this to the 4.40.0 milestone Jan 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-dotnet .NET Bindings C-java Java Bindings C-nodejs JavaScript Bindings C-py Python Bindings C-rb Ruby Bindings Review effort 2/5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants