profile.js 6.64 KB
// http://www.daterangepicker.com/#usage

const Router = require('koa-router');
const SqlBuilder = require('../utils/sql-builder');
const request = require('superagent');
const _ = require('lodash');
const alasql = require('alasql');
const config = require('../../../config/config');

const endpoint = (server) => `http://${server.host}:${server.port}`;

const r = new Router;

const TABLE = {
    DURATION: 'web-client-duration',
    REPORT: 'error-report',
    SERVER: 'web-server-duration'
};

const DB_NAME = 'web-apm';

const APP_NAME = {
    pc: 'yohobuy-node',
    h5: 'yohobuywap-node'
};

const profile_sql = {
    duration() {
        return SqlBuilder.of(TABLE.DURATION);
    },
    error() {
        return SqlBuilder.of(TABLE.REPORT);
    }
};

async function exec(server, sql) {
    console.log('influx query from ', `[${server}] `, 'sql =>' ,sql);
    return request.get(`${server}/query`)
        .query({
            q: sql,
            db: DB_NAME
        }).then(({body: result}) => {
            return result;
        }).catch((err) => {
            console.log(err);
            return {};
        });
}

const APP = {
    default: {field: '', op: '', value: ''},
    pc: {field: 'app', op:'=',  value: APP_NAME.pc},
    h5: {field: 'app', op: '=', value: APP_NAME.h5}
};

const SERVER = {
    aws: endpoint(config.apm.aws),
    qcloud: endpoint(config.apm.qcloud)
};


function handleZip(items) {
    const col = _.get(items, 'columns', []);
    const values = _.get(items, "values", []);

    return values.map((v) => {
        return _.zipObject(col, v)
    });
}

function handleRows(rows) {
    let result = alasql('SELECT route, AVG(duration) as mean FROM ? GROUP BY route,type', [rows]);
    result = alasql('SELECT route, SUM(mean) as mean FROM ? GROUP BY route', [result]);
    return result;
}

function handleCount(rows) {
    let result = alasql('SELECT route, COUNT(route) as times FROM ? GROUP BY route', [rows]);
    return result;
}

const profile_service = {
    async mean(server, start, end, app, lastTime) {
        const model = profile_sql.duration()
            .select('*')
            .where(APP[app]);

        if (lastTime) {
            model.where('time', '>=', SqlBuilder.raw(`now() - ${lastTime}`))
        }

        if (start && end) {
            model.where('time', '>=', start)
                .where('time', '<', end);
        }

        let rows = await exec(SERVER[server],model.toSql())
                .then(result => _.get(result, 'results[0].series[0]', []))
                .then(handleZip);

        rows = handleRows(rows);

        return {code: 200, data: rows}
    },
    async count(server, start, end, app, lastTime) {
        const model = profile_sql.duration()
            .select('*')
            .where(APP[app]);

        if (lastTime) {
            model.where('time', '>=', SqlBuilder.raw(`now() - ${lastTime}`))
        }

        if (start && end) {
            model.where('time', '>=', start)
                .where('time', '<', end);
        }

        let rows = await exec(SERVER[server],model.toSql())
            .then(result => _.get(result, 'results[0].series[0]', []))
            .then(handleZip);

        rows = handleCount(rows);

        return {code: 200, data: rows}
    },
    async time(server, start, end, app, lastTime) {
        const model = profile_sql.duration()
            .select('*')
            .where(APP[app]);

        if (lastTime) {
            model.where('time', '>=', SqlBuilder.raw(`now() - ${lastTime}`))
        }

        if (start && end) {
            model.where('time', '>=', start)
                .where('time', '<', end);
        }

        const rows = await exec(SERVER[server], model.toSql())
            .then(result => _.get(result, 'results[0].series[0]', []))
            .then(handleZip);

        return {cde: 200, data: rows};
    },
    async error(server, start, end, app, lastTime) {
        const model = profile_sql.error()
            .select('*')
            .where(APP[app]);

        if (lastTime) {
            model.where('time', '>=', SqlBuilder.raw(`now() - ${lastTime}`))
        }

        if (start && end) {
            model.where('time', '>=', start)
                .where('time', '<', end);
        }

        const rows = await exec(SERVER[server], model.toSql())
            .then(result => _.get(result, 'results[0].series[0]', []))
            .then(handleZip);

        return {cde: 200, data: rows};
    }
};

const profile_controller = {
    async mean_report_index(ctx) {
        await ctx.render('action/profile_mean');
    },
    async mean_report_json(ctx) {
        const start = ctx.query.start;
        const end = ctx.query.end;
        const app = ctx.query.app;
        const server = ctx.query.server || 'aws';
        const lastTime = ctx.query.lastTime;

        const result = await profile_service.mean(server, start, end, app, lastTime);
        ctx.body = result;
    },
    async count_report_index(ctx) {
        await ctx.render('action/profile_count');
    },
    async count_report_json(ctx) {
        const start = ctx.query.start;
        const end = ctx.query.end;
        const app = ctx.query.app;
        const server = ctx.query.server || 'aws';
        const lastTime = ctx.query.lastTime;

        const result = await profile_service.count(server, start, end, app, lastTime);
        ctx.body = result;
    },
    async time_report_index(ctx) {
        await ctx.render('action/profile_time');
    },
    async time_report_json(ctx) {
        const start = ctx.query.start;
        const end = ctx.query.end;
        const app = ctx.query.app;
        const server = ctx.query.server || 'aws';
        const lastTime = ctx.query.lastTime;

        const result = await profile_service.time(server, start, end, app, lastTime);
        ctx.body = result;
    },
    async error_report_index(ctx) {
        await ctx.render('action/profile_error');
    },
    async error_report_json(ctx) {
        const start = ctx.query.start;
        const end = ctx.query.end;
        const app = ctx.query.app;
        const server = ctx.query.server || 'aws';
        const lastTime = ctx.query.lastTime;

        const result = await profile_service.error(server, start, end, app, lastTime);
        ctx.body = result;
    }

};

r.get('/mean', profile_controller.mean_report_index);
r.get('/mean.json', profile_controller.mean_report_json);

r.get('/count', profile_controller.count_report_index);
r.get('/count.json', profile_controller.count_report_json);

r.get('/time', profile_controller.time_report_index);
r.get('/time.json', profile_controller.time_report_json);

r.get('/error', profile_controller.error_report_index);
r.get('/error.json', profile_controller.error_report_json);

module.exports = r;