Skip to content

Commit

Permalink
ReadMe and some fixes for ZLoggerOptions.CaptureThreadInfo, LogInfo.T…
Browse files Browse the repository at this point in the history
…hreadInfo
  • Loading branch information
neuecc committed Sep 12, 2024
1 parent d2fe96e commit 1ef23c0
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 15 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,7 @@ Additional information about when each log was written can be obtained from this
| `EventId EventId` | EventId of `Microsoft.Extensions.Logging` |
| `Exception? Exception` | Exception given as argument when logging. |
| `LogScopeState? ScopeState` | Additional properties set by `ILogger.BeginScope(...)` (if ZLoggerOptions.IncludeScopes = true) |
| `ThreadInfo ThreadInfo` | Additional properties set by ZLoggerOptions.CaptureThreadInfo = true) |
| `object? Context` | Additional context |
| `string? MemberName` | Caller MemberName |
| `string? FilePath` | Caller FilePath |
Expand All @@ -658,6 +659,7 @@ The following are common option items for all providers.
|:-----------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `bool IncludeScopes { get; set; }` | Enable `ILogger.BeginScope`, default is `false`. |
| `bool IsFormatLogImmediatelyInStandardLog { get; set; }` | Fallback of standard logger.Log, message stringify immediately or not. Default is `true`. |
| `bool CaptureThreadInfo { get; set; }` | Capture information about the thread that generated a log entry. Default is `false`. |
| `TimeProvider? TimeProvider { get; set; }` | Gets or sets the time provider for the logger. The Timestamp of LogInfo is generated by TimeProvider's GetUtcNow() and LocalTimeZone when TimeProvider is set. The default value is null, which means use the system standard. |
| `Action<Exception>? InternalErrorLogger { get; set; }` | `InternalErrorLogger` is a delegate that is called when an exception occurs in the log writing process (such as a serialization error). The default value is `null`, which means errors are ignored. |
| `CreateFormatter()` | Create an formatter to use in ZLoggerProvider. |
Expand Down
11 changes: 9 additions & 2 deletions src/ZLogger/LogInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

namespace ZLogger;

public readonly struct LogInfo(LogCategory category, Timestamp timestamp, LogLevel logLevel, EventId eventId, Exception? exception, LogScopeState? scopeState, ThreadInfo? threadInfo, object? context = null, string? memberName = null, string? filePath = null, int lineNumber = 0)
public readonly struct LogInfo(LogCategory category, Timestamp timestamp, LogLevel logLevel, EventId eventId, Exception? exception, LogScopeState? scopeState, ThreadInfo threadInfo, object? context = null, string? memberName = null, string? filePath = null, int lineNumber = 0)
{
public readonly LogCategory Category = category;
public readonly Timestamp Timestamp = timestamp;
public readonly LogLevel LogLevel = logLevel;
public readonly EventId EventId = eventId;
public readonly Exception? Exception = exception;
public readonly LogScopeState? ScopeState = scopeState;
public readonly ThreadInfo? ThreadInfo = threadInfo;
public readonly ThreadInfo ThreadInfo = threadInfo;
public readonly object? Context = context;
public readonly string? MemberName = memberName;
public readonly string? FilePath = filePath;
Expand Down Expand Up @@ -42,6 +42,13 @@ public override string ToString()

public readonly struct ThreadInfo(int threadId, string? threadName, bool isThreadPoolThread)
{
internal static readonly ThreadInfo Null = new ThreadInfo(-1, null, false);
internal static ThreadInfo FromCurrentThread()
{
var currentThread = Thread.CurrentThread;
return new ThreadInfo(currentThread.ManagedThreadId, currentThread.Name, currentThread.IsThreadPoolThread);
}

public readonly int ThreadId = threadId;
public readonly string? ThreadName = threadName;
public readonly bool IsThreadPoolThread = isThreadPoolThread;
Expand Down
13 changes: 4 additions & 9 deletions src/ZLogger/ZLoggerLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,14 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
var callerFilePath = default(string?);
var callerLineNumber = default(int);
var context = default(object?);
if (state is IZLoggerAdditionalInfo additionalInfo)
{
(context, callerMemberName, callerFilePath, callerLineNumber) = additionalInfo.GetAdditionalInfo();
}

var threadInfo = default(ThreadInfo?);
if (captureThreadInfo)
// if( is ) -> ((T)).Method() is common pattern to avoid struct boxing for JIT, see: https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs,337
if (state is IZLoggerAdditionalInfo)
{
var currentThread = Thread.CurrentThread;
threadInfo = new ThreadInfo(currentThread.ManagedThreadId, currentThread.Name, currentThread.IsThreadPoolThread);
(context, callerMemberName, callerFilePath, callerLineNumber) = ((IZLoggerAdditionalInfo)state).GetAdditionalInfo();
}

var info = new LogInfo(category, new Timestamp(timeProvider), logLevel, eventId, exception, scopeState, threadInfo, context, callerMemberName, callerFilePath, callerLineNumber);
var info = new LogInfo(category, new Timestamp(timeProvider), logLevel, eventId, exception, scopeState, captureThreadInfo ? ThreadInfo.FromCurrentThread() : ThreadInfo.Null, context, callerMemberName, callerFilePath, callerLineNumber);

IZLoggerEntry entry;
if (state is VersionedLogState)
Expand Down
10 changes: 6 additions & 4 deletions tests/ZLogger.Tests/CallerInfoTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ public void CallerInfo()
Path.GetFileName(x.LogInfo.FilePath).Should().Be("CallerInfoTest.cs");
x.LogInfo.LineNumber.Should().Be(23);

x.LogInfo.ThreadInfo.Should().NotBeNull();
x.LogInfo.ThreadInfo!.Value.ThreadId.Should().Be(System.Environment.CurrentManagedThreadId);
x.LogInfo.ThreadInfo!.Value.IsThreadPoolThread.Should().Be(true);
x.LogInfo.ThreadInfo!.Value.ThreadName.Should().Be(".NET TP Worker");
var currentThread = System.Threading.Thread.CurrentThread;

x.LogInfo.ThreadInfo.ThreadId.Should().NotBe(-1);
x.LogInfo.ThreadInfo.ThreadId.Should().Be(currentThread.ManagedThreadId);
x.LogInfo.ThreadInfo.IsThreadPoolThread.Should().Be(currentThread.IsThreadPoolThread);
x.LogInfo.ThreadInfo.ThreadName.Should().Be(currentThread.Name);
}
}

0 comments on commit 1ef23c0

Please sign in to comment.