初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace PCL.Core.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft.Extensions.Logging.ILogger 适配器
|
||||
/// 将现有的 Logger 包装为标准的 ILogger 接口实现
|
||||
/// </summary>
|
||||
public class LoggerAdapter(Logger logger, string categoryName) : ILogger
|
||||
{
|
||||
private readonly Logger _innerLogger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
private readonly string _categoryName = categoryName ?? throw new ArgumentNullException(nameof(categoryName));
|
||||
|
||||
private static readonly AsyncLocal<Stack<object>> _ScopeStack = new();
|
||||
|
||||
IDisposable ILogger.BeginScope<TState>(TState state)
|
||||
{
|
||||
_ScopeStack.Value ??= new Stack<object>();
|
||||
_ScopeStack.Value.Push(state);
|
||||
return new ScopeDisposable(state);
|
||||
}
|
||||
|
||||
#pragma warning disable CS9113 // 参数未读。
|
||||
private class ScopeDisposable(object state) : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (_ScopeStack.Value is { Count: > 0 })
|
||||
{
|
||||
#if DEBUG
|
||||
var popped = _ScopeStack.Value.Pop();
|
||||
if (!ReferenceEquals(popped, state))
|
||||
{
|
||||
throw new InvalidOperationException("Scope disposal order mismatch.");
|
||||
}
|
||||
#else
|
||||
_ = _ScopeStack.Value.Pop();
|
||||
#endif
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel level) => true;
|
||||
|
||||
public void Log<TState>(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
if (!IsEnabled(logLevel))
|
||||
return;
|
||||
|
||||
ArgumentNullException.ThrowIfNull(formatter);
|
||||
|
||||
var originalMessage = formatter(state, exception);
|
||||
var sb = new StringBuilder();
|
||||
|
||||
// 类别名称
|
||||
if (!string.IsNullOrEmpty(_categoryName))
|
||||
{
|
||||
sb.Append('[').Append(_categoryName).Append("] ");
|
||||
}
|
||||
|
||||
// 事件 ID
|
||||
if (eventId.Id != 0 || !string.IsNullOrEmpty(eventId.Name))
|
||||
{
|
||||
sb.Append("[EventId:");
|
||||
if (!string.IsNullOrEmpty(eventId.Name))
|
||||
{
|
||||
sb.Append(eventId.Id).Append(':').Append(eventId.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(eventId.Id);
|
||||
}
|
||||
sb.Append("] ");
|
||||
}
|
||||
|
||||
// 上下文信息
|
||||
var scopeContext = _BuildScopeContext();
|
||||
if (!string.IsNullOrEmpty(scopeContext))
|
||||
{
|
||||
sb.Append('[').Append(_categoryName).Append("] ");
|
||||
}
|
||||
|
||||
sb.Append(originalMessage);
|
||||
var finalMessage = sb.ToString();
|
||||
|
||||
// 日志级别
|
||||
switch (logLevel)
|
||||
{
|
||||
case Microsoft.Extensions.Logging.LogLevel.Trace:
|
||||
_innerLogger.Trace(finalMessage);
|
||||
break;
|
||||
case Microsoft.Extensions.Logging.LogLevel.Debug:
|
||||
_innerLogger.Debug(finalMessage);
|
||||
break;
|
||||
case Microsoft.Extensions.Logging.LogLevel.Information:
|
||||
_innerLogger.Info(finalMessage);
|
||||
break;
|
||||
case Microsoft.Extensions.Logging.LogLevel.Warning:
|
||||
_innerLogger.Warn(finalMessage);
|
||||
break;
|
||||
case Microsoft.Extensions.Logging.LogLevel.Error:
|
||||
_innerLogger.Error(finalMessage);
|
||||
break;
|
||||
case Microsoft.Extensions.Logging.LogLevel.Critical:
|
||||
_innerLogger.Fatal(finalMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
if (exception is not null)
|
||||
{
|
||||
var exceptionMessage = $"Exception: {exception}";
|
||||
_innerLogger.Log($"[{_categoryName}] {exceptionMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
private string _BuildScopeContext()
|
||||
{
|
||||
var stack = _ScopeStack.Value;
|
||||
if (stack is null || stack.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var scopes = stack.AsEnumerable().Reverse();
|
||||
return string.Join(" => ", scopes.Select(s => s.ToString()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user