Debian Node.js 第三方库调用分析实操指南
一 目标与总体思路
二 日志采集与增强
// logger.js
const { createLogger, format, transports } = require('winston');
const { combine, timestamp, json } = format;
const logger = createLogger({
level: 'info',
format: combine(timestamp(), json()),
transports: [
new transports.Console(),
new transports.File({ filename: 'logs/combined.log' }),
new transports.File({ filename: 'logs/error.log', level: 'error' })
]
});
module.exports = logger;
// app.js
const morgan = require('morgan');
const express = require('express');
const logger = require('./logger');
const app = express();
app.use(morgan('combined')); // 访问日志
app.use((req, res, next) => {
req.traceId = req.headers['x-request-id'] || Math.random().toString(36).slice(2, 10);
next();
});
// lib/wrap.js
const logger = require('./logger');
function wrapLibMethod(lib, methodName) {
const orig = lib[methodName];
return function (...args) {
const start = Date.now();
const argsHash = args.length ? hash(args[0])?.slice(0, 8) : '-'; // 简单摘要
return orig.apply(lib, args)
.then(res => {
logger.info('LIB_CALL', {
lib: lib.constructor?.name || 'unknown',
method: methodName, argsHash, status: 'ok', durationMs: Date.now() - start
});
return res;
})
.catch(err => {
logger.error('LIB_CALL', {
lib: lib.constructor?.name || 'unknown',
method: methodName, argsHash, status: 'error', durationMs: Date.now() - start, err: err.message
});
throw err;
});
};
}
// 简单摘要函数(生产可用更稳健实现)
function hash(s) { return require('crypto').createHash('sha1').update(String(s)).digest('hex'); }
三 运行与日志管理
sudo npm i -g pm2
pm2 start app.js --name "my-app"
pm2 logs my-app --raw # 实时查看
pm2 monit # 资源与日志概览
pm2 install pm2-sysmon # 可选:系统监控
# /etc/systemd/system/my-app.service
[Unit]
Description=My Node.js App
After=network.target
[Service]
ExecStart=/usr/bin/node /opt/myapp/app.js
Restart=always
StandardOutput=journal
StandardError=journal
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
sudo systemctl start my-app
sudo journalctl -u my-app -f
四 性能剖析与异常兜底
// 示例:高精度计时
const { performance } = require('perf_hooks');
const t0 = performance.now();
await thirdParty.someMethod();
const dt = performance.now() - t0;
logger.info('LIB_PERF', { lib: 'thirdParty', method: 'someMethod', durationMs: dt });
process.on('uncaughtException', (err) => {
logger.error('UNCAUGHT_EXCEPTION', { err: err.stack || err.message });
process.exit(1); // 或进入降级流程
});
process.on('unhandledRejection', (reason, p) => {
logger.error('UNHANDLED_REJECTION', { reason: reason?.stack || reason, promise: p });
});
五 落地检查清单与最小示例
// app.js
const express = require('express');
const morgan = require('morgan');
const logger = require('./logger');
const { wrapLibMethod } = require('./lib/wrap');
const app = express();
app.use(morgan('combined'));
app.use((req, res, next) => { req.traceId = req.headers['x-request-id'] || Math.random().toString(36).slice(2, 10); next(); });
// 假设使用的第三方 SDK
const someSdk = require('some-sdk');
someSdk.someMethod = wrapLibMethod(someSdk, 'someMethod');
app.get('/test', async (req, res) => {
try {
const data = await someSdk.someMethod({ q: 'test' });
res.json({ ok: true, data });
} catch (err) {
res.status(500).json({ ok: false, error: err.message });
}
});
app.listen(3000, () => logger.info('Server listening', { port: 3000 }));