Updated
This commit is contained in:
@@ -14,7 +14,7 @@ It features a rich fluent API for routing log events to dozens of destinations f
|
||||
<Copyright>EonaCat (Jeroen Saey)</Copyright>
|
||||
<PackageTags>EonaCat;Logger;EonaCatLogStack;Log;Writer;Flows;LogStack;Memory;Speed;Jeroen;Saey</PackageTags>
|
||||
<PackageIconUrl />
|
||||
<FileVersion>0.2.1</FileVersion>
|
||||
<FileVersion>0.2.2</FileVersion>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
@@ -25,7 +25,7 @@ It features a rich fluent API for routing log events to dozens of destinations f
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<EVRevisionFormat>0.2.1+{chash:10}.{c:ymd}</EVRevisionFormat>
|
||||
<EVRevisionFormat>0.2.2+{chash:10}.{c:ymd}</EVRevisionFormat>
|
||||
<EVDefault>true</EVDefault>
|
||||
<EVInfo>true</EVInfo>
|
||||
<EVTagMatch>v[0-9]*</EVTagMatch>
|
||||
@@ -36,7 +36,7 @@ It features a rich fluent API for routing log events to dozens of destinations f
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>0.2.1</Version>
|
||||
<Version>0.2.2</Version>
|
||||
<PackageId>EonaCat.LogStack</PackageId>
|
||||
<Product>EonaCat.LogStack</Product>
|
||||
<RepositoryUrl>https://git.saey.me/EonaCat/EonaCat.LogStack</RepositoryUrl>
|
||||
|
||||
@@ -177,6 +177,13 @@ namespace EonaCat.LogStack
|
||||
private LogLevel EffectiveMinLevel() =>
|
||||
_dynamicLevel != null ? _dynamicLevel.CurrentLevel : _minimumLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether an event at the specified level would be accepted.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsEnabled(LogLevel level) =>
|
||||
Volatile.Read(ref _disposed) == 0 && level >= EffectiveMinLevel();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a flow (output destination) to this logger
|
||||
/// </summary>
|
||||
@@ -418,14 +425,65 @@ namespace EonaCat.LogStack
|
||||
ProcessLogEvent(ref builder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an exception together with structured properties.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Log(LogLevel level, Exception exception, string message, params (string Key, object Value)[] properties)
|
||||
{
|
||||
if (Volatile.Read(ref _disposed) == 1 || level < EffectiveMinLevel())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TrackLevel(level);
|
||||
Interlocked.Increment(ref _totalExceptionsCount);
|
||||
|
||||
var builder = new LogEventBuilder()
|
||||
.WithLevel(level)
|
||||
.WithCategory(_category)
|
||||
.WithMessage(message)
|
||||
.WithException(exception)
|
||||
.WithTimestamp(GetTimestamp());
|
||||
|
||||
foreach (var (key, value) in properties)
|
||||
{
|
||||
builder.WithProperty(key, value);
|
||||
}
|
||||
|
||||
ProcessLogEvent(ref builder);
|
||||
}
|
||||
|
||||
private void Write(LogLevel level, string template, params object[] args)
|
||||
{
|
||||
Log(level, string.Format(template, args));
|
||||
Log(level, FormatTemplate(template, args));
|
||||
}
|
||||
|
||||
private void Write(LogLevel level, Exception ex, string template, params object[] args)
|
||||
{
|
||||
Log(level, ex, string.Format(template, args));
|
||||
Log(level, ex, FormatTemplate(template, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a message template, supporting both Serilog-style named holes (e.g. "{UserId}")
|
||||
/// and classic string.Format-style positional holes (e.g. "{0}"). Never throws on malformed
|
||||
/// templates; falls back to the raw template text instead.
|
||||
/// </summary>
|
||||
private static string FormatTemplate(string template, object[] args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(template))
|
||||
{
|
||||
return template;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return MessageTemplate.FromCache(template).Render(args, out _);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
||||
public void Trace(string template, params object[] args) => Write(LogLevel.Trace, template, args);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace EonaCat.LogStack.Logging;
|
||||
|
||||
@@ -40,7 +42,7 @@ internal sealed class CategoryLogger : Microsoft.Extensions.Logging.ILogger
|
||||
=> _scopes?.Push(state) ?? NullScope.Instance;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
=> logLevel != LogLevel.None;
|
||||
=> logLevel != LogLevel.None && _EonaCatLogStack.IsEnabled(logLevel.FromLogLevel());
|
||||
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel,
|
||||
@@ -55,18 +57,55 @@ internal sealed class CategoryLogger : Microsoft.Extensions.Logging.ILogger
|
||||
}
|
||||
|
||||
var message = formatter(state, exception);
|
||||
|
||||
_scopes?.ForEachScope<object?>((scope, _) =>
|
||||
var properties = new List<(string Key, object Value)>(4)
|
||||
{
|
||||
message = $"{message} | Scope={scope}";
|
||||
}, null);
|
||||
("Category", _category),
|
||||
("EventId", eventId.Id)
|
||||
};
|
||||
|
||||
if (exception != null)
|
||||
if (!string.IsNullOrEmpty(eventId.Name))
|
||||
{
|
||||
message = $"{message} | Exception={exception}";
|
||||
properties.Add(("EventName", eventId.Name));
|
||||
}
|
||||
|
||||
_EonaCatLogStack.Log($"[{logLevel}] [{_category}] {message}");
|
||||
if (state is IEnumerable<KeyValuePair<string, object?>> structuredState)
|
||||
{
|
||||
foreach (var pair in structuredState)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(pair.Key) && pair.Value != null)
|
||||
{
|
||||
properties.Add((pair.Key, pair.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_scopes?.ForEachScope<List<(string Key, object Value)>>((scope, stateProperties) =>
|
||||
{
|
||||
if (scope is IEnumerable<KeyValuePair<string, object?>> structuredScope)
|
||||
{
|
||||
foreach (var pair in structuredScope)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(pair.Key) && pair.Value != null)
|
||||
{
|
||||
stateProperties.Add((pair.Key, pair.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (scope != null)
|
||||
{
|
||||
stateProperties.Add(("Scope", scope));
|
||||
}
|
||||
}, properties);
|
||||
|
||||
var level = logLevel.FromLogLevel();
|
||||
if (exception == null)
|
||||
{
|
||||
_EonaCatLogStack.Log(level, message, properties.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
_EonaCatLogStack.Log(level, exception, message, properties.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user