0

我想为我的服务提供插件,该插件将测量对 redis 的每次调用并发送带有响应时间的指标。

我该如何包装 ioredis 来做到这一点?

我想使用代理,但它只适用于异步(承诺)方法。

 let handler = {
    get: (target, name, receiver) => {

      const startTime = Date.now();

      return (...args) => new Promise((resolve, reject) => {
        const apiMethod = Reflect.get(target, name, receiver);
        const boundApiMethod = apiMethod.bind(target);

        boundApiMethod(...args).then((data) => {
          const duration = Date.now() - startTime;
          metric({duration});
          resolve(data)
        }, (err) => {
          rawMetering.reportError(err);
         reject(err);
        });
      });
    }
  };

  return new Proxy(redis, handler);
4

1 回答 1

0

我们最近面临一个非常相似的需求,我们最终做的是创建一个代理类ioredis,如下所示:

class RedisClient {
    constructor() {
        this.initClient(); // init your ioredis here
    }

    @MeasureTime()
    async get(key) {
        return this._ioredis.get(key);
    }
   // other methods like set here
}

如您所见,我们定义了一个装饰器 MeasureTime,它实际上只是一个包装调用并执行测量的高阶函数:

function MeasureTime = () => (target, _propertyKey, descriptor) => {
   
    const originalMethod = descriptor.value;
    
    descriptor.value = async function (...args) {
        const start = moment.now();
        const result = await originalMethod.apply(this, args);
        const duration = moment.now() - start;
        // do something with the duration here
        return result;
    };
    return descriptor;
}
于 2020-07-01T16:55:24.650 回答