Skip to content

[rb] output driver logs by default when debug is enabled#16901

Merged
titusfortner merged 6 commits intotrunkfrom
rb_debug_all
Jan 26, 2026
Merged

[rb] output driver logs by default when debug is enabled#16901
titusfortner merged 6 commits intotrunkfrom
rb_debug_all

Conversation

@titusfortner
Copy link
Member

@titusfortner titusfortner commented Jan 13, 2026

User description

Update: Changed to only trigger on SE_DEBUG env var (not DEBUG/$DEBUG).
Added Logger force methods, warnings when overriding user settings, and fixed Firefox arg parsing bug.

🔗 Related Issues

Similar to #16900
I actually thought Ruby already did this.

💥 What does this PR do?

  • when WebDriver.logger.debug? adds driver log output to logger
  • Edit: Only SE_DEBUG env var enables driver verbose logging
  • Edit: Adds Logger#debug! and Logger#stderr! to force settings
  • Edit: Warns when overriding user-specified driver logging settings
  • Edit: Forces driver output to stderr when SE_DEBUG is set

🔧 Implementation Notes

  • we could have a separate setting for this in logger instead of forcing it on existing debug setups. Or toggle it based on SE_DEBUG (the new behavior)
  • Edit: Chose SE_DEBUG-only approach for cross-binding consistency
  • Edit: DEBUG/$DEBUG continues to only affect Selenium's own logging (preserves existing behavior)
  • Edit: Logger force methods are generic (not SE_DEBUG-aware) to keep Logger reusable

PR Type

Enhancement


Description

  • Enable verbose driver logging when WebDriver debug mode is active

  • Add automatic log level configuration for Chrome, Edge, Firefox, IE

  • Remove conflicting log-level arguments before applying debug settings

  • Unify debug logging behavior across all supported browser drivers


Diagram Walkthrough

flowchart LR
  A["WebDriver.logger.debug?"] -->|enabled| B["Chrome/Edge Service"]
  A -->|enabled| C["Firefox Service"]
  A -->|enabled| D["IE Service"]
  B -->|add --verbose| E["Driver Logs"]
  C -->|set --log debug| E
  D -->|add --log-level=DEBUG| E
Loading

File Walkthrough

Relevant files
Enhancement
service.rb
Add verbose logging for Chrome when debug enabled               

rb/lib/selenium/webdriver/chrome/service.rb

  • Override initialize method to check WebDriver debug status
  • Remove any existing --log-level arguments from args
  • Add --verbose flag when debug mode is enabled
  • Call parent class initialization with modified arguments
+10/-0   
service.rb
Add verbose logging for Edge when debug enabled                   

rb/lib/selenium/webdriver/edge/service.rb

  • Override initialize method to check WebDriver debug status
  • Remove any existing --log-level arguments from args
  • Add --verbose flag when debug mode is enabled
  • Call parent class initialization with modified arguments
+11/-0   
service.rb
Add debug logging for Firefox when debug enabled                 

rb/lib/selenium/webdriver/firefox/service.rb

  • Extend existing initialize method with debug logging logic
  • Remove existing --log arguments and their values if present
  • Add --log debug arguments when debug mode is enabled
  • Preserve existing websocket port configuration logic
+12/-0   
service.rb
Add debug logging for IE when debug enabled                           

rb/lib/selenium/webdriver/ie/service.rb

  • Override initialize method to check WebDriver debug status
  • Remove any existing --log-level arguments from args
  • Add --log-level=DEBUG flag when debug mode is enabled
  • Call parent class initialization with modified arguments
+10/-0   

@titusfortner titusfortner requested review from aguspe and p0deje January 13, 2026 18:11
@selenium-ci selenium-ci added the C-rb Ruby Bindings label Jan 13, 2026
@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 13, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Sensitive information exposure

Description: Enabling verbose/debug driver logging automatically when WebDriver.logger.debug? is true
(also in Edge/Firefox/IE service initializers) may cause sensitive data (URLs with tokens,
cookies, PII in form values, internal paths) to be written to logs in environments where
debug is enabled unintentionally or logs are centrally collected.
service.rb [29-37]

Referred Code
def initialize(path: nil, port: nil, log: nil, args: nil)
  args ||= []
  if WebDriver.logger.debug?
    args.reject! { |arg| arg.start_with?('--log-level') }
    args << '--verbose'
  end

  super
end
Ticket Compliance
🟡
🎫 #5678
🔴 Fix/avoid repeated ChromeDriver instantiation failures that produce "Error: ConnectFailure
(Connection refused)" on subsequent driver starts (Ubuntu 16.04 / Chrome 65 / ChromeDriver
2.35 context).
🟡
🎫 #1234
🔴 Restore/ensure that clicking a link with javascript in its href triggers the expected
behavior in Firefox (regression from Selenium 2.47.1 to 2.48.x per provided repro).
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:
Verbose logging risk: Enabling driver --verbose (and similar debug flags across drivers) when
WebDriver.logger.debug? is true may cause sensitive data (e.g., URLs with credentials,
session identifiers, or other request details) to be written to logs depending on driver
behavior and should be reviewed/guarded accordingly.

Referred Code
def initialize(path: nil, port: nil, log: nil, args: nil)
  args ||= []
  if WebDriver.logger.debug?
    args.reject! { |arg| arg.start_with?('--log-level') }
    args << '--verbose'
  end

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 Jan 13, 2026

PR Code Suggestions ✨

Latest suggestions up to 8dc536d

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix nil args crash

Fix a potential crash by changing Array(args.dup) to Array(args).dup to safely
handle cases where args is nil.

rb/lib/selenium/webdriver/chrome/service.rb [29-37]

 def initialize(args: nil, **)
   if ENV.key?('SE_DEBUG')
-    args = Array(args.dup)
+    args = Array(args).dup
     warn_driver_log_override if args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
     args << '--verbose'
   end
 
   super
 end
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a NoMethodError crash when args is nil and proposes a valid fix, which also applies to identical code in edge and ie service files.

High
Prevent nil args crash

Fix a potential crash by changing Array(args.dup) to Array(args).dup to safely
handle cases where args is nil.

rb/lib/selenium/webdriver/firefox/service.rb [29-42]

 def initialize(args: nil, **)
-  args = Array(args.dup)
+  args = Array(args).dup
   unless args.any? { |arg| arg.include?('--connect-existing') || arg.include?('--websocket-port') }
     args << '--websocket-port'
     args << '0'
   end
 
   if ENV.key?('SE_DEBUG')
     remove_log_args(args)
     args << '-v'
   end
 
   super
 end
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a NoMethodError crash when args is nil due to args.dup and provides a correct fix by changing the order of operations to Array(args).dup.

High
General
Align driver output with debug

Change the condition for redirecting driver process IO from ENV.key?('SE_DEBUG')
to WebDriver.logger.debug? to ensure driver logs are always enabled when any
debug flag is active.

rb/lib/selenium/webdriver/common/service_manager.rb [83-90]

-if ENV.key?('SE_DEBUG')
+if WebDriver.logger.debug?
   if @io && @io != WebDriver.logger.io
-    WebDriver.logger.warn('SE_DEBUG is set; overriding user-specified driver log output to use stderr',
+    WebDriver.logger.warn('Debug logging is enabled; overriding user-specified driver log output to use stderr',
                           id: :se_debug)
   end
   @io = WebDriver.logger.io
 end
 @process.io = @io if @io
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out an inconsistency in debug behavior and proposes a good improvement to align driver log output with the general debug state, enhancing the debugging experience.

Medium
Learned
best practice
Defensively copy input arrays

Always defensively copy args (not only when SE_DEBUG is set) so later internal
mutations can’t affect the caller’s array. Initialize args as Array(args).dup up
front, then apply conditional modifications.

rb/lib/selenium/webdriver/chrome/service.rb [29-37]

 def initialize(args: nil, **)
+  args = Array(args).dup
   if ENV.key?('SE_DEBUG')
-    args = Array(args.dup)
     warn_driver_log_override if args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
     args << '--verbose'
   end
 
   super
 end
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Avoid mutating caller-provided collection arguments; defensively copy arrays/hashes before modification.

Low
Validate env var boolean flags

Treat SE_DEBUG as enabled only when it has a meaningful value (e.g., not blank
and not “0”) to avoid unexpected behavior when the key exists but is effectively
false. Compute a boolean (e.g., se_debug = ...) and use it instead of ENV.key?.

rb/lib/selenium/webdriver.rb [99-104]

+se_debug = (ENV['SE_DEBUG'] || '').strip
+se_debug_enabled = !se_debug.empty? && se_debug != '0'
+
 @logger ||= WebDriver::Logger.new('Selenium', default_level: level, **).tap do |logger|
-  if ENV.key?('SE_DEBUG')
+  if se_debug_enabled
     logger.debug!
     logger.stderr!
   end
 end
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why:
Relevant best practice - Add validation/guards for environment variable inputs (presence and non-blank/non-falsey values) before changing behavior.

Low
  • More

Previous suggestions

✅ Suggestions up to commit 581e694
CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix bug in argument parsing logic
Suggestion Impact:The commit refactored log-arg removal into a helper (remove_log_args) and implemented the suggested safety check: it deletes the value following '--log' only if it exists and does not start with '-'. This prevents accidentally removing another option flag.

code diff:

+        def remove_log_args(args)
+          if (index = args.index('--log'))
+            args.delete_at(index) # delete '--log'
+            args.delete_at(index) if args[index] && !args[index].start_with?('-') # delete value if present
+            warn_driver_log_override
+          elsif (index = args.index { |arg| arg.start_with?('--log=') })
+            args.delete_at(index)
+            warn_driver_log_override
+          end

Fix a bug in the Firefox service argument parsing by checking if the value for
--log is a valid value and not another option flag before removing it.

rb/lib/selenium/webdriver/firefox/service.rb [37-42]

 if (index = args.index('--log'))
-  args.delete_at(index) # delete '--log'
-  args.delete_at(index) # delete the value (now at same index)
+  # also remove value if it's not an option flag
+  if args[index + 1] && !args[index + 1].start_with?('-')
+    args.delete_at(index + 1)
+  end
+  args.delete_at(index)
 elsif (index = args.index { |arg| arg.start_with?('--log=') })
   args.delete_at(index)
 end

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a bug in the new argument parsing logic that could cause incorrect driver configuration, and the proposed fix is accurate.

Medium
High-level
Unify driver log configuration logic
Suggestion Impact:The commit modified the debug logging argument-handling logic in both Chrome and IE services in a parallel/standardized way (changing how args are duplicated/normalized and how log-related args are removed), but it did not introduce any shared helper or otherwise remove the duplication as suggested.

code diff:

# File: rb/lib/selenium/webdriver/chrome/service.rb
@@ -26,10 +26,10 @@
         SHUTDOWN_SUPPORTED = true
         DRIVER_PATH_ENV_KEY = 'SE_CHROMEDRIVER'
 
-        def initialize(path: nil, port: nil, log: nil, args: nil)
-          args ||= []
+        def initialize(args: nil, **)
           if WebDriver.logger.debug?
-            args.reject! { |arg| arg.start_with?('--log-level') }
+            args = Array(args.dup)
+            args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
             args << '--verbose'
           end

# File: rb/lib/selenium/webdriver/ie/service.rb
@@ -26,10 +26,10 @@
         SHUTDOWN_SUPPORTED = true
         DRIVER_PATH_ENV_KEY = 'SE_IEDRIVER'
 
-        def initialize(path: nil, port: nil, log: nil, args: nil)
-          args ||= []
+        def initialize(args: nil, **)
           if WebDriver.logger.debug?
-            args.reject! { |arg| arg.start_with?('--log-level') }
+            args = Array(args.dup)
+            args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
             args << '--log-level=DEBUG'
           end

The logic for enabling debug logs is duplicated across the Chrome, Edge, and IE
service classes. This repeated code should be abstracted into a shared helper
method to improve maintainability.

Examples:

rb/lib/selenium/webdriver/chrome/service.rb [29-37]
        def initialize(path: nil, port: nil, log: nil, args: nil)
          args ||= []
          if WebDriver.logger.debug?
            args.reject! { |arg| arg.start_with?('--log-level') }
            args << '--verbose'
          end

          super
        end
rb/lib/selenium/webdriver/ie/service.rb [29-37]
        def initialize(path: nil, port: nil, log: nil, args: nil)
          args ||= []
          if WebDriver.logger.debug?
            args.reject! { |arg| arg.start_with?('--log-level') }
            args << '--log-level=DEBUG'
          end

          super
        end

Solution Walkthrough:

Before:

# In chrome/service.rb & edge/service.rb
def initialize(args: nil)
  args ||= []
  if WebDriver.logger.debug?
    args.reject! { |arg| arg.start_with?('--log-level') }
    args << '--verbose'
  end
  super
end

# In ie/service.rb
def initialize(args: nil)
  args ||= []
  if WebDriver.logger.debug?
    args.reject! { |arg| arg.start_with?('--log-level') }
    args << '--log-level=DEBUG'
  end
  super
end

After:

# In a shared helper or parent class
def apply_debug_logging(args, remove_prefix:, add_arg:)
  return unless WebDriver.logger.debug?

  args.reject! { |arg| arg.start_with?(remove_prefix) }
  args << add_arg
end

# In chrome/service.rb & edge/service.rb
def initialize(args: nil)
  args ||= []
  apply_debug_logging(args, remove_prefix: '--log-level', add_arg: '--verbose')
  super
end

# In ie/service.rb
def initialize(args: nil)
  args ||= []
  apply_debug_logging(args, remove_prefix: '--log-level', add_arg: '--log-level=DEBUG')
  super
end
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies significant code duplication in the initialize methods of Chrome, Edge, and IE services and proposes a valid abstraction to improve maintainability.

Medium
Learned
best practice
Defensive copy of input arrays
Suggestion Impact:The commit changes the initialization logic to defensively copy `args` (via `args = Array(args.dup)`) before calling `reject!`/mutation in debug mode, addressing the core concern about mutating a caller-owned array. It does not follow the exact suggested pattern (copying unconditionally and explicitly passing args to `super` is not shown here).

code diff:

-        def initialize(path: nil, port: nil, log: nil, args: nil)
-          args ||= []
+        def initialize(args: nil, **)
           if WebDriver.logger.debug?
-            args.reject! { |arg| arg.start_with?('--log-level') }
+            args = Array(args.dup)
+            args.reject! { |arg| arg.include?('log-level') || arg.include?('silent') }
             args << '--verbose'

args may be a caller-owned array; duplicating it before reject!/<< prevents
surprising external side effects. Create a new array (e.g., Array(args).dup) and
pass it to super explicitly.

rb/lib/selenium/webdriver/chrome/service.rb [29-37]

 def initialize(path: nil, port: nil, log: nil, args: nil)
-  args ||= []
+  args = Array(args).dup
   if WebDriver.logger.debug?
     args.reject! { |arg| arg.start_with?('--log-level') }
     args << '--verbose'
   end
 
-  super
+  super(path: path, port: port, log: log, args: args)
 end

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Avoid mutating caller-provided collections; make a defensive copy of collection-like inputs before modifying/storing them.

Low
Centralize repeated debug-arg logic

The same debug-arg manipulation logic is duplicated across multiple service
classes; move it into WebDriver::Service (or a shared helper) to keep behavior
consistent and easier to maintain.

rb/lib/selenium/webdriver/edge/service.rb [29-37]

 def initialize(path: nil, port: nil, log: nil, args: nil)
-  args ||= []
-  if WebDriver.logger.debug?
-    args.reject! { |arg| arg.start_with?('--log-level') }
-    args << '--verbose'
-  end
-
-  super
+  args = with_debug_driver_args(args, remove_prefix: '--log-level', add: '--verbose')
+  super(path: path, port: port, log: log, args: args)
 end
Suggestion importance[1-10]: 5

__

Why:
Relevant best practice - Reduce duplication by centralizing repeated behavior into a shared helper or base type.

Low

@CLAassistant
Copy link

CLAassistant commented Jan 14, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds automatic debug logging to the Selenium WebDriver Ruby bindings by enabling verbose driver output when WebDriver.logger.debug? is true. The implementation modifies the service initialization for Chrome, Edge, Firefox, and IE drivers to automatically inject appropriate debug flags.

Changes:

  • Override initialize method in Chrome, Edge, IE, and Firefox service classes to detect debug mode
  • Remove conflicting log-level arguments before adding debug flags
  • Add appropriate verbose flags for each driver (--verbose for Chrome/Edge, -v for Firefox, --log-level=DEBUG for IE)

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
rb/lib/selenium/webdriver/chrome/service.rb Add initialize override to inject --verbose flag when debug is enabled
rb/lib/selenium/webdriver/edge/service.rb Add initialize override to inject --verbose flag when debug is enabled
rb/lib/selenium/webdriver/firefox/service.rb Modify initialize to inject -v flag when debug is enabled
rb/lib/selenium/webdriver/ie/service.rb Add initialize override to inject --log-level=DEBUG when debug is enabled
rb/sig/lib/selenium/webdriver/chrome/service.rbs Add type signature for new initialize method
rb/sig/lib/selenium/webdriver/edge/service.rbs Add type signature for new initialize method
rb/sig/lib/selenium/webdriver/ie/service.rbs Add type signature for new initialize method
rb/spec/unit/selenium/webdriver/chrome/service_spec.rb Stub debug? to return false in tests
rb/spec/unit/selenium/webdriver/edge/service_spec.rb Stub debug? to return false in tests
rb/spec/unit/selenium/webdriver/firefox/service_spec.rb Stub debug? to return false in tests, update test description
rb/spec/unit/selenium/webdriver/ie/service_spec.rb Stub debug? to return false in tests
rb/spec/unit/selenium/webdriver/common/service_spec.rb Stub debug? to return false, update Firefox test expectation

titusfortner and others added 5 commits January 25, 2026 09:56
- Add Logger#debug! and Logger#stderr! to force settings and prevent overrides
- When SE_DEBUG is set, force debug level and stderr output
- Warn when SE_DEBUG overrides user-specified driver logging args
- Warn when SE_DEBUG overrides user-specified driver log output

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix bug where --log without value would delete the next arg incorrectly
- Only enable driver verbose logging when SE_DEBUG is set (not DEBUG/$DEBUG)
- Add tests verifying SE_DEBUG adds verbose flags and removes conflicting args

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

@titusfortner titusfortner merged commit a497c5b into trunk Jan 26, 2026
61 checks passed
@titusfortner titusfortner deleted the rb_debug_all branch January 26, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants