debian

Debian Node.js 日志中的第三方库调用分析

小樊
44
2025-11-20 18:55:57
栏目: 编程语言

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 }));

0
看了该问题的人还看了