Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all articles
Browse latest Browse all 14821

koa-yield-breakpoint——koa@1请求打点工具

$
0
0

这几天写了个 koa-yield-breakpoint模块,这个玩意主要是在 yield 表达式前后打点,主要用在 koa@1 的 routes 或 controllers 文件,用来记录每个 yield 表达式前后的现场及 yield 表达式的返回值。

特点:可以记录每个请求的流程(甚至可以查到某个用户某个时间段的请求),及每一次请求的每一步的现场及返回值,当然只针对 yield 表达式。

实现原理:

  1. 重载 Module.prototype._compile,hack 了 require
  2. 用 esprima 解析代码,生成 AST
  3. 遍历找到 YieldExpression,进行以下包装后生成 AST 替换掉原来的节点:
global.logger(
  this,
  function*(){
    return YieldExpression
  },
  YieldExpressionString,
  filename
);
  1. 用 escodegen 生成代码(支持 soucemap,所以错误栈对应的行数是对的)

有两点需要说明:

  1. 每个请求到来时,生成一个 requestId{uuid} 挂载到 this 上
  2. global.logger 记录请求的日志

如 example:

app.js

'use strict';

const koaYieldBreakpoint = require('koa-yield-breakpoint')({
  files: ['./routes/*.js'],
  // store: new require('koa-yield-breakpoint-mongodb')({
  //   url: 'mongodb://localhost:27017/test',
  //   coll: 'koa-yield-breakpoint-loggers'
  // })
});

const koa = require('koa');
const routes = require('./routes');
const app = koa();

app.use(koaYieldBreakpoint);

routes(app);

app.listen(3000, () => {
  console.log('listening on 3000');
});

routes/index.js

'use strict';

const route = require('koa-route');
const users = require('./users');

module.exports = function (app) {
  app.use(route.get('/users', users.getUsers));
};

routes/users.js

'use strict';

const Mongolass = require('mongolass');
const mongolass = new Mongolass();
mongolass.connect('mongodb://localhost:27017/test');

exports.getUsers = function* getUsers() {
  yield mongolass.model('users').create({
    name: 'xx',
    age: 18
  });

  const users = yield mongolass.model('users').find();
  this.body = users;
};

打点之后的代码:

'use strict';
const Mongolass = require('mongolass');
const mongolass = new Mongolass();
mongolass.connect('mongodb://localhost:27017/test');
exports.getUsers = function* getUsers() {
  yield global.logger(this, function* () {
    return mongolass.model('users').create({
      name: 'xx',
      age: 18
    });
  }, 'mongolass.model(\'users\').create({\n    name: \'xx\',\n    age: 18\n})', '/Users/nswbmw/node/koa-yield-breakpoint/example/routes/users.js:8:2');
  const users = yield global.logger(this, function* () {
    return mongolass.model('users').find();
  }, 'mongolass.model(\'users\').find()', '/Users/nswbmw/node/koa-yield-breakpoint/example/routes/users.js:13:16');
  this.body = users;
};

访问 localhost:3000/users,控制台打印出:

{ requestId: 'dad593c0-c4a1-4640-a00e-9ba0349cfd2f',
  timestamp: Wed Oct 26 2016 18:28:49 GMT+0800 (CST),
  this:
   { state: {},
     request:
      { method: 'GET',
        path: '/users',
        header: [Object],
        query: [Object] },
     response: { status: 404, body: undefined } },
  type: 'start',
  step: 1 }
{ requestId: 'dad593c0-c4a1-4640-a00e-9ba0349cfd2f',
  step: 2,
  filename: '/Users/nswbmw/node/koa-yield-breakpoint/example/routes/users.js:8:2',
  timestamp: Wed Oct 26 2016 18:28:49 GMT+0800 (CST),
  this:
   { state: {},
     request:
      { method: 'GET',
        path: '/users',
        header: [Object],
        query: [Object] },
     response: { status: 404, body: undefined } },
  type: 'before',
  fn: 'mongolass.model(\'users\').create({\n    name: \'xx\',\n    age: 18\n})',
  result: undefined,
  take: '1ms' }
{ requestId: 'dad593c0-c4a1-4640-a00e-9ba0349cfd2f',
  step: 3,
  filename: '/Users/nswbmw/node/koa-yield-breakpoint/example/routes/users.js:8:2',
  timestamp: Wed Oct 26 2016 18:28:49 GMT+0800 (CST),
  this:
   { state: {},
     request:
      { method: 'GET',
        path: '/users',
        header: [Object],
        query: [Object] },
     response: { status: 404, body: undefined } },
  type: 'after',
  fn: 'mongolass.model(\'users\').create({\n    name: \'xx\',\n    age: 18\n})',
  result:
   { result: { ok: 1, n: 1 },
     ops: [ [Object] ],
     insertedCount: 1,
     insertedIds: [ undefined, 5810856182d0eea2f12030fd ] },
  take: '7ms' }
{ requestId: 'dad593c0-c4a1-4640-a00e-9ba0349cfd2f',
  step: 4,
  filename: '/Users/nswbmw/node/koa-yield-breakpoint/example/routes/users.js:13:16',
  timestamp: Wed Oct 26 2016 18:28:49 GMT+0800 (CST),
  this:
   { state: {},
     request:
      { method: 'GET',
        path: '/users',
        header: [Object],
        query: [Object] },
     response: { status: 404, body: undefined } },
  type: 'before',
  fn: 'mongolass.model(\'users\').find()',
  result: undefined,
  take: '1ms' }
{ requestId: 'dad593c0-c4a1-4640-a00e-9ba0349cfd2f',
  step: 5,
  filename: '/Users/nswbmw/node/koa-yield-breakpoint/example/routes/users.js:13:16',
  timestamp: Wed Oct 26 2016 18:28:49 GMT+0800 (CST),
  this:
   { state: {},
     request:
      { method: 'GET',
        path: '/users',
        header: [Object],
        query: [Object] },
     response: { status: 404, body: undefined } },
  type: 'after',
  fn: 'mongolass.model(\'users\').find()',
  result: [ { _id: 5810856182d0eea2f12030fd, name: 'xx', age: 18 } ],
  take: '4ms' }
{ requestId: 'dad593c0-c4a1-4640-a00e-9ba0349cfd2f',
  timestamp: Wed Oct 26 2016 18:28:49 GMT+0800 (CST),
  this:
   { state: {},
     request:
      { method: 'GET',
        path: '/users',
        header: [Object],
        query: [Object] },
     response: { status: 200, body: [Object] } },
  type: 'end',
  step: 6,
  take: '1ms' }

GitHub传送门


Viewing all articles
Browse latest Browse all 14821

Trending Articles