serverapm-service.js 3.24 KB
const Sender = require('influx-batch-sender');
const MysqlSender = require('../lib/mysql-sender');
const config = require('../common/config');
const msg2row = require('./msg2row');
const cache = global.yoho.cache.master;

const logger = global.yoho.logger;
const errorSqlSender = new MysqlSender(config.table.error);
const slowRouterSqlSender = new MysqlSender(config.table.slow);

const routeInfluxSender = new Sender(config.reportRoute);
const apiInfluxSender = new Sender(config.reportApi);
const _ = require('lodash');

const API_BLACK_LIST = [
  'app.shop.banner'
];

async function handleWebServerDuration(m) {
  let duration = _.parseInt(m.fields.duration);

  if (duration > config.slowRoute.min / 10 && duration < config.slowRoute.max) {
    const newData = _.merge({}, m, {
      fields: {
        duration
      }
    });

    slowRouterSqlSender.addMessage(msg2row.slowRouter(newData));
  }

  if (m.tags.type.toLowerCase() === 'api') {
    if (_.includes(API_BLACK_LIST, m.tags.api)) {
      return;
    }

    logger.debug('[api] route info [%s]', JSON.stringify(m));

    apiInfluxSender.addMessage({
      tags: {
        app: m.tags.app,
        host: m.tags.hostname,
        api: m.tags.api
      },
      fields: {
                duration,
        times: 1
      }
    });
  }

  if (m.tags.type.toLowerCase() === 'route') {
    logger.debug('[server] route info [%s]', JSON.stringify(m));

    routeInfluxSender.addMessage({
      tags: {
        app: m.tags.app,
        host: m.tags.hostname,
        route: m.tags.route,
        ajax: m.fields.ajax
      },
      fields: {
                duration
      }
    });
    try {
      const degradeKey = `${m.tags.app}:degradessr`;
      const data = await cache.getAsync(degradeKey);

      if (data) {
          const list = JSON.parse(data || '[]');

          _.forEach(list, async item => {
            const key = `${degradeKey}:${item.time}`;
            const result = await cache.getAsync(key);

            if (!result) {
              cache.setAsync(key, 1, item.time);
            } else {
              cache.incrAsync(key, 1);
            }
          });
      }
    } catch (error) {
      logger.error('[server] route info degradeKey [%s]', error.message);
    }
  }
}

function handleErrorReport(m) {
  routeInfluxSender.addMessage({
    measurement: 'error-info',
    tags: {
      app: m.tags.app,
      host: m.tags.hostname,
      route: m.tags.route,
      code: m.tags.code
    },
    fields: {
      times: 1
    }
  });

  // 排除情况
  const msg = _.get(m, 'fields.message', '');

  if (!msg) {
    return;
  }

  if (msg === '""') {
    return;
  }

  const type = _.get(m, 'tags.type', '');

  if (type === 'api') {
    logger.debug('[api] error info [%s]', JSON.stringify(m));
  } else {
    logger.debug('[server] error info [%s]', JSON.stringify(m));
  }

  errorSqlSender.addMessage(msg2row.errorRouter(m));
}

function handleProcessInfo(m) {
  logger.debug('[process] info [%s]', JSON.stringify(m));

  m.measurement = 'process-info';

  _.set(m, 'fields.memory', _.parseInt(_.get(m, 'fields.memory', '0')));
  _.set(m, 'fields.cpu', _.parseInt(_.get(m, 'fields.cpu', '0')));

  routeInfluxSender.addMessage(m);
}

module.exports = {
  handleErrorReport,
  handleProcessInfo,
  handleWebServerDuration
};