
99% 的人 vibe coding 都跳过了这一步:日志体系

你贴了 500 行代码给 AI,它还在瞎猜问题在哪。
老程序员贴 5 行日志,AI 就定位到了 Bug。
Vibe coding 的时代,大家都学会了直接把代码扔给 AI:「帮我看看这段代码哪里有问题。」
然后 AI 开始猜。是逻辑错了?是边界条件没处理?是并发问题?还是内存泄漏?
你在那贴 500 行代码,AI 消耗几千 token,最后给你一个似是而非的答案。
而老程序员的做法完全不同。
他们不会让 AI 瞎猜。他们会先做一件事:让 AI 搭一套完整的日志体系。
然后出问题时,他们贴的不是代码,是日志。
AI 看一眼日志,马上定位问题。
省 token,省时间,排查效率直接翻倍。
为什么日志体系这么重要?
问题一:代码是静态的,日志是动态的
你给 AI 看代码,它看到的是「程序长什么样」。
但你给 AI 看日志,它看到的是「程序发生了什么」。
Bug 不在于代码长什么样,而于代码执行时发生了什么。
日志记录了:
- 什么时候进入的函数
- 参数是什么
- 中间状态是什么
- 什么时候出的函数
- 出了什么错
这些动态信息,才是定位 Bug 的关键。
问题二:贴代码太贵,贴日志太便宜
你贴 500 行代码给 AI,一次就要消耗几千 token。
而且你还要贴上下文:这个函数从哪调用的、参数是什么、期望结果是什么。
一次 Bug 排查,可能要消耗几万 token。
但如果你有日志体系,你只需要贴:
[2024-05-29 10:23:45] [AuthService] [login] 开始登录,用户: user123
[2024-05-29 10:23:45] [AuthService] [validateUser] 验证用户,输入: user123
[2024-05-29 10:23:46] [DB] [query] SELECT * FROM users WHERE username = 'user123'
[2024-05-29 10:23:46] [DB] [error] 连接超时: timeout after 5000ms
[2024-05-29 10:23:46] [AuthService] [login] 登录失败: DB_ERROR5 行日志,AI 马上看出问题:数据库连接超时。
不需要看代码,不需要猜。日志已经告诉了答案。
问题三:日志是可追溯的
你给 AI 看代码,它只能看到「这一刻」的代码。
但日志记录了「整个执行流程」:
- 请求从哪进来
- 经过了哪些模块
- 每个模块做了什么
- 最后在哪出错
当你的日志足够详细,AI 不需要看代码。它通过日志就能重构整个执行路径。
一个好的日志体系长什么样?
特征一:分模块
每个模块的日志带自己的标识:
[AuthService] [login] ...
[DB] [query] ...
[PaymentService] [process] ...好处: AI 一眼就能看出日志来自哪个模块,快速定位问题范围。
特征二:分级别
不同级别用不同标识:
[INFO] [AuthService] 用户登录成功
[WARN] [AuthService] 密码错误次数过多
[ERROR] [DB] 数据库连接失败好处: AI 可以根据级别判断问题严重性,优先处理 ERROR 级别的问题。
特征三:带上下文
日志不只是「发生了什么」,还包括「什么条件下发生的」:
[INFO] [AuthService] 用户登录成功 | 用户ID: 12345 | IP: 192.168.1.100 | 耗时: 125ms
[ERROR] [DB] 查询失败 | SQL: SELECT * FROM users WHERE id = 12345 | 错误: syntax error好处: AI 能从上下文中提取关键信息,快速判断问题根源。
特征四:可追溯
日志带时间戳、带追踪 ID:
[2024-05-29 10:23:45.123] [TRACE-abc123] [AuthService] 开始登录
[2024-05-29 10:23:45.234] [TRACE-abc123] [DB] 执行查询
[2024-05-29 10:23:45.345] [TRACE-abc123] [AuthService] 登录成功好处: AI 能通过 TRACE ID 把整个请求链路的日志串联起来,看到完整执行路径。
实战:让 AI 搭建日志体系
下面是一个可以直接复用的提示词,让 AI 为你的项目搭建完整的日志体系。
提示词模板
你是一个资深后端工程师。请为以下项目搭建一个完整的日志体系。
项目信息:
- 技术栈:${YOUR_TECH_STACK}
- 项目类型:${WEB_SERVICE / CRON_JOB / LIBRARY}
- 主要模块:${YOUR_MODULES}
要求:
1. 设计日志格式
- 包含:时间戳、追踪ID、模块名、级别、消息、上下文
- 格式示例:[2024-05-29 10:23:45.123] [TRACE-id] [Module] [Level] Message | Context
2. 设计日志级别
- DEBUG:详细调试信息
- INFO:正常流程信息
- WARN:警告但不影响运行
- ERROR:错误但可恢复
- FATAL:致命错误需重启
3. 为每个模块设计关键日志点
- 模块入口:记录输入参数
- 关键步骤:记录中间状态
- 模块出口:记录输出结果
- 异常处理:记录错误信息
4. 提供代码示例
- 创建日志工具类/函数
- 展示如何在模块中使用
- 展示如何记录不同级别的日志
- 展示如何记录上下文信息
5. 设计日志配置
- 开发环境:输出 DEBUG 级别到控制台
- 生产环境:输出 INFO 级别到文件,每天滚动
- 日志路径、文件大小限制
请给出完整的代码和说明。实际案例:Node.js + Express
假设你的项目是 Node.js + Express,你可以这样问 AI:
你是一个资深后端工程师。请为以下项目搭建一个完整的日志体系。
项目信息:
- 技术栈:Node.js 18 + Express 4
- 项目类型:Web 服务
- 主要模块:AuthService(认证)、PaymentService(支付)、DB(数据库)
要求:
1. 设计日志格式
- 包含:时间戳、追踪ID、模块名、级别、消息、上下文
- 格式示例:[2024-05-29 10:23:45.123] [TRACE-id] [Module] [Level] Message | Context
2. 设计日志级别
- DEBUG:详细调试信息
- INFO:正常流程信息
- WARN:警告但不影响运行
- ERROR:错误但可恢复
- FATAL:致命错误需重启
3. 为每个模块设计关键日志点
- 模块入口:记录输入参数
- 关键步骤:记录中间状态
- 模块出口:记录输出结果
- 异常处理:记录错误信息
4. 提供代码示例
- 使用 winston 日志库
- 创建日志工具类
- 创建中间件自动生成追踪 ID
- 展示如何在 Express 路由中使用
- 展示如何记录不同级别的日志
- 展示如何记录上下文信息
5. 设计日志配置
- 开发环境:输出 DEBUG 级别到控制台,带颜色
- 生产环境:输出 INFO 级别到文件,每天滚动
- 日志路径:./logs/
- 单文件最大 10MB,保留 30 天
请给出完整的代码和说明。AI 会给你什么?
AI 会给你一套完整的日志体系,包括:
1. 日志工具类(logger.js):
const winston = require('winston');
const { format } = winston;
const logFormat = format.combine(
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
format.errors({ stack: true }),
format.json()
);
const logger = winston.createLogger({
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
format: logFormat,
transports: [
new winston.transports.File({
filename: './logs/error.log',
level: 'error',
maxsize: 10485760, // 10MB
maxFiles: 30
}),
new winston.transports.File({
filename: './logs/combined.log',
maxsize: 10485760,
maxFiles: 30
})
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: format.combine(
format.colorize(),
format.printf(({ timestamp, level, message, context }) => {
const ctxStr = context ? ` | ${JSON.stringify(context)}` : '';
return `${timestamp} [${level}]: ${message}${ctxStr}`;
})
)
}));
}
module.exports = logger;2. 追踪中间件(tracking.js):
const { v4: uuidv4 } = require('uuid');
function trackingMiddleware(req, res, next) {
req.traceId = uuidv4();
const startTime = Date.now();
res.on('finish', () => {
const duration = Date.now() - startTime;
console.log(`[${req.traceId}] ${req.method} ${req.path} - ${res.statusCode} - ${duration}ms`);
});
next();
}
module.exports = trackingMiddleware;3. 模块化日志封装(moduleLogger.js):
const logger = require('./logger');
class ModuleLogger {
constructor(moduleName) {
this.moduleName = moduleName;
}
info(message, context = {}) {
logger.info(message, { module: this.moduleName, ...context });
}
warn(message, context = {}) {
logger.warn(message, { module: this.moduleName, ...context });
}
error(message, context = {}) {
logger.error(message, { module: this.moduleName, ...context });
}
debug(message, context = {}) {
logger.debug(message, { module: this.moduleName, ...context });
}
}
module.exports = (moduleName) => new ModuleLogger(moduleName);4. 实际使用示例(authService.js):
const logger = require('./moduleLogger')('AuthService');
async function login(username, password) {
const traceId = getCurrentTraceId();
logger.info('开始登录', { username, traceId });
try {
const user = await validateUser(username);
logger.debug('用户验证完成', { userId: user.id, traceId });
const token = await generateToken(user);
logger.info('登录成功', { userId: user.id, traceId });
return { success: true, token };
} catch (error) {
logger.error('登录失败', {
username,
error: error.message,
traceId
});
return { success: false, message: error.message };
}
}5. 日志输出示例:
[2024-05-29 10:23:45.123] [INFO]: 开始登录 | {"module":"AuthService","username":"user123","traceId":"abc-123"}
[2024-05-29 10:23:45.234] [DEBUG]: 用户验证完成 | {"module":"AuthService","userId":456,"traceId":"abc-123"}
[2024-05-29 10:23:45.345] [INFO]: 登录成功 | {"module":"AuthService","userId":456,"traceId":"abc-123"}有了日志体系,怎么用 AI 排查 Bug?
场景一:性能问题
传统做法:
用户反馈:「登录很慢」
你贴代码给 AI:「帮我看看哪里慢」
AI 瞎猜:「是不是数据库查询太慢?」有日志的做法:
你贴日志给 AI:
[2024-05-29 10:23:45] [AuthService] [login] 开始登录
[2024-05-29 10:23:50] [DB] [query] 查询完成 | 耗时: 5000ms
[2024-05-29 10:23:50] [AuthService] [login] 登录成功
AI 马上回答:数据库查询耗时 5 秒,检查 SQL 和索引。场景二:并发问题
传统做法:
用户反馈:「库存扣减有问题」
你贴代码给 AI:「帮我看看并发问题」
AI 瞎猜:「是不是没加锁?」有日志的做法:
你贴日志给 AI:
[10:23:45] [OrderService] [createOrder] 创建订单 | 用户ID: 123 | 商品ID: 456 | 库存: 10
[10:23:46] [OrderService] [createOrder] 创建订单 | 用户ID: 124 | 商品ID: 456 | 库存: 10
[10:23:47] [DB] [update] 更新库存 | 商品ID: 456 | 数量: -2
[10:23:48] [DB] [update] 更新库存 | 商品ID: 456 | 数量: -2
AI 马上回答:并发请求都读到库存 10,最后都扣减,导致超卖。需要加锁或用事务。场景三:数据错误
传统做法:
用户反馈:「价格不对」
你贴代码给 AI:「帮我看看价格计算」
AI 瞎猜:「是不是浮点数精度问题?」有日志的做法:
你贴日志给 AI:
[10:23:45] [PriceService] [calculate] 计算价格 | 原价: 100 | 折扣: 0.8 | 优惠: 20
[10:23:46] [PriceService] [calculate] 最终价格 | 价格: 79.99999999999999
AI 马上回答:浮点数精度问题,用 Decimal 或 Math.round 处理。老程序员的秘密
老程序员都知道:日志不是写给别人看的,是写给未来的自己看的。
当你三个月后再来看这段代码,你忘了当时是怎么写的。
但日志会告诉你:当时发生了什么、出了什么问题、是怎么解决的。
AI 时代,日志还有一个新作用:写给 AI 看。
当你的日志足够详细、结构清晰、带上下文,AI 不需要看代码,就能理解发生了什么。
这不是老派的做法。这是 AI 时代的最佳实践。
写在最后
搭建日志体系,看似花时间,其实省时间。
你花 1 小时让 AI 搭一套完整的日志体系,之后每次排查 Bug 都能省 1 小时。
这是典型的「前期投入,后期复利」。
而且,当你的项目越来越复杂、团队越来越大,日志体系的价值会指数级增长。
因为你不是一个人在写代码。你是在和 AI、和团队一起维护一个系统。
日志是这个系统的「共同语言」。
99% 的人 vibe coding 都跳过了这一步。
但 1% 的老程序员知道:这是让 AI 和你高效协作的关键。
让 AI 先搭日志体系,然后让 AI 看日志排 Bug。
这才是 AI 时代该有的 vibe coding 方式。
