各位靓仔靓女,晚上好!我是你们的老朋友,今天咱们来聊聊JavaScript应用中的日志记录和错误监控,这可是保证系统“耳聪目明”的关键所在!
想象一下,你的代码就像一辆在高速公路上狂奔的跑车。你肯定想知道:
- 它跑得怎么样?速度多少?油耗如何?
- 有没有遇到坑坑洼洼?哪个轮胎压力不足?
- 万一抛锚了,得知道在哪儿抛的,以及怎么修!
日志记录和错误监控就是这辆跑车的车载电脑和维修手册,能帮你实时掌握情况,及时发现问题,并迅速修复。
第一部分:日志记录——给你的代码安个“录音机”
日志记录,简单来说,就是在代码的关键节点,记录一些信息,方便我们事后回溯和分析。
1. console.log()?别逗了!
console.log()
确实是最简单粗暴的日志记录方式,但它只适合调试阶段。一旦上线,满屏的 console.log()
会让你的控制台变成垃圾场,而且还会影响性能。
// 别这么干!
function calculate(a, b) {
console.log("开始计算...");
console.log("a 的值是:", a);
console.log("b 的值是:", b);
let result = a + b;
console.log("结果是:", result);
return result;
}
2. 分级日志:给日志穿上“制服”
更好的做法是使用分级日志,根据信息的严重程度,给日志穿上不同的“制服”,方便筛选和处理。常见的日志级别有:
日志级别 | 描述 | 颜色(只是举例,实际应用中可能不同) |
---|---|---|
debug |
用于开发阶段的详细信息,例如变量的值、函数的调用顺序等。上线后一般关闭。 | 灰色 |
info |
一般性信息,例如系统启动、用户登录等。 | 绿色 |
warn |
警告信息,表示可能存在潜在的问题,但不影响系统正常运行。例如配置项缺失、API 调用频率过高等。 | 黄色 |
error |
错误信息,表示系统出现了问题,可能导致部分功能无法正常使用。例如数据库连接失败、API 调用返回错误等。 | 红色 |
fatal |
致命错误,表示系统出现了严重问题,无法继续运行。例如内存溢出、文件系统损坏等。 | 亮红色 |
你可以自己实现一个简单的日志记录器,或者使用现成的库,比如 winston
、log4js
等。
3. 手写一个简易日志记录器
const logLevels = {
debug: 0,
info: 1,
warn: 2,
error: 3,
fatal: 4,
};
const logLevel = logLevels.info; // 设置日志级别
function log(level, message, ...args) {
if (logLevels[level] >= logLevel) {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] [${level.toUpperCase()}] ${message}`, ...args);
}
}
const logger = {
debug: (message, ...args) => log('debug', message, ...args),
info: (message, ...args) => log('info', message, ...args),
warn: (message, ...args) => log('warn', message, ...args),
error: (message, ...args) => log('error', message, ...args),
fatal: (message, ...args) => log('fatal', message, ...args),
};
// 使用
logger.info("服务器启动...");
logger.debug("变量 x 的值是:", 10); // 这条日志不会显示,因为日志级别是 info
logger.warn("配置项 'apiKey' 缺失");
logger.error("API 调用失败");
logger.fatal("内存溢出!");
这个简易的日志记录器可以根据设置的日志级别,决定是否输出日志。上线后,你可以将日志级别设置为 warn
或 error
,只记录重要的信息,避免噪音。
4. 使用 winston 库
winston
是一个功能强大的日志记录库,支持多种输出方式,例如控制台、文件、数据库等。
首先,安装 winston
:
npm install winston
然后,使用 winston
:
const winston = require('winston');
const logger = winston.createLogger({
level: 'info', // 设置日志级别
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(({ timestamp, level, message }) => {
return `${timestamp} ${level}: ${message}`;
})
),
transports: [
new winston.transports.Console(), // 输出到控制台
new winston.transports.File({ filename: 'error.log', level: 'error' }), // 输出错误日志到文件
new winston.transports.File({ filename: 'combined.log' }), // 输出所有日志到文件
],
});
// 使用
logger.info("服务器启动...");
logger.debug("变量 x 的值是:", 10); // 这条日志不会显示,因为日志级别是 info
logger.warn("配置项 'apiKey' 缺失");
logger.error("API 调用失败");
logger.fatal("内存溢出!");
winston
提供了更多的配置选项,例如日志格式、输出目标等,可以根据实际需求进行调整。
5. 日志格式:让日志更易读
日志格式很重要,清晰的日志格式可以让你更快地找到问题。常见的日志格式包括:
- 文本格式: 简单易懂,但不利于机器解析。
- JSON 格式: 方便机器解析,适合存储到数据库或发送到日志分析平台。
winston
支持自定义日志格式,你可以根据自己的需求选择合适的格式。
6. 日志存储:把日志“存起来”
日志不能只输出到控制台,还需要存储起来,方便后续分析。常见的日志存储方式包括:
- 文件: 简单易用,但不利于大规模存储和查询。
- 数据库: 适合大规模存储和查询,但需要维护数据库。
- 日志管理平台: 提供专业的日志存储、分析和可视化功能,例如 ELK Stack(Elasticsearch、Logstash、Kibana)、Splunk 等。
选择哪种存储方式,取决于你的应用规模和预算。
第二部分:错误监控——给你的代码装个“警报器”
错误监控,就是在代码出错时,及时发出警报,让你第一时间知道问题所在。
1. try…catch:抓住“小错误”
try...catch
是最基本的错误处理方式,可以捕获代码块中发生的错误。
try {
// 可能会出错的代码
let result = 10 / 0;
console.log(result);
} catch (error) {
// 处理错误
console.error("发生错误:", error.message);
}
try...catch
只能捕获同步代码中的错误,无法捕获异步代码中的错误。
2. Promise 的 reject:处理异步错误
Promise 提供了 reject
方法,可以处理异步操作中的错误。
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 模拟 API 调用失败
reject(new Error("API 调用失败"));
}, 1000);
});
}
fetchData()
.then(data => {
console.log("数据:", data);
})
.catch(error => {
console.error("发生错误:", error.message);
});
3. window.onerror:捕获全局错误
window.onerror
可以捕获全局未处理的错误,包括语法错误、运行时错误等。
window.onerror = function(message, source, lineno, colno, error) {
console.error("全局错误:", message, source, lineno, colno, error);
// 可以将错误信息发送到服务器
return true; // 阻止浏览器默认的错误处理
};
// 故意制造一个错误
console.log(undefinedVariable.toString());
window.onerror
只能捕获未处理的错误,无法捕获 try...catch
已经处理过的错误。
4. 错误监控平台:专业的“报警器”
try...catch
、Promise.reject
和 window.onerror
只能捕获错误,但无法提供完整的错误信息,例如用户环境、堆栈信息等。
专业的错误监控平台,例如 Sentry、Bugsnag、Raygun 等,可以提供更全面的错误监控功能:
- 自动捕获错误: 自动捕获未处理的错误,无需手动编写
try...catch
。 - 提供详细的错误信息: 包括用户环境、堆栈信息、浏览器信息等。
- 错误分组和去重: 将类似的错误分组,避免重复报警。
- 实时报警: 在错误发生时,立即发送邮件、短信等通知。
- 错误分析: 提供错误趋势分析、影响用户数等统计信息。
5. 使用 Sentry 监控错误
Sentry 是一个流行的错误监控平台,提供了免费和付费版本。
首先,注册 Sentry 账号,并创建一个项目。
然后,安装 Sentry 的 JavaScript SDK:
npm install @sentry/browser @sentry/tracing
然后,初始化 Sentry:
import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
Sentry.init({
dsn: "YOUR_SENTRY_DSN", // 替换为你的 Sentry DSN
integrations: [
new Integrations.BrowserTracing(),
],
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 0.1,
release: "[email protected]", // 可选,设置版本号
environment: "production", // 可选,设置环境
});
// 故意制造一个错误
try {
console.log(undefinedVariable.toString());
} catch (error) {
Sentry.captureException(error); // 手动捕获错误
}
Sentry 会自动捕获未处理的错误,并将错误信息发送到 Sentry 平台。你也可以使用 Sentry.captureException()
手动捕获错误。
第三部分:最佳实践——让你的系统更“健康”
- 不要记录敏感信息: 例如用户密码、银行卡号等。
- 设置合适的日志级别: 上线后,将日志级别设置为
warn
或error
,避免噪音。 - 定期清理日志: 避免日志文件过大,占用磁盘空间。
- 监控关键指标: 例如 CPU 使用率、内存使用率、响应时间等。
- 设置报警阈值: 当关键指标超过阈值时,及时发出警报。
- 定期分析日志和错误信息: 找出潜在的问题,并及时修复。
- 使用 source map: 在生产环境中,使用 source map 可以将压缩后的代码还原为原始代码,方便调试。
总结:
日志记录和错误监控是保证系统可观测性的重要手段。通过合理的日志记录和错误监控,你可以及时发现问题,并迅速修复,让你的系统更加“健康”。
希望今天的讲座对大家有所帮助!祝大家的代码永远没有 Bug!(手动狗头) 谢谢大家!