-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[dotnet] Possibility to output internal log messages to file #13249
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
Merged
nvborisenko
merged 85 commits into
SeleniumHQ:trunk
from
nvborisenko:dotnet-logging-file
Dec 7, 2023
Merged
Changes from all commits
Commits
Show all changes
85 commits
Select commit
Hold shift + click to select a range
0688c8b
INitial implementation
nvborisenko 091ee36
With context
nvborisenko eea4ab6
Update HttpCommandExecutor.cs
nvborisenko f8c27f8
Nullable handlers
nvborisenko 3cee19d
Don't capture logger
nvborisenko c722c4e
Log message issuer
nvborisenko 16c3cae
Simplify things
nvborisenko d7ceb67
Merge remote-tracking branch 'upstream/trunk' into dotnet-logging
nvborisenko 2a85e27
Continue
nvborisenko 4fca9a3
Merge remote-tracking branch 'upstream/trunk' into dotnet-logging
nvborisenko 4c7ba77
Update nunit adapter to work with dotnet 7 and be more friendly with …
nvborisenko 0dc4b35
Merge remote-tracking branch 'upstream/trunk' into dotnet-logging
nvborisenko 1042d4e
Rename to LogEventLevel
nvborisenko eae7f4c
Typo
nvborisenko 0b7c610
Introduce LogContextManager
nvborisenko 1390b1e
Typo again
nvborisenko e87773e
Rename to Timestamp
nvborisenko b874730
Make ILogger as static field
nvborisenko fcf811c
Support hierarchical contexts
nvborisenko 3a9dbaf
Rename to EmitMessage
nvborisenko ca73016
Do not emit message to parent context
nvborisenko bf004d6
Deep copy of loggers and handlers per context
nvborisenko 88cb872
Make fields private
nvborisenko 9795e8f
Static works with current log context
nvborisenko 6f3e484
Create context with minimum level
nvborisenko 478ae5a
Set minimum level for context
nvborisenko 5f54cfa
Rename to WithHandler
nvborisenko 571479a
Set minimum level per issuer
nvborisenko edb14d3
Simplify getting internal logger
nvborisenko 4573398
Use DateTimeOffset
nvborisenko 044fc86
Docs for log event level
nvborisenko 13b00f6
Docs for ILogger
nvborisenko 34b9b40
Docs for Logger
nvborisenko cec3811
Docs for others
nvborisenko 3cf6e48
Make ILogger interface as internal
nvborisenko c7dd8ed
Revert "Make ILogger interface as internal"
nvborisenko 7a02443
First test
nvborisenko 339e4f9
Merge remote-tracking branch 'upstream/trunk' into dotnet-logging-test
nvborisenko 9cb6a14
Update LogTest.cs
nvborisenko c4af631
Fix build error
nvborisenko 684d565
Info minimum log level by default
nvborisenko cba7a68
Remove unnecessary log call in ChromeDriver
nvborisenko 84da458
Adjust log levels in console output
nvborisenko 48bd407
Make it length fixed
nvborisenko cd46467
Make webdriver assembly internals visible to tests
nvborisenko 1d1cfc5
Make ILogger hidden from user
nvborisenko d7d22b2
More tests for log context
nvborisenko f96fadb
Init
nvborisenko a6271e7
Rename back to AddHandler
nvborisenko fbc36ab
Make format script happy?
nvborisenko 0514324
Make format script happy?
nvborisenko 3314553
Rename back to SetLevel
nvborisenko 479c357
Console handler by default
nvborisenko 20a66ae
Output logs to stderr
nvborisenko 5fb6acf
New api to mange log handlers
nvborisenko 4681724
Merge branch 'trunk' into dotnet-logging
nvborisenko e3255a6
Use logging in DriverFactory
nvborisenko 0167dfa
Revert "Use logging in DriverFactory"
nvborisenko 7ac3376
Verbose driver creation in tests
nvborisenko 225474c
Search driver type in loaded assemblies
nvborisenko 9b61d8a
Decalare internals visible to in csproj to not conflict with bazel
nvborisenko 3e35ca7
Clean specific assembly name for driver type
nvborisenko b7bd127
Merge branch 'trunk' into dotnet-logging
nvborisenko 9663bc3
Merge branch 'trunk' into dotnet-logging
nvborisenko 5ff197f
Merge remote-tracking branch 'upstream/trunk' into dotnet-logging
nvborisenko 0885002
Old school using to make bazel happy
nvborisenko 1138648
Fix targeting packs for test targets
nvborisenko bcf9e0c
Merge branch 'dotnet-logging' into dotnet-logging-file
nvborisenko 049e646
It works
nvborisenko 8c952e9
Small clean up
nvborisenko 9f47cb5
Lock in ctor
nvborisenko 1a6803e
Dispose at process exit
nvborisenko bea874f
Merge remote-tracking branch 'upstream/trunk' into dotnet-logging-file
nvborisenko 418ae88
Remove redundant Clone for log handlers
nvborisenko b7e09d6
Dispose log handlers when context finishes
nvborisenko 5814e27
Lock writing to the disk globally
nvborisenko 001641b
Fix new list of log handlers for context
nvborisenko aa9626f
Don't lock in ctor
nvborisenko 1a4b87b
Add docs
nvborisenko 2b19228
Change format of datetime in file log
nvborisenko dbebb14
Thread safe disposing
nvborisenko d368244
Add finilizer
nvborisenko 060cf77
Docs for finilizer
nvborisenko db63f60
Add tests
nvborisenko 8076316
Recreating missing dirs
nvborisenko File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using System; | ||
using System.IO; | ||
|
||
namespace OpenQA.Selenium.Internal.Logging | ||
{ | ||
/// <summary> | ||
/// Represents a log handler that writes log events to a file. | ||
/// </summary> | ||
public class FileLogHandler : ILogHandler, IDisposable | ||
{ | ||
// performance trick to avoid expensive Enum.ToString() with fixed length | ||
private static readonly string[] _levels = { "TRACE", "DEBUG", " INFO", " WARN", "ERROR" }; | ||
|
||
private FileStream _fileStream; | ||
private StreamWriter _streamWriter; | ||
|
||
private readonly object _lockObj = new object(); | ||
private bool _isDisposed; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="FileLogHandler"/> class with the specified file path. | ||
/// </summary> | ||
/// <param name="path">The path of the log file.</param> | ||
public FileLogHandler(string path) | ||
{ | ||
if (string.IsNullOrEmpty(path)) throw new ArgumentException("File log path cannot be null or empty.", nameof(path)); | ||
|
||
var directory = Path.GetDirectoryName(path); | ||
if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) | ||
{ | ||
Directory.CreateDirectory(directory); | ||
} | ||
|
||
_fileStream = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); | ||
_fileStream.Seek(0, SeekOrigin.End); | ||
_streamWriter = new StreamWriter(_fileStream, System.Text.Encoding.UTF8) | ||
{ | ||
AutoFlush = true | ||
}; | ||
} | ||
|
||
/// <summary> | ||
/// Handles a log event by writing it to the log file. | ||
/// </summary> | ||
/// <param name="logEvent">The log event to handle.</param> | ||
public void Handle(LogEvent logEvent) | ||
{ | ||
lock (_lockObj) | ||
{ | ||
_streamWriter.WriteLine($"{logEvent.Timestamp:r} {_levels[(int)logEvent.Level]} {logEvent.IssuedBy.Name}: {logEvent.Message}"); | ||
nvborisenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
/// <summary> | ||
/// Disposes the file log handler and releases any resources used. | ||
/// </summary> | ||
public void Dispose() | ||
{ | ||
Dispose(true); | ||
GC.SuppressFinalize(this); | ||
} | ||
|
||
/// <summary> | ||
/// Finalizes the file log handler instance. | ||
/// </summary> | ||
~FileLogHandler() | ||
{ | ||
Dispose(false); | ||
} | ||
|
||
/// <summary> | ||
/// Disposes the file log handler and releases any resources used. | ||
/// </summary> | ||
/// <param name="disposing">A flag indicating whether to dispose managed resources.</param> | ||
protected virtual void Dispose(bool disposing) | ||
{ | ||
lock (_lockObj) | ||
{ | ||
if (!_isDisposed) | ||
{ | ||
if (disposing) | ||
{ | ||
_streamWriter?.Dispose(); | ||
_streamWriter = null; | ||
_fileStream?.Dispose(); | ||
_fileStream = null; | ||
} | ||
|
||
_isDisposed = true; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using NUnit.Framework; | ||
using System; | ||
using System.IO; | ||
|
||
namespace OpenQA.Selenium.Internal.Logging | ||
{ | ||
public class FileLogHandlerTest | ||
{ | ||
[Test] | ||
nvborisenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
[TestCase(null)] | ||
[TestCase("")] | ||
public void ShouldNotAcceptIncorrectPath(string path) | ||
{ | ||
var act = () => new FileLogHandler(path); | ||
|
||
Assert.That(act, Throws.ArgumentException); | ||
} | ||
|
||
[Test] | ||
public void ShouldHandleLogEvent() | ||
{ | ||
var tempFile = Path.GetTempFileName(); | ||
|
||
try | ||
{ | ||
using (var fileLogHandler = new FileLogHandler(tempFile)) | ||
{ | ||
fileLogHandler.Handle(new LogEvent(typeof(FileLogHandlerTest), DateTimeOffset.Now, LogEventLevel.Info, "test message")); | ||
} | ||
|
||
Assert.That(File.ReadAllText(tempFile), Does.Contain("test message")); | ||
} | ||
catch (Exception) | ||
{ | ||
throw; | ||
} | ||
nvborisenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||
finally | ||
{ | ||
File.Delete(tempFile); | ||
} | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.