mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 19:03:29 +08:00
- 将所有小写的命名空间导入更正为首字母大写格式 - 统一 GFramework 框架的命名空间引用规范 - 修复 core、ecs、godot 等模块的命名空间导入错误 - 标准化文档示例代码中的 using 语句格式 - 确保所有文档中的命名空间引用保持一致性 - 更新 global using 语句以匹配正确的命名空间格式
7.4 KiB
7.4 KiB
日志生成器
GFramework.SourceGenerators 自动生成日志代码,减少样板代码
概述
日志生成器是一个 Source Generator,它会自动为标记了 [Log] 特性的类生成 ILogger 字段。这消除了手动编写日志字段的需要,让开发者专注于业务逻辑。
基本用法
标记类
using GFramework.SourceGenerators.Abstractions.Logging;
[Log]
public partial class MyService
{
public void DoSomething()
{
// 自动生成的 Logger 字段可直接使用
Logger.Info("执行操作");
}
}
生成代码
上面的代码会被编译时转换为:
// <auto-generated/>
public partial class MyService
{
private static readonly ILogger Logger =
LoggerFactoryResolver.Provider.CreateLogger("YourNamespace.MyService");
}
注意:生成器只生成 ILogger 字段,不生成日志方法。日志方法(Info、Debug、Error 等)来自 ILogger 接口本身。
日志级别
生成的 Logger 字段支持 ILogger 接口的所有方法:
[Log]
public partial class MyClass
{
public void Example()
{
// 调试信息
Logger.Debug($"调试信息: {value}");
// 普通信息
Logger.Info("操作成功");
// 警告
Logger.Warning($"警告: {message}");
// 错误
Logger.Error($"错误: {ex.Message}");
// 严重错误
Logger.Critical("系统故障");
}
}
自定义日志类别
[Log("Gameplay")]
public partial class GameplaySystem
{
// 日志会标记为 Gameplay 类别
public void Update()
{
Logger.Info("游戏逻辑更新");
}
}
配置选项
自定义字段名称
[Log(FieldName = "_customLogger")]
public partial class MyClass
{
public void DoSomething()
{
// 使用自定义字段名
_customLogger.Info("使用自定义日志器");
}
}
非静态字段
[Log(IsStatic = false)]
public partial class InstanceLogger
{
// 生成实例字段而非静态字段
public void LogMessage()
{
Logger.Info("实例日志");
}
}
访问修饰符
[Log(AccessModifier = "protected")]
public partial class ProtectedLogger
{
// 生成 protected 字段
}
配置选项说明
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| Name | string? | null | 日志分类名称(默认使用类名) |
| FieldName | string | "Logger" | 生成的字段名称 |
| IsStatic | bool | true | 是否生成静态字段 |
| AccessModifier | string | "private" | 访问修饰符(private/protected/public) |
与其他模块集成
与 Godot 集成
[Log]
[ContextAware]
public partial class GodotController : Node
{
public override void _Ready()
{
Logger.Info("控制器已准备就绪");
}
}
与架构集成
[Log]
public partial class MySystem : AbstractSystem
{
protected override void OnInit()
{
Logger.Info("系统初始化");
}
}
实际应用示例
游戏控制器
using GFramework.Core.Abstractions.Controller;
using GFramework.SourceGenerators.Abstractions.Logging;
using GFramework.SourceGenerators.Abstractions.Rule;
[Log]
[ContextAware]
public partial class PlayerController : IController
{
public void HandleInput(string action)
{
Logger.Debug($"处理输入: {action}");
switch (action)
{
case "jump":
Logger.Info("玩家跳跃");
Jump();
break;
case "attack":
Logger.Info("玩家攻击");
Attack();
break;
default:
Logger.Warning($"未知操作: {action}");
break;
}
}
private void Jump()
{
try
{
// 跳跃逻辑
Logger.Debug("跳跃执行成功");
}
catch (Exception ex)
{
Logger.Error($"跳跃失败: {ex.Message}");
}
}
}
数据处理服务
[Log("DataService")]
public partial class DataProcessor
{
public void ProcessData(string data)
{
Logger.Info($"开始处理数据,长度: {data.Length}");
if (string.IsNullOrEmpty(data))
{
Logger.Warning("数据为空,跳过处理");
return;
}
try
{
// 处理逻辑
Logger.Debug("数据处理中...");
// ...
Logger.Info("数据处理完成");
}
catch (Exception ex)
{
Logger.Error($"数据处理失败: {ex.Message}");
throw;
}
}
}
最佳实践
1. 合理使用日志级别
[Log]
public partial class BestPracticeExample
{
public void ProcessRequest()
{
// Debug: 详细的调试信息
Logger.Debug("开始处理请求");
// Info: 重要的业务流程信息
Logger.Info("请求处理成功");
// Warning: 可恢复的异常情况
Logger.Warning("缓存未命中,使用默认值");
// Error: 错误但不影响系统运行
Logger.Error("处理失败,将重试");
// Critical: 严重错误,可能导致系统崩溃
Logger.Critical("数据库连接失败");
}
}
2. 避免过度日志
[Log]
public partial class PerformanceExample
{
private int _frameCount = 0;
public void Update()
{
// 好的做法:定期记录
if (_frameCount % 1000 == 0)
{
Logger.Debug($"已运行 {_frameCount} 帧");
}
_frameCount++;
// 避免:每帧都记录
// Logger.Debug($"帧 {_frameCount}"); // ❌ 太频繁
}
}
3. 结构化日志信息
[Log]
public partial class StructuredLogging
{
public void ProcessUser(int userId, string action)
{
// 好的做法:包含上下文信息
Logger.Info($"用户操作 [UserId={userId}, Action={action}]");
// 避免:信息不完整
// Logger.Info("用户操作"); // ❌ 缺少上下文
}
}
常见问题
Q: 为什么需要 partial 关键字?
A: 源代码生成器需要向现有类添加代码,partial 关键字允许一个类的定义分散在多个文件中。
Q: 可以在静态类中使用吗?
A: 可以,生成器会自动生成静态字段:
[Log]
public static partial class StaticHelper
{
public static void DoSomething()
{
Logger.Info("静态方法日志");
}
}
Q: 如何自定义日志工厂?
A: 通过配置 LoggerFactoryResolver.Provider 来自定义日志工厂实现。
相关文档: