Skip to content

[dotnet] Enabling drivers to set log to console. #16097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: trunk
Choose a base branch
from

Conversation

diemol
Copy link
Member

@diemol diemol commented Jul 28, 2025

User description

This will be false by default, following what the .NET bindings have usually done.

🔗 Related Issues

Helps with #12273
Should fix #15785

💥 What does this PR do?

It enables users to send driver logs to the console, disabled by default.

🔧 Implementation Notes

💡 Additional Considerations

I could only test it manually by creating a .NET app and using the build as a dependency.

@nvborisenko, could you please help me check this?

🔄 Types of changes

  • Cleanup (formatting, renaming)
  • Bug fix (backwards compatible)
  • New feature (non-breaking change which adds functionality and tests!)
  • Breaking change (fix or feature that would cause existing functionality to change)

PR Type

Enhancement


Description

  • Add LogToConsole property to DriverService class

  • Enable driver process console output logging (disabled by default)

  • Handle mutual exclusivity between LogToConsole and LogPath in Firefox


Diagram Walkthrough

flowchart LR
  A["DriverService"] --> B["LogToConsole Property"]
  B --> C["Process Start Configuration"]
  C --> D["Console Output Control"]
  E["FirefoxDriverService"] --> F["LogPath vs LogToConsole"]
  F --> G["Mutual Exclusivity Logic"]
Loading

File Walkthrough

Relevant files
Enhancement
DriverService.cs
Add LogToConsole property and output redirection                 

dotnet/src/webdriver/DriverService.cs

  • Add LogToConsole boolean property with XML documentation
  • Configure process to redirect standard output/error when LogToConsole
    is false
+13/-0   
FirefoxDriverService.cs
Handle LogToConsole and LogPath mutual exclusivity             

dotnet/src/webdriver/Firefox/FirefoxDriverService.cs

  • Add logic to handle mutual exclusivity between LogToConsole and
    LogPath
  • Disable LogToConsole when LogPath is specified
+7/-3     

This will be false by default, following what the

.NET bindings have usually done.

Helps with #12273
@diemol diemol requested a review from nvborisenko July 28, 2025 09:46
@selenium-ci selenium-ci added the C-dotnet .NET Bindings label Jul 28, 2025
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Logic Issue

The mutual exclusivity logic modifies the LogToConsole property after it has been set by the user, which could be unexpected behavior. Consider using a local variable or different approach to handle the precedence without modifying the user-set property value.

if (this.LogToConsole)
{
    this.LogToConsole = false;
    eventArgs.DriverServiceProcessStartInfo.RedirectStandardOutput = true;
    eventArgs.DriverServiceProcessStartInfo.RedirectStandardError = true;
}
Missing Documentation

The LogToConsole property lacks documentation about its interaction with other logging mechanisms like LogPath in derived classes, which could lead to confusion about expected behavior.

/// <summary>
/// Gets or sets a value indicating whether the driver process console output should be logged
/// to the console. Defaults to <see langword="false"/>, meaning console output from the
/// driver will be suppressed.
/// </summary>
public bool LogToConsole { get; set; }

Copy link
Contributor

qodo-merge-pro bot commented Jul 28, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix conditional redirection logic
Suggestion Impact:The suggestion was directly implemented - the conditional check for LogToConsole was removed and the redirection settings are now applied unconditionally when LogPath is set

code diff:

-            if (this.LogToConsole)
-            {
-                this.LogToConsole = false;
-                eventArgs.DriverServiceProcessStartInfo.RedirectStandardOutput = true;
-                eventArgs.DriverServiceProcessStartInfo.RedirectStandardError = true;
-            }
+            eventArgs.DriverServiceProcessStartInfo.RedirectStandardOutput = true;
+            eventArgs.DriverServiceProcessStartInfo.RedirectStandardError = true;

The redirection should be set unconditionally when LogPath is specified, not
just when LogToConsole is true. This ensures proper log file functionality
regardless of the LogToConsole state.

dotnet/src/webdriver/Firefox/FirefoxDriverService.cs [216-222]

 // LogToConsole and LogPath are mutually exclusive. LogPath takes precedence.
-if (this.LogToConsole)
-{
-    this.LogToConsole = false;
-    eventArgs.DriverServiceProcessStartInfo.RedirectStandardOutput = true;
-    eventArgs.DriverServiceProcessStartInfo.RedirectStandardError = true;
-}
+this.LogToConsole = false;
+eventArgs.DriverServiceProcessStartInfo.RedirectStandardOutput = true;
+eventArgs.DriverServiceProcessStartInfo.RedirectStandardError = true;

[Suggestion processed]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a bug where setting the LogPath will not work as expected unless LogToConsole is also true, which is a significant flaw in the new logic.

High
  • Update

diemol and others added 2 commits August 3, 2025 22:39
Messages will be shown to the console
using the Logger functionality.

Adding a test that listens to the
logger and checks that logs are being
sent to console.

Fixing an issue when sending the log
to a file, as the OnDriverProcessStarted
method in the base class was not being
invoked.
diemol and others added 4 commits August 3, 2025 23:16
Internal variable to avoid using
the stream when logs are sent to a file.

Not exposed to the user.
@@ -305,6 +317,16 @@ protected virtual void OnDriverProcessStarted(DriverProcessStartedEventArgs even
throw new ArgumentNullException(nameof(eventArgs), "eventArgs must not be null");
}

if (this.WriteDriverLogToConsole && eventArgs.StandardOutputStreamReader != null)
{
_ = Task.Run(() => ReadStreamAsync(eventArgs.StandardOutputStreamReader, "stdout"));
Copy link
Member

Choose a reason for hiding this comment

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

Don't use async Tasks to capture log messages. By the nature async is unpredictable when exactly it will be executed, meaning for us we will see messed log messages.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good suggestion. I wasn't aware of that in .NET.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just pushed changes to do sync threads instead.

/// Collects the driver log output and writes it to the console. Defaults to <see langword="true"/>.
/// Internal variable to avoid using the stream when logs are sent to a file.
/// </summary>
protected bool WriteDriverLogToConsole { get; set; } = true;
Copy link
Member

Choose a reason for hiding this comment

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

I am pretty sure we don't need this property, despite its name is not clear. Just don't introduce it.

Copy link
Member Author

@diemol diemol Aug 4, 2025

Choose a reason for hiding this comment

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

In the case of sending GeckoDriver logs to a file, if we don't have a flag, even if it is internal, the streams get consumed by the console and the file. This ends up in an error because the console consumes the stream, and nothing gets sent to the file. That is why we need it.

@diemol diemol added this to the Selenium 4.35 milestone Aug 5, 2025
@nvborisenko
Copy link
Member

Please see minimal example how to capture output from process. Probably it helps.

var service = new MyService();
service.Start();

class MyService
{
    public void Start()
    {
        var process = new Process();

        process.StartInfo.FileName = "ping";
        process.StartInfo.Arguments = "google.com";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;

        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;

        process.OutputDataReceived += OnDataReceived;
        process.ErrorDataReceived += OnDataReceived;

        process.Start();

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        process.WaitForExit();
    }

    protected virtual void OnDataReceived(object sender, DataReceivedEventArgs args)
    {
        if (string.IsNullOrEmpty(args.Data))
            return;

        // This method can be used to handle data received from the process
        Console.WriteLine($"Data received: {args.Data}");
    }
}

@diemol
Copy link
Member Author

diemol commented Aug 5, 2025

Thanks. I did try the approach and made changes to use the idea you suggest, but then I end up with errors like this one:

1) Error : OpenQA.Selenium.Firefox.FirefoxDriverServiceTest.ShouldRedirectGeckoDriverLogsToConsole
System.InvalidOperationException : Cannot mix synchronous and asynchronous operation on process stream.
   at System.Diagnostics.Process.BeginOutputReadLine()
   at OpenQA.Selenium.DriverService.Start()
   at OpenQA.Selenium.Remote.DriverServiceCommandExecutor.ExecuteAsync(Command commandToExecute)
   at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.WebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.WebDriver.StartSession(ICapabilities capabilities)
   at OpenQA.Selenium.WebDriver..ctor(ICommandExecutor executor, ICapabilities capabilities)
   at OpenQA.Selenium.Firefox.FirefoxDriver..ctor(FirefoxDriverService service, FirefoxOptions options, TimeSpan commandTimeout)
   at OpenQA.Selenium.Firefox.FirefoxDriver..ctor(FirefoxDriverService service, FirefoxOptions options)
   at OpenQA.Selenium.Firefox.FirefoxDriverServiceTest.ShouldRedirectGeckoDriverLogsToConsole() in ./dotnet/test/firefox/FirefoxDriverServiceTest.cs:line 88
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Do you have any suggestions? I am only trying to log messages to console here, not even trying to log to a file yet.

@diemol
Copy link
Member Author

diemol commented Aug 5, 2025

Please disregard the message above, I found out why this happens.

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.

[🐛 Bug]: [dotnet] Selenium Library should never write to my console
3 participants