Logger - 日志记录
日志记录是调试程序的重要手段,EasyBot 提供了简单的日志记录功能,该接口是对 Serilog 的简单封装。
logger 命名空间
info()
记录信息级别日志。
语法:
logger.info(message: string): voidlogger.info(message: string, ...args: any[]): void
参数:
message- 日志消息或格式化字符串args- 格式化参数(可选)
示例:
// 简单信息日志
logger.info("插件已启动");
// 带格式化参数的日志
logger.info("用户 {0} 发送了消息: {1}", "张三", "Hello World");
// 使用变量
const userName = "李四";
const messageCount = 5;
logger.info("用户 {0} 今天发送了 {1} 条消息", userName, messageCount);
warning()
记录警告级别日志。
语法:
logger.warning(message: string): voidlogger.warning(message: string, ...args: any[]): void
参数:
message- 日志消息或格式化字符串args- 格式化参数(可选)
示例:
// 简单警告日志
logger.warning("配置文件缺少某些选项,使用默认值");
// 带格式化参数的警告
logger.warning("用户 {0} 尝试执行未授权操作: {1}", "恶意用户", "删除文件");
// 性能警告
const responseTime = 5000;
logger.warning("API响应时间过长: {0}ms", responseTime);
error()
记录错误级别日志。
语法:
logger.error(message: string): voidlogger.error(message: string, ...args: any[]): void
参数:
message- 日志消息或格式化字符串args- 格式化参数(可选)
示例:
// 简单错误日志
logger.error("数据库连接失败");
// 带格式化参数的错误
logger.error("处理用户 {0} 的请求时发生错误: {1}", "user123", "网络超时");
// 异常处理中的错误日志
try {
// 一些可能出错的操作
const result = await someAsyncOperation();
} catch (error) {
logger.error("操作失败: {0}", error.message);
}
日志级别说明
Info(信息)
- 用途: 记录程序正常运行的信息
- 场景: 启动消息、用户操作、状态变更等
- 颜色: 通常为白色或蓝色
Warning(警告)
- 用途: 记录可能的问题或异常情况
- 场景: 配置问题、性能警告、用户权限不足等
- 颜色: 通常为黄色
Error(错误)
- 用途: 记录严重错误和异常
- 场景: 系统错误、网络故障、数据处理失败等
- 颜色: 通常为红色
格式化字符串
EasyBot 的日志系统支持 .NET 风格的字符串格式化:
// 使用 {0}, {1}, {2} 等占位符
logger.info("用户 {0} 在群 {1} 中发送了 {2} 条消息", userName, groupId, count);
// 占位符按参数顺序对应
logger.warning("操作 {0} 耗时 {1}ms,超过阈值 {2}ms", operation, time, threshold);
实用示例
插件生命周期日志
// 插件启动
logger.info("EasyBot插件 v1.0.0 正在启动...");
// 配置加载
logger.info("正在加载配置文件: {0}", configPath);
// 初始化完成
logger.info("插件初始化完成,监听 {0} 个事件", eventCount);
// 插件停止
logger.info("插件正在停止...");
用户操作日志
bus.on("group_message_event", (event) => {
logger.info("群 {0} 中用户 {1} 发送消息: {2}",
event.PeerId,
event.SenderName,
event.RawMessage
);
if (event.RawMessage.startsWith("/")) {
logger.info("用户 {0} 执行命令: {1}", event.SenderName, event.RawMessage);
}
});
错误处理日志
bus.on("group_message_event", async (event) => {
try {
if (event.RawMessage === "/weather") {
const weather = await getWeatherData();
logger.info("成功获取天气数据");
event.Context.Reply(new MessageChain().Text(weather));
}
} catch (error) {
logger.error("获取天气数据失败: {0}", error.message);
event.Context.Reply(new MessageChain().Text("天气服务暂时不可用"));
}
});
性能监控日志
async function processUserRequest(userId, request) {
const startTime = Date.now();
logger.info("开始处理用户 {0} 的请求: {1}", userId, request);
try {
const result = await handleRequest(request);
const duration = Date.now() - startTime;
if (duration > 1000) {
logger.warning("请求处理耗时过长: {0}ms", duration);
} else {
logger.info("请求处理完成,耗时: {0}ms", duration);
}
return result;
} catch (error) {
const duration = Date.now() - startTime;
logger.error("请求处理失败,耗时: {0}ms,错误: {1}", duration, error.message);
throw error;
}
}
数据库操作日志
// 数据查询
async function getUserData(userId) {
logger.info("查询用户数据: {0}", userId);
try {
const userData = await db.GetPlayerByUuid(userId);
if (userData) {
logger.info("成功获取用户 {0} 的数据", userId);
} else {
logger.warning("用户 {0} 的数据不存在", userId);
}
return userData;
} catch (error) {
logger.error("查询用户 {0} 数据失败: {1}", userId, error.message);
throw error;
}
}
// 数据更新
async function updateUserScore(userId, newScore) {
logger.info("更新用户 {0} 积分: {1}", userId, newScore);
try {
await db.UpdatePlayer(userId, { score: newScore });
logger.info("用户 {0} 积分更新成功", userId);
} catch (error) {
logger.error("更新用户 {0} 积分失败: {1}", userId, error.message);
throw error;
}
}
定时任务日志
// 定期清理任务
setInterval(() => {
logger.info("开始执行定期清理任务");
try {
const cleanedCount = cleanupExpiredData();
logger.info("清理任务完成,清理了 {0} 条过期数据", cleanedCount);
} catch (error) {
logger.error("清理任务执行失败: {0}", error.message);
}
}, 3600000); // 每小时执行一次
网络请求日志
async function fetchApiData(url) {
logger.info("发起API请求: {0}", url);
try {
const response = await network.get(url);
logger.info("API请求成功,状态码: {0}", response.status);
return response.data;
} catch (error) {
logger.error("API请求失败: {0},错误: {1}", url, error.message);
throw error;
}
}
最佳实践
1. 合理使用日志级别
// ✅ 正确使用
logger.info("用户登录成功"); // 正常信息
logger.warning("配置项缺失,使用默认值"); // 潜在问题
logger.error("数据库连接失败"); // 严重错误
// ❌ 错误使用
logger.error("用户发送了消息"); // 这不是错误
logger.info("系统崩溃"); // 这应该是错误
2. 提供足够的上下文信息
// ✅ 好的日志
logger.error("用户 {0} 在群 {1} 中执行命令 {2} 失败: {3}",
userId, groupId, command, error.message);
// ❌ 不好的日志
logger.error("命令执行失败");