---
title: Godot 日志系统
description: Godot 日志系统提供了 GFramework 日志功能与 Godot 引擎控制台的完整集成。
---

# Godot 日志系统

## 概述

Godot 日志系统是 GFramework.Godot 中连接框架日志功能与 Godot 引擎控制台的核心组件。它提供了与 Godot
控制台的深度集成，支持彩色输出、多级别日志记录，以及与 GFramework 日志系统的无缝对接。

通过 Godot 日志系统，你可以在 Godot 项目中使用统一的日志接口，日志会自动输出到 Godot 编辑器控制台，并根据日志级别使用不同的颜色和输出方式。

**主要特性**：

- 与 Godot 控制台深度集成
- 支持彩色日志输出
- 多级别日志记录（Trace、Debug、Info、Warning、Error、Fatal）
- 日志缓存机制
- 时间戳和格式化支持
- 异常信息记录

## 核心概念

### GodotLogger

`GodotLogger` 是 Godot 平台的日志记录器实现，继承自 `AbstractLogger`：

```csharp
public sealed class GodotLogger : AbstractLogger
{
    public GodotLogger(string? name = null, LogLevel minLevel = LogLevel.Info);
    protected override void Write(LogLevel level, string message, Exception? exception);
}
```

### GodotLoggerFactory

`GodotLoggerFactory` 用于创建 Godot 日志记录器实例：

```csharp
public class GodotLoggerFactory : ILoggerFactory
{
    public ILogger GetLogger(string name, LogLevel minLevel = LogLevel.Info);
}
```

### GodotLoggerFactoryProvider

`GodotLoggerFactoryProvider` 提供日志工厂实例，并支持日志缓存：

```csharp
public sealed class GodotLoggerFactoryProvider : ILoggerFactoryProvider
{
    public LogLevel MinLevel { get; set; }
    public ILogger CreateLogger(string name);
}
```

## 基本用法

### 配置 Godot 日志系统

在架构初始化时配置日志提供程序：

```csharp
using GFramework.Godot.Architecture;
using GFramework.Godot.Logging;
using GFramework.Core.Logging;
using GFramework.Core.Abstractions.Logging;

public class GameArchitecture : AbstractArchitecture
{
    public static GameArchitecture Interface { get; private set; }

    public GameArchitecture()
    {
        Interface = this;

        // 配置 Godot 日志系统
        LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
        {
            MinLevel = LogLevel.Debug  // 设置最小日志级别
        };
    }

    protected override void InstallModules()
    {
        var logger = LoggerFactoryResolver.Provider.CreateLogger("GameArchitecture");
        logger.Info("游戏架构初始化开始");

        RegisterModel(new PlayerModel());
        RegisterSystem(new GameplaySystem());

        logger.Info("游戏架构初始化完成");
    }
}
```

### 创建和使用日志记录器

```csharp
using Godot;
using GFramework.Core.Logging;
using GFramework.Core.Abstractions.Logging;

public partial class Player : CharacterBody2D
{
    private ILogger _logger;

    public override void _Ready()
    {
        // 创建日志记录器
        _logger = LoggerFactoryResolver.Provider.CreateLogger("Player");

        _logger.Info("玩家初始化");
        _logger.Debug("玩家位置: {0}", Position);
    }

    public override void _Process(double delta)
    {
        if (_logger.IsDebugEnabled())
        {
            _logger.Debug("玩家速度: {0}", Velocity);
        }
    }

    private void TakeDamage(float damage)
    {
        _logger.Warn("玩家受到伤害: {0}", damage);
    }

    private void OnError()
    {
        _logger.Error("玩家状态异常");
    }
}
```

### 记录不同级别的日志

```csharp
var logger = LoggerFactoryResolver.Provider.CreateLogger("GameSystem");

// Trace - 最详细的跟踪信息（灰色）
logger.Trace("执行函数: UpdatePlayerPosition");

// Debug - 调试信息（青色）
logger.Debug("当前帧率: {0}", Engine.GetFramesPerSecond());

// Info - 一般信息（白色）
logger.Info("游戏开始");

// Warning - 警告信息（黄色）
logger.Warn("资源加载缓慢: {0}ms", loadTime);

// Error - 错误信息（红色）
logger.Error("无法加载配置文件");

// Fatal - 致命错误（红色，使用 PushError）
logger.Fatal("游戏崩溃");
```

### 记录异常信息

```csharp
var logger = LoggerFactoryResolver.Provider.CreateLogger("SaveSystem");

try
{
    SaveGame();
}
catch (Exception ex)
{
    // 记录异常信息
    logger.Error("保存游戏失败", ex);
}
```

## 高级用法

### 在 System 中使用日志

```csharp
using GFramework.Core.System;
using GFramework.Core.Logging;
using GFramework.Core.Abstractions.Logging;

public class CombatSystem : AbstractSystem
{
    private ILogger _logger;

    protected override void OnInit()
    {
        _logger = LoggerFactoryResolver.Provider.CreateLogger("CombatSystem");
        _logger.Info("战斗系统初始化完成");
    }

    public void ProcessCombat(Entity attacker, Entity target, float damage)
    {
        _logger.Debug("战斗处理: {0} 攻击 {1}, 伤害: {2}",
            attacker.Name, target.Name, damage);

        if (damage > 100)
        {
            _logger.Warn("高伤害攻击: {0}", damage);
        }
    }

    protected override void OnDestroy()
    {
        _logger.Info("战斗系统已销毁");
    }
}
```

### 在 Model 中使用日志

```csharp
using GFramework.Core.Model;
using GFramework.Core.Logging;
using GFramework.Core.Abstractions.Logging;

public class PlayerModel : AbstractModel
{
    private ILogger _logger;
    private int _health;

    protected override void OnInit()
    {
        _logger = LoggerFactoryResolver.Provider.CreateLogger("PlayerModel");
        _logger.Info("玩家模型初始化");

        _health = 100;
    }

    public void SetHealth(int value)
    {
        var oldHealth = _health;
        _health = value;

        _logger.Debug("玩家生命值变化: {0} -> {1}", oldHealth, _health);

        if (_health <= 0)
        {
            _logger.Warn("玩家生命值归零");
        }
    }
}
```

### 条件日志记录

```csharp
var logger = LoggerFactoryResolver.Provider.CreateLogger("PerformanceMonitor");

// 检查日志级别是否启用，避免不必要的字符串格式化
if (logger.IsDebugEnabled())
{
    var stats = CalculateComplexStats();  // 耗时操作
    logger.Debug("性能统计: {0}", stats);
}

// 简化写法
if (logger.IsTraceEnabled())
{
    logger.Trace("详细的执行流程信息");
}
```

### 分类日志记录

```csharp
// 为不同模块创建独立的日志记录器
var networkLogger = LoggerFactoryResolver.Provider.CreateLogger("Network");
var databaseLogger = LoggerFactoryResolver.Provider.CreateLogger("Database");
var aiLogger = LoggerFactoryResolver.Provider.CreateLogger("AI");

networkLogger.Info("连接到服务器");
databaseLogger.Debug("查询用户数据");
aiLogger.Trace("AI 决策树遍历");
```

### 自定义日志级别

```csharp
// 在开发环境使用 Debug 级别
#if DEBUG
LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
{
    MinLevel = LogLevel.Debug
};
#else
// 在生产环境使用 Info 级别
LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
{
    MinLevel = LogLevel.Info
};
#endif
```

### 在 Godot 模块中使用日志

```csharp
using GFramework.Godot.Architecture;
using GFramework.Core.Logging;
using GFramework.Core.Abstractions.Logging;
using Godot;

public class SceneModule : AbstractGodotModule
{
    private ILogger _logger;
    private Node _sceneRoot;

    public override Node Node => _sceneRoot;

    public SceneModule()
    {
        _sceneRoot = new Node { Name = "SceneRoot" };
        _logger = LoggerFactoryResolver.Provider.CreateLogger("SceneModule");
    }

    public override void Install(IArchitecture architecture)
    {
        _logger.Info("场景模块安装开始");

        // 安装场景系统
        var sceneSystem = new SceneSystem();
        architecture.RegisterSystem<ISceneSystem>(sceneSystem);

        _logger.Info("场景模块安装完成");
    }

    public override void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
    {
        _logger.Debug("场景模块阶段: {0}", phase);

        if (phase == ArchitecturePhase.Ready)
        {
            _logger.Info("场景模块已就绪");
        }
    }

    public override void OnDetach()
    {
        _logger.Info("场景模块已分离");
        _sceneRoot?.QueueFree();
    }
}
```

## 日志输出格式

### 输出格式说明

Godot 日志系统使用以下格式输出日志：

```
[时间戳] 日志级别 [日志器名称] 日志消息
```

**示例输出**：

```
[2025-01-09 10:30:45.123] INFO    [GameArchitecture] 游戏架构初始化开始
[2025-01-09 10:30:45.456] DEBUG   [Player] 玩家位置: (100, 200)
[2025-01-09 10:30:46.789] WARNING [CombatSystem] 高伤害攻击: 150
[2025-01-09 10:30:47.012] ERROR   [SaveSystem] 保存游戏失败
```

### 日志级别与 Godot 输出方法

| 日志级别        | Godot 方法         | 颜色 | 说明       |
|-------------|------------------|----|----------|
| **Trace**   | `GD.PrintRich`   | 灰色 | 最详细的跟踪信息 |
| **Debug**   | `GD.PrintRich`   | 青色 | 调试信息     |
| **Info**    | `GD.Print`       | 白色 | 一般信息     |
| **Warning** | `GD.PushWarning` | 黄色 | 警告信息     |
| **Error**   | `GD.PrintErr`    | 红色 | 错误信息     |
| **Fatal**   | `GD.PushError`   | 红色 | 致命错误     |

### 异常信息格式

当记录异常时，异常信息会附加到日志消息后：

```
[2025-01-09 10:30:47.012] ERROR   [SaveSystem] 保存游戏失败
System.IO.IOException: 文件访问被拒绝
   at SaveSystem.SaveGame() in SaveSystem.cs:line 42
```

## 最佳实践

1. **在架构初始化时配置日志系统**：
   ```csharp
   public GameArchitecture()
   {
       LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
       {
           MinLevel = LogLevel.Debug
       };
   }
   ```

2. **为每个类创建独立的日志记录器**：
   ```csharp
   private ILogger _logger;

   public override void _Ready()
   {
       _logger = LoggerFactoryResolver.Provider.CreateLogger(GetType().Name);
   }
   ```

3. **使用合适的日志级别**：
    - `Trace`：详细的执行流程，仅在深度调试时使用
    - `Debug`：调试信息，开发阶段使用
    - `Info`：重要的业务流程和状态变化
    - `Warning`：潜在问题但不影响功能
    - `Error`：错误但程序可以继续运行
    - `Fatal`：严重错误，程序无法继续

4. **检查日志级别避免性能损失**：
   ```csharp
   if (_logger.IsDebugEnabled())
   {
       var expensiveData = CalculateExpensiveData();
       _logger.Debug("数据: {0}", expensiveData);
   }
   ```

5. **提供有意义的上下文信息**：
   ```csharp
   // ✗ 不好
   logger.Error("错误");

   // ✓ 好
   logger.Error("加载场景失败: SceneKey={0}, Path={1}", sceneKey, scenePath);
   ```

6. **记录异常时提供上下文**：
   ```csharp
   try
   {
       LoadScene(sceneKey);
   }
   catch (Exception ex)
   {
       logger.Error($"加载场景失败: {sceneKey}", ex);
   }
   ```

7. **使用分类日志记录器**：
   ```csharp
   var networkLogger = LoggerFactoryResolver.Provider.CreateLogger("Network");
   var aiLogger = LoggerFactoryResolver.Provider.CreateLogger("AI");
   ```

8. **在生命周期方法中记录关键事件**：
   ```csharp
   protected override void OnInit()
   {
       _logger.Info("系统初始化完成");
   }

   protected override void OnDestroy()
   {
       _logger.Info("系统已销毁");
   }
   ```

## 性能考虑

1. **日志缓存**：
    - `GodotLoggerFactoryProvider` 使用 `CachedLoggerFactory` 缓存日志记录器实例
    - 相同名称和级别的日志记录器会被复用

2. **级别检查**：
    - 日志方法会自动检查日志级别
    - 低于最小级别的日志不会被处理

3. **字符串格式化**：
    - 使用参数化日志避免不必要的字符串拼接
   ```csharp
   // ✗ 不好 - 总是执行字符串拼接
   logger.Debug("位置: " + position.ToString());

   // ✓ 好 - 只在 Debug 启用时格式化
   logger.Debug("位置: {0}", position);
   ```

4. **条件日志**：
    - 对于耗时的数据计算，先检查日志级别
   ```csharp
   if (logger.IsDebugEnabled())
   {
       var stats = CalculateComplexStats();
       logger.Debug("统计: {0}", stats);
   }
   ```

## 常见问题

### 问题：如何配置 Godot 日志系统？

**解答**：
在架构构造函数中配置日志提供程序：

```csharp
public GameArchitecture()
{
    LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
    {
        MinLevel = LogLevel.Debug
    };
}
```

### 问题：日志没有输出到 Godot 控制台？

**解答**：
检查以下几点：

1. 确认已配置 `GodotLoggerFactoryProvider`
2. 检查日志级别是否低于最小级别
3. 确认使用了正确的日志记录器

```csharp
// 确认配置
LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
{
    MinLevel = LogLevel.Trace  // 设置为最低级别测试
};

// 创建日志记录器
var logger = LoggerFactoryResolver.Provider.CreateLogger("Test");
logger.Info("测试日志");  // 应该能看到输出
```

### 问题：如何在不同环境使用不同的日志级别？

**解答**：
使用条件编译或环境检测：

```csharp
public GameArchitecture()
{
    var minLevel = OS.IsDebugBuild() ? LogLevel.Debug : LogLevel.Info;

    LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
    {
        MinLevel = minLevel
    };
}
```

### 问题：如何禁用某个模块的日志？

**解答**：
为该模块创建一个高级别的日志记录器：

```csharp
// 只记录 Error 及以上级别
var logger = new GodotLogger("VerboseModule", LogLevel.Error);
```

### 问题：日志输出影响性能怎么办？

**解答**：

1. 提高最小日志级别
2. 使用条件日志
3. 避免在高频调用的方法中记录日志

```csharp
// 提高日志级别
LoggerFactoryResolver.Provider = new GodotLoggerFactoryProvider
{
    MinLevel = LogLevel.Warning  // 只记录警告及以上
};

// 使用条件日志
if (_logger.IsDebugEnabled())
{
    _logger.Debug("高频数据: {0}", data);
}

// 避免在 _Process 中频繁记录
public override void _Process(double delta)
{
    // ✗ 不好 - 每帧都记录
    // _logger.Debug("帧更新");

    // ✓ 好 - 只在特定条件下记录
    if (someErrorCondition)
    {
        _logger.Error("检测到错误");
    }
}
```

### 问题：如何记录结构化日志？

**解答**：
使用参数化日志或 `IStructuredLogger` 接口：

```csharp
// 参数化日志
logger.Info("玩家登录: UserId={0}, UserName={1}, Level={2}",
    userId, userName, level);

// 使用结构化日志（如果实现了 IStructuredLogger）
if (logger is IStructuredLogger structuredLogger)
{
    structuredLogger.Log(LogLevel.Info, "玩家登录",
        ("UserId", userId),
        ("UserName", userName),
        ("Level", level));
}
```

## 相关文档

- [核心日志系统](/zh-CN/core/logging) - GFramework 核心日志功能
- [Godot 架构集成](/zh-CN/godot/architecture) - Godot 架构系统
- [Godot 扩展](/zh-CN/godot/extensions) - Godot 扩展方法
- [最佳实践](/zh-CN/best-practices/architecture-patterns) - 架构最佳实践
