日志管理基础:选择合适的日志库
在Debian系统上管理Node.js日志,首先需要选择适合的日志库。常用库包括:
npm install winston
配置文件(logger.js)示例:
const { createLogger, format, transports } = require('winston');
const logger = createLogger({
level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug', // 根据环境调整日志级别
format: format.combine(
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // 添加时间戳
format.json() // 结构化日志(便于后续分析)
),
transports: [
new transports.File({ filename: 'logs/error.log', level: 'error' }), // 错误日志单独存储
new transports.File({ filename: 'logs/combined.log' }) // 所有日志合并存储
]
});
// 开发环境输出到控制台
if (process.env.NODE_ENV !== 'production') {
logger.add(new transports.Console({
format: format.simple() // 控制台输出简化格式
}));
}
module.exports = logger;
在应用中使用:
const logger = require('./logger');
logger.info('Server started on port 3000');
logger.error('Database connection failed:', { error: err.message });
日志轮转:防止日志文件过大
日志文件长期积累会导致磁盘空间占用过高,需通过轮转压缩旧日志。Debian系统推荐使用logrotate(系统自带工具)或winston-daily-rotate-file(Winston扩展)。
安装logrotate:
sudo apt update && sudo apt install logrotate
创建Node.js专用配置文件(/etc/logrotate.d/nodejs):
/var/log/nodejs/*.log { # 监控的日志路径(需与Node.js应用日志路径一致)
daily # 每天轮转一次
missingok # 日志文件不存在时不报错
rotate 7 # 保留最近7个轮转文件
compress # 压缩旧日志(节省空间)
delaycompress # 延迟压缩(避免立即压缩导致资源占用)
notifempty # 日志为空时不轮转
create 640 root adm # 新日志文件的权限和所有者
sharedscripts # 所有日志轮转完成后执行脚本
postrotate
# 可选:通知应用重新打开日志文件(如使用PM2需替换为pm2 reload)
systemctl restart your-node-app.service
endscript
}
测试配置是否正确:
sudo logrotate -f /etc/logrotate.d/nodejs
安装扩展:
npm install winston-daily-rotate-file
修改Winston配置(logger.js):
const DailyRotateFile = require('winston-daily-rotate-file');
const logger = createLogger({
// ...其他配置
transports: [
new DailyRotateFile({
filename: 'logs/application-%DATE%.log', // 轮转文件名(%DATE%为日期占位符)
datePattern: 'YYYY-MM-DD', // 日期格式
zippedArchive: true, // 压缩旧日志
maxSize: '20m', // 单个日志文件最大大小
maxFiles: '14d' // 保留最近14天的日志
}),
new transports.Console()
]
});
进程管理与日志集成:pm2
pm2是Node.js常用的进程管理工具,可自动重启应用、监控资源,并提供日志管理功能。
sudo npm install pm2 -g # 全局安装pm2
pm2 start app.js --name my-app # 启动应用并命名
pm2 logs my-app
pm2 logs my-app --lines 100 # 查看最后100行
通过pm2内置的日志轮转功能限制日志大小和保留数量:
pm2 set pm2:log-date-format "YYYY-MM-DD HH:mm Z" # 设置日志时间格式
pm2 set pm2:merge-logs true # 合并stdout和stderr
pm2 set pm2:max-size 10M # 单个日志文件最大10MB
pm2 set pm2:retain 7 # 保留最近7天的日志
若需将pm2日志集成到系统日志(/var/log/syslog),可修改pm2配置(ecosystem.config.js):
module.exports = {
apps: [{
name: 'my-app',
script: 'app.js',
log_date_format: 'YYYY-MM-DD HH:mm Z',
merge_logs: true,
out_file: '/var/log/nodejs/my-app.log', // 输出到系统日志目录
error_file: '/var/log/nodejs/my-app-error.log',
env: {
NODE_ENV: 'production'
}
}]
};
重启pm2使配置生效:
pm2 restart my-app
系统日志集成:syslog/journald
将Node.js日志发送到系统日志(syslog/journald),便于统一管理。
安装扩展:
npm install winston-syslog
修改Winston配置(logger.js):
const SyslogTransport = require('winston-syslog').SyslogTransport;
const logger = createLogger({
// ...其他配置
transports: [
new SyslogTransport({
host: 'localhost', // syslog服务器地址(本地则为localhost)
port: 514, // syslog默认端口
protocol: 'udp4', // 传输协议(udp/tcp)
app_name: 'my-node-app', // 应用名称(syslog中标识)
facility: 'local0' // 设施类型(如local0-local7)
})
]
});
配置rsyslog(/etc/rsyslog.d/50-nodejs.conf):
if $programname == 'my-node-app' then /var/log/nodejs/my-app.log # 将my-node-app日志写入指定文件
& stop # 停止继续处理(避免重复写入)
重启rsyslog:
sudo systemctl restart rsyslog
若应用作为systemd服务运行,可通过systemd-cat将日志发送到journald:
const { exec } = require('child_process');
// 记录info日志
exec('systemd-cat -t my-app -p info "Server started on port 3000"', (error, stdout, stderr) => {
if (error) console.error(`Error sending to journald: ${error.message}`);
});
// 记录error日志
exec('systemd-cat -t my-app -p err "Database connection failed"', (error, stdout, stderr) => {
if (error) console.error(`Error sending to journald: ${error.message}`);
});
查看journald日志:
journalctl -t my-app -f # 实时查看my-app日志
journalctl -u my-app.service # 查看应用对应的systemd服务日志
高级:第三方日志服务
对于需要集中管理、实时分析的场景,可将日志发送到第三方服务(如ELK Stack、Graylog、Sentry)。
logstash.conf):input {
file {
path => "/var/log/nodejs/*.log"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
json {
source => "message"
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "nodejs-logs-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
nodejs-logs-*索引,即可查看和分析日志。安装Sentry SDK:
npm install @sentry/node @sentry/tracing
初始化Sentry(app.js):
const Sentry = require('@sentry/node');
const Tracing = require('@sentry/tracing');
Sentry.init({
dsn: 'YOUR_SENTRY_DSN', // 替换为你的Sentry DSN
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0 // 采样率(1.0表示100%采样)
});
// 捕获未处理的异常
process.on('uncaughtException', (err) => {
Sentry.captureException(err);
process.exit(1);
});
// 捕获未处理的Promise rejection
process.on('unhandledRejection', (reason, promise) => {
Sentry.captureException(reason);
});
错误日志将自动上传到Sentry,可在Sentry控制台查看详情并设置报警。