Authored by 周奇琪

Merge branch 'feature/report' into 'master'

Feature/report



See merge request !9
... ... @@ -4,6 +4,7 @@ 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}`;
... ... @@ -11,7 +12,7 @@ const endpoint = (server) => `http://${server.host}:${server.port}`;
const r = new Router;
const TABLE = {
DURATION: 'web-duration',
DURATION: 'web-client-duration',
REPORT: 'error-report'
};
... ... @@ -38,13 +39,10 @@ async function exec(server, sql) {
q: sql,
db: DB_NAME
}).then(({body: result}) => {
const series = _.get(result, 'results[0].series[0]', {});
const col = _.get(series, 'columns', []);
const values = _.get(series, "values", []);
return values.map(v => {
return _.zipObject(col, v);
})
return result;
}).catch((err) => {
console.log(err);
return {};
});
}
... ... @@ -54,44 +52,146 @@ const APP = {
h5: {field: 'app', op: '=', value: APP_NAME.h5}
};
const DURATION = {
0: {field: '', op: '', value: ''},
1: {field: 'duration', op: '<=', value: 100},
2: {field: '', op: '', value: '"duration">100 and "duration"<=200'},
3: {field: 'duration', op: '>', value: 200},
};
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 time(server, start, end, app, duration) {
async mean(server, start, end, app, lastTime) {
const model = profile_sql.duration()
.select('*')
.where(DURATION[duration])
.where(APP[app])
.where('time', '>=', start)
.where('time', '<', end);
.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);
const rows = await exec(SERVER[server],model.toSql());
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}`))
}
async error(server, start, end, app) {
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])
.where('time', '>=', start)
.where('time', '<', end);
.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);
const rows = await exec(SERVER[server], model.toSql());
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.time(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');
},
... ... @@ -99,10 +199,10 @@ const profile_controller = {
const start = ctx.query.start;
const end = ctx.query.end;
const app = ctx.query.app;
const duration = ctx.query.duration;
const server = ctx.query.server || 'aws';
const lastTime = ctx.query.lastTime;
const result = await profile_service.time(server, start, end, app, duration);
const result = await profile_service.time(server, start, end, app, lastTime);
ctx.body = result;
},
async error_report_index(ctx) {
... ... @@ -113,15 +213,23 @@ const profile_controller = {
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);
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);
... ...
... ... @@ -9,6 +9,7 @@ class SqlBuilder {
this._limit = null;
this._offset = null;
this._orderBy = null;
this._groupBy = null;
}
static of(table) {
... ... @@ -43,6 +44,10 @@ class SqlBuilder {
}
}
timeWhere(value) {
}
orWhere(field, op, value) {
this._orWhere.push({field, op, value});
return this;
... ... @@ -73,6 +78,19 @@ class SqlBuilder {
return this.toString();
}
groupBy(field) {
this._groupBy = field;
return this;
}
static raw(str) {
return {
toString() {
return str;
}
}
}
toString() {
let sql = `SELECT ${this._select.join(',')} FROM "${this._from}" `;
... ... @@ -93,12 +111,16 @@ class SqlBuilder {
sql += `AND (${orWhere}) `;
} else {
if (orWhere) {
sql += `WHERE ${orWhere}`
sql += `WHERE ${orWhere}`;
}
}
if (this._orderBy) {
sql += `ORDER BY time ${this._orderBy.order} `
sql += `ORDER BY time ${this._orderBy.order} `;
}
if (this._groupBy) {
sql += `GROUP BY ` + this._groupBy.map(f => `"${f}"`).join(',')
}
if (!_.isNil(this._limit)) {
... ...
<div class="pageheader">
<div class="media">
<div class="pageicon pull-left">
<i class="fa fa-th-list"></i>
</div>
<div class="media-body">
<ul class="breadcrumb">
<li><a href=""><i class="glyphicon glyphicon-home"></i></a></li>
<li><a href="">性能监控</a></li>
<li>调用次数统计</li>
</ul>
<h4>调用次数统计</h4>
</div>
</div>
<!-- media -->
</div>
<!-- pageheader -->
<div class="contentpanel page-servers">
<div class="panel panel-primary-head">
<div class="panel-heading" style="overflow: hidden">
<div class="pull-left">
<select id="selectedServer" class="selectpicker show-menu-arrow form-control" style="margin-left: 10px;">
<option value="aws" selected>aws</option>
<option value="qcloud">qcloud</option>
</select>
</div>
<div id="reportrange" class="pull-left"
style="display: inline-block; background: #fff; cursor: pointer; padding: 9px 10px; border: 1px solid #ccc; width: 250px; color: black; margin-left: 20px;">
<i class="glyphicon glyphicon-calendar fa fa-calendar"></i>&nbsp;
<span></span> <b class="caret"></b>
</div>
<div class="pull-left">
<select id="selectedApp" class="selectpicker show-menu-arrow form-control" style="margin-left: 10px;">
<option value="default">全部</option>
<option value="pc">PC</option>
<option value="h5">H5</option>
</select>
</div>
<div class="pull-left">
<button id="search" class="btn btn-info" style="margin-left: 20px;">查询</button>
</div>
</div>
<!-- panel-heading -->
<table id="table-servers" class="table table-striped table-bordered">
<thead class="">
<tr>
<td >接口名称</td>
<td >次数</td>
</thead>
<tbody>
</tbody>
</table>
</div>
<!-- panel -->
</div>
<script>
var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime;
var data_end_point = '/profile/count.json';
var dataTable = null;
function ajaxUrl() {
let url = `${data_end_point}?app=${selectedApp}&server=${selectedServer}`;
if (selectedEndTime && selectedEndTime) {
url += `&start=${selectedStarTime}&end=${selectedEndTime}`;
}
if (lastTime) {
url += `&lastTime=${lastTime}`
}
return url
}
$(function() {
init();
initTable();
initDatePicker();
initSelect();
});
function init() {
selectedServer = 'aws';
selectedApp = 'default';
}
function initTable() {
dataTable = $("#table-servers").DataTable({
pageLength: 20,
retrieve: true,
searching: true,
dataSrc: 'data',
pageLength: 25,
columns: [
{data: 'route'},
{data: 'times'}
],
data: [{
route: '',
times: ''
}],
order: [[ 1, "desc" ]]
});
}
const TIME = {
'最近1分钟': '1m',
'最近30分钟': '30m',
'最近1小时': '1h',
'最近3小时': '3h',
'最近6小时': '6h',
'最近12小时': '12h'
};
function initDatePicker() {
var start = selectedStarTime;
var end = selectedEndTime;
var first = '最近1分钟';
$('#reportrange span').html(first);
lastTime = TIME[first];
function cb(start, end, label) {
if (label && label !== '自定义日期') {
$('#reportrange span').html(label);
lastTime = TIME[label];
} else if (label && label === '自定义日期'){
$('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD'));
selectedStarTime = start.format('YYYY-MM-DD');
selectedEndTime = end.format('YYYY-MM-DD');
lastTime = null
}
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
timePicker: true,
timePicker24Hour: true,
dateLimit: {
days: 7
},
ranges: {
'最近1分钟': [moment().subtract(1, 'minutes'), moment()],
'最近30分钟': [moment().subtract(30, 'minutes'), moment()],
'最近1小时': [moment().subtract(1, 'hours'), moment()],
'最近3小时': [moment().subtract(3, 'hours'), moment()],
'最近6小时': [moment().subtract(6, 'hours'), moment()],
'最近12小时': [moment().subtract(12, 'hours'), moment()]
},
locale: {
format: "YYYY-MM-DD",
applyLabel: '确定',
cancelLabel: '取消',
weekLabel: 'W',
customRangeLabel: '自定义日期',
daysOfWeek: '一_二_三_四_五_六_日'.split('_'),
monthNames: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
firstDay: 1
},
}, cb);
cb(start, end);
}
function initSelect() {
$('#selectedServer').change(function() {
selectedServer = $('#selectedServer').val();
});
$('#selectedApp').change(function() {
selectedApp = $('#selectedApp').val();
});
$('#search').on('click', () => {
_handleChanged();
})
}
function _handleChanged() {
dataTable && dataTable.ajax.url(ajaxUrl()).load();
}
</script>
\ No newline at end of file
... ...
... ... @@ -21,7 +21,8 @@
<div class="panel-heading" style="overflow: hidden">
<div class="pull-left">
<select id="selectedServer" class="selectpicker show-menu-arrow form-control" style="margin-left: 10px;">
<select id="selectedServer" class="selectpicker show-menu-arrow form-control"
style="margin-left: 10px;">
<option value="aws" selected>aws</option>
<option value="qcloud">qcloud</option>
</select>
... ... @@ -40,6 +41,10 @@
<option value="h5">H5</option>
</select>
</div>
<div class="pull-left">
<button id="search" class="btn btn-info" style="margin-left: 20px;">查询</button>
</div>
</div>
<!-- panel-heading -->
... ... @@ -70,22 +75,22 @@
<script>
var selectedServer, selectedStarTime, selectedEndTime, selectedApp;
var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime;
var data_end_point = '/profile/error.json';
var dataTable = null;
var handleChanged = skipOnce(_handleChanged);
function ajaxUrl() {
return `${data_end_point}?start=${selectedStarTime.format('YYYY-MM-DD')}&end=${selectedEndTime.format('YYYY-MM-DD')}&app=${selectedApp}&server=${selectedServer}`
}
let url = `${data_end_point}?app=${selectedApp}&server=${selectedServer}`;
function skipOnce(fn) {
var count = 0;
if (selectedEndTime && selectedEndTime) {
url += `&start=${selectedStarTime}&end=${selectedEndTime}`;
}
return function() {
if (count++ >= 1) fn.apply(null, arguments);
return null
if (lastTime) {
url += `&lastTime=${lastTime}`
}
return url
}
$(function() {
... ... @@ -97,8 +102,6 @@
function init() {
selectedServer = 'aws';
selectedStarTime = moment();
selectedEndTime = moment().add(1, 'days');
selectedApp = 'default';
}
... ... @@ -113,61 +116,91 @@
pageLength: 25,
deferLoading: 0,
columns: [
{ data: 'time' },
{ data: 'app' },
{ data: 'type' },
{ data: 'reqID' },
{ data: 'uid' },
{ data: 'udid' },
{ data: 'code' },
{ data: 'message' },
{ data: 'script' },
{ data: 'line' },
{ data: 'column' },
{ data: 'stack' }
{data: 'time'},
{data: 'app'},
{data: 'type'},
{data: 'reqID'},
{data: 'uid'},
{data: 'udid'},
{data: 'code'},
{data: 'message'},
{data: 'script'},
{data: 'line'},
{data: 'column'},
{data: 'stack'}
],
data: [{
time: "",
app: "",
type: "",
reqID: "",
uid: "",
udid: "",
code: "",
message: "",
script: "",
line: "",
column: "",
stack: ""
}],
columnDefs: [
{
render: function ( data, type, row ) {
render: function(data, type, row) {
return moment(data).format('YYYY/MM/DD HH:MM:ss');
},
targets: 0
}
],
order: [[ 0, "desc" ]]
order: [[0, "desc"]]
});
}
const TIME = {
'最近1分钟': '1m',
'最近30分钟': '30m',
'最近1小时': '1h',
'最近3小时': '3h',
'最近6小时': '6h',
'最近12小时': '12h'
};
function initDatePicker() {
var start = selectedStarTime;
var end = selectedEndTime;
var first = '最近1分钟';
$('#reportrange span').html(first);
$('#reportrange span').html('今天');
lastTime = TIME[first];
function cb(start, end, label) {
if (label !== '自定义日期') {
if (label && label !== '自定义日期') {
$('#reportrange span').html(label);
} else {
$('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD'))
lastTime = TIME[label];
} else if (label && label === '自定义日期'){
$('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD'));
selectedStarTime = start.format('YYYY-MM-DD');
selectedEndTime = end.format('YYYY-MM-DD');
lastTime = null
}
selectedStarTime = start;
selectedEndTime = end;
handleChanged();
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
timePicker: true,
timePicker24Hour: true,
dateLimit: {
days: 7
},
ranges: {
'今天': [moment(), moment().add(1, 'days')],
'昨天': [moment().subtract(1, 'days'), moment()],
'最近 7 天': [moment().subtract(6, 'days'), moment().add(1, 'days')],
'最近 30 天': [moment().subtract(29, 'days'), moment().add(1, 'days')],
'本月': [moment().startOf('month'), moment().endOf('month')],
'上个月': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
'最近1分钟': [moment().subtract(1, 'minutes'), moment()],
'最近30分钟': [moment().subtract(30, 'minutes'), moment()],
'最近1小时': [moment().subtract(1, 'hours'), moment()],
'最近3小时': [moment().subtract(3, 'hours'), moment()],
'最近6小时': [moment().subtract(6, 'hours'), moment()],
'最近12小时': [moment().subtract(12, 'hours'), moment()]
},
locale: {
format: "YYYY-MM-DD",
... ... @@ -186,14 +219,16 @@
function initSelect() {
$('#selectedServer').change(function() {
selectedApp = $('#selectedServer').val();
handleChanged();
selectedServer = $('#selectedServer').val();
});
$('#selectedApp').change(function() {
selectedApp = $('#selectedApp').val();
handleChanged();
});
$('#search').on('click', function() {
_handleChanged();
})
}
function _handleChanged() {
... ...
<div class="pageheader">
<div class="media">
<div class="pageicon pull-left">
<i class="fa fa-th-list"></i>
</div>
<div class="media-body">
<ul class="breadcrumb">
<li><a href=""><i class="glyphicon glyphicon-home"></i></a></li>
<li><a href="">性能监控</a></li>
<li>调用时间统计</li>
</ul>
<h4>调用时间统计</h4>
</div>
</div>
<!-- media -->
</div>
<!-- pageheader -->
<div class="contentpanel page-servers">
<div class="panel panel-primary-head">
<div class="panel-heading" style="overflow: hidden">
<div class="pull-left">
<select id="selectedServer" class="selectpicker show-menu-arrow form-control" style="margin-left: 10px;">
<option value="aws" selected>aws</option>
<option value="qcloud">qcloud</option>
</select>
</div>
<div id="reportrange" class="pull-left"
style="display: inline-block; background: #fff; cursor: pointer; padding: 9px 10px; border: 1px solid #ccc; width: 250px; color: black; margin-left: 20px;">
<i class="glyphicon glyphicon-calendar fa fa-calendar"></i>&nbsp;
<span></span> <b class="caret"></b>
</div>
<div class="pull-left">
<select id="selectedApp" class="selectpicker show-menu-arrow form-control" style="margin-left: 10px;">
<option value="default">全部</option>
<option value="pc">PC</option>
<option value="h5">H5</option>
</select>
</div>
<div class="pull-left">
<button id="search" class="btn btn-info" style="margin-left: 20px;">查询</button>
</div>
</div>
<!-- panel-heading -->
<table id="table-servers" class="table table-striped table-bordered">
<thead class="">
<tr>
<td >接口名称</td>
<td >耗时</td>
</thead>
<tbody>
</tbody>
</table>
</div>
<!-- panel -->
</div>
<script>
var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime;
var data_end_point = '/profile/mean.json';
var dataTable = null;
function ajaxUrl() {
let url = `${data_end_point}?app=${selectedApp}&server=${selectedServer}`;
if (selectedEndTime && selectedEndTime) {
url += `&start=${selectedStarTime}&end=${selectedEndTime}`;
}
if (lastTime) {
url += `&lastTime=${lastTime}`
}
return url
}
$(function() {
init();
initTable();
initDatePicker();
initSelect();
});
function init() {
selectedServer = 'aws';
selectedApp = 'default';
}
function initTable() {
dataTable = $("#table-servers").DataTable({
pageLength: 20,
retrieve: true,
searching: true,
dataSrc: 'data',
pageLength: 25,
columns: [
{data: 'route'},
{data: 'mean'}
],
data: [{
route: '',
mean: ''
}],
order: [[ 1, "desc" ]]
});
}
const TIME = {
'最近1分钟': '1m',
'最近30分钟': '30m',
'最近1小时': '1h',
'最近3小时': '3h',
'最近6小时': '6h',
'最近12小时': '12h'
};
function initDatePicker() {
var start = selectedStarTime;
var end = selectedEndTime;
var first = '最近1分钟';
$('#reportrange span').html(first);
lastTime = TIME[first];
function cb(start, end, label) {
if (label && label !== '自定义日期') {
$('#reportrange span').html(label);
lastTime = TIME[label];
} else if (label && label === '自定义日期'){
$('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD'));
selectedStarTime = start.format('YYYY-MM-DD');
selectedEndTime = end.format('YYYY-MM-DD');
lastTime = null
}
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
timePicker: true,
timePicker24Hour: true,
dateLimit: {
days: 7
},
ranges: {
'最近1分钟': [moment().subtract(1, 'minutes'), moment()],
'最近30分钟': [moment().subtract(30, 'minutes'), moment()],
'最近1小时': [moment().subtract(1, 'hours'), moment()],
'最近3小时': [moment().subtract(3, 'hours'), moment()],
'最近6小时': [moment().subtract(6, 'hours'), moment()],
'最近12小时': [moment().subtract(12, 'hours'), moment()]
},
locale: {
format: "YYYY-MM-DD",
applyLabel: '确定',
cancelLabel: '取消',
weekLabel: 'W',
customRangeLabel: '自定义日期',
daysOfWeek: '一_二_三_四_五_六_日'.split('_'),
monthNames: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
firstDay: 1
},
}, cb);
cb(start, end);
}
function initSelect() {
$('#selectedServer').change(function() {
selectedServer = $('#selectedServer').val();
});
$('#selectedApp').change(function() {
selectedApp = $('#selectedApp').val();
});
$('#search').on('click', () => {
_handleChanged();
})
}
function _handleChanged() {
dataTable && dataTable.ajax.url(ajaxUrl()).load();
}
</script>
\ No newline at end of file
... ...
... ... @@ -21,7 +21,8 @@
<div class="panel-heading" style="overflow: hidden">
<div class="pull-left">
<select id="selectedServer" class="selectpicker show-menu-arrow form-control" style="margin-left: 10px;">
<select id="selectedServer" class="selectpicker show-menu-arrow form-control"
style="margin-left: 10px;">
<option value="aws" selected>aws</option>
<option value="qcloud">qcloud</option>
</select>
... ... @@ -42,12 +43,7 @@
</div>
<div class="pull-left">
<select id="selectedDuration" class="selectpicker show-menu-arrow form-control" style="margin-left: 20px;">
<option value="0">全部</option>
<option value="1">小于100</option>
<option value="2">大于100小于200</option>
<option value="3">大于200</option>
</select>
<button id="search" class="btn btn-info" style="margin-left: 20px;">查询</button>
</div>
</div>
<!-- panel-heading -->
... ... @@ -63,7 +59,8 @@
<td>耗时</td>
<th>请求ID</th>
<td>用户ID</td>
<td>访客ID</td></tr>
<td>访客ID</td>
</tr>
</thead>
<tbody>
... ... @@ -75,24 +72,23 @@
<script>
var selectedServer, selectedStarTime, selectedEndTime, selectedApp, selectedDuration;
var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime;
var data_end_point = '/profile/time.json';
var dataTable = null;
var handleChanged = skipOnce(_handleChanged);
function ajaxUrl() {
return `${data_end_point}?start=${selectedStarTime.format('YYYY-MM-DD')}&end=${selectedEndTime.format('YYYY-MM-DD')}&app=${selectedApp}&duration=${selectedDuration}&server=${selectedServer}`
}
let url = `${data_end_point}?app=${selectedApp}&server=${selectedServer}`;
function skipOnce(fn) {
var count = 0;
if (selectedEndTime && selectedEndTime) {
url += `&start=${selectedStarTime}&end=${selectedEndTime}`;
}
return function() {
if (count++ >= 1) fn.apply(null, arguments);
return null
if (lastTime) {
url += `&lastTime=${lastTime}`
}
}
return url
}
$(function() {
init();
... ... @@ -106,7 +102,6 @@
selectedStarTime = moment();
selectedEndTime = moment().add(1, 'days');
selectedApp = 'default';
selectedDuration = 0;
}
function initTable() {
... ... @@ -115,7 +110,6 @@
retrieve: true,
responsive: true,
searching: true,
ajax: ajaxUrl(),
dataSrc: 'data',
pageLength: 25,
deferLoading: 0,
... ... @@ -130,48 +124,75 @@
{data: "uid"},
{data: "udid"}
],
data: [{
time: "",
app: "",
type: "",
api: "",
route: "",
duration: "",
reqID: "",
uid: "",
udid: ""
}],
columnDefs: [
{
render: function ( data, type, row ) {
render: function(data, type, row) {
return moment(data).format('YYYY/MM/DD HH:MM:ss');
},
targets: 0
}
],
order: [[ 0, "desc" ]]
order: [[0, "desc"]]
});
}
const TIME = {
'最近1分钟': '1m',
'最近30分钟': '30m',
'最近1小时': '1h',
'最近3小时': '3h',
'最近6小时': '6h',
'最近12小时': '12h'
};
function initDatePicker() {
var start = selectedStarTime;
var end = selectedEndTime;
var first = '最近1分钟';
$('#reportrange span').html(first);
$('#reportrange span').html('今天');
lastTime = TIME[first];
function cb(start, end, label) {
if (label !== '自定义日期') {
if (label && label !== '自定义日期') {
$('#reportrange span').html(label);
} else {
$('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD'))
lastTime = TIME[label];
} else if (label && label === '自定义日期') {
$('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD'));
selectedStarTime = start.format('YYYY-MM-DD');
selectedEndTime = end.format('YYYY-MM-DD');
lastTime = null
}
selectedStarTime = start;
selectedEndTime = end;
handleChanged();
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
timePicker: true,
timePicker24Hour: true,
dateLimit: {
days: 7
},
ranges: {
'今天': [moment(), moment().add(1, 'days')],
'昨天': [moment().subtract(1, 'days'), moment()],
'最近 7 天': [moment().subtract(6, 'days'), moment().add(1, 'days')],
'最近 30 天': [moment().subtract(29, 'days'), moment().add(1, 'days')],
'本月': [moment().startOf('month'), moment().endOf('month')],
'上个月': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
'最近1分钟': [moment().subtract(1, 'minutes'), moment()],
'最近30分钟': [moment().subtract(30, 'minutes'), moment()],
'最近1小时': [moment().subtract(1, 'hours'), moment()],
'最近3小时': [moment().subtract(3, 'hours'), moment()],
'最近6小时': [moment().subtract(6, 'hours'), moment()],
'最近12小时': [moment().subtract(12, 'hours'), moment()]
},
locale: {
format: "YYYY-MM-DD",
... ... @@ -191,18 +212,15 @@
function initSelect() {
$('#selectedServer').change(function() {
selectedServer = $('#selectedServer').val();
handleChanged();
});
$('#selectedApp').change(function() {
selectedApp = $('#selectedApp').val();
handleChanged();
});
$('#selectedDuration').change(function() {
selectedDuration = $('#selectedDuration').val();
handleChanged();
});
$('#search').on('click', () => {
_handleChanged();
})
}
function _handleChanged() {
... ...
... ... @@ -75,10 +75,12 @@
</ul>
</li>
<li class="parent"><a><i class="fa fa-list"></i> <span>性能分析</span></a>
<li class="parent"><a><i class="fa fa-list"></i> <span>性能统计</span></a>
<ul class="children">
<li><a href="/profile/time"> <span>耗时</span></a></li>
<li><a href="/profile/error"> <span>错误</span></a></li>
<li><a href="/profile/mean"> <span>调用时间统计</span></a></li>
<li><a href="/profile/count"> <span>调用次数统计</span></a></li>
<li><a href="/profile/time"> <span>调用时间统计</span></a></li>
<li><a href="/profile/error"> <span>错误信息统计</span></a></li>
</ul>
</li>
{{/if}}
... ...
... ... @@ -25,6 +25,7 @@
"author": "jiangfeng <jeff.jiang@yoho.cn>",
"license": "ISC",
"dependencies": {
"alasql": "^0.4.3",
"bluebird": "^3.5.0",
"co": "^4.6.0",
"co-body": "^4.2.0",
... ...
... ... @@ -29,6 +29,13 @@ adler-32@:
exit-on-epipe ""
printj ""
adler-32@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.1.0.tgz#03551a5c7f0edfbd4fc8fa12a6814978eab651c3"
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
after@0.8.1:
version "0.8.1"
resolved "http://registry.npm.taobao.org/after/download/after-0.8.1.tgz#ab5d4fb883f596816d3515f8f791c0af486dd627"
... ... @@ -53,6 +60,17 @@ ajv@^5.1.0:
json-schema-traverse "^0.3.0"
json-stable-stringify "^1.0.1"
alasql@^0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/alasql/-/alasql-0.4.3.tgz#46f2c3552be7b5c3ff1c01e5e5ae3706bbe075cb"
dependencies:
dom-storage "^2.0.1"
es6-promise "^4.0.5"
lodash "^4.17.4"
request "2.79.0"
xlsx "^0.11.5"
yargs "^5.0.0"
align-text@^0.1.1, align-text@^0.1.3:
version "0.1.4"
resolved "http://registry.npm.taobao.org/align-text/download/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
... ... @@ -362,6 +380,10 @@ camelcase@^1.0.2:
version "1.2.1"
resolved "http://registry.npm.taobao.org/camelcase/download/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
camelcase@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
... ... @@ -391,6 +413,13 @@ cfb@>=0.10.0:
dependencies:
commander ""
cfb@~0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/cfb/-/cfb-0.13.1.tgz#6506e0ab9b6846be7ef25c758932fe16f64c9c71"
dependencies:
commander "~2.11.0"
printj "~1.1.0"
chalk@^1.0.0, chalk@^1.1.1:
version "1.1.3"
resolved "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
... ... @@ -444,6 +473,14 @@ cliui@^2.1.0:
right-align "^0.1.1"
wordwrap "0.0.2"
cliui@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrap-ansi "^2.0.0"
clone@^1.0.2:
version "1.0.2"
resolved "http://registry.npm.taobao.org/clone/download/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
... ... @@ -472,6 +509,14 @@ code-point-at@^1.0.0:
version "1.1.0"
resolved "http://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
codepage@~1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/codepage/-/codepage-1.11.0.tgz#1076095b9f03b5ca04f43873fa1a627742285de2"
dependencies:
commander "~2.11.0"
exit-on-epipe "~1.0.1"
voc "~1.0.0"
codepage@~1.3.6:
version "1.3.8"
resolved "http://registry.npm.taobao.org/codepage/download/codepage-1.3.8.tgz#4f2e5d7c0975de28f88498058dcb5afcab6a5f71"
... ... @@ -513,6 +558,10 @@ commander@, commander@^2.9.0:
dependencies:
graceful-readlink ">= 1.0.0"
commander@~2.11.0:
version "2.11.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
component-bind@1.0.0:
version "1.0.0"
resolved "http://registry.npm.taobao.org/component-bind/download/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
... ... @@ -606,6 +655,13 @@ crc-32@:
exit-on-epipe ""
printj ""
crc-32@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.1.1.tgz#5d739d5e4c6e352ad8304d73223d483fe55adb8d"
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
create-error-class@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
... ... @@ -691,7 +747,7 @@ debuglog@^1.0.1:
version "1.0.1"
resolved "http://registry.npm.taobao.org/debuglog/download/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
decamelize@^1.0.0:
decamelize@^1.0.0, decamelize@^1.1.1:
version "1.2.0"
resolved "http://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
... ... @@ -755,6 +811,10 @@ digest-header@^0.0.1:
dependencies:
utility "0.1.11"
dom-storage@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/dom-storage/-/dom-storage-2.0.2.tgz#ed17cbf68abd10e0aef8182713e297c5e4b500b0"
dot-prop@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
... ... @@ -829,6 +889,12 @@ engine.io@1.7.2:
engine.io-parser "1.3.1"
ws "1.1.1"
error-ex@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
dependencies:
is-arrayish "^0.2.1"
error-inject@~1.0.0:
version "1.0.0"
resolved "http://registry.npm.taobao.org/error-inject/download/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37"
... ... @@ -878,6 +944,10 @@ es6-promise@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
es6-promise@^4.0.5:
version "4.1.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a"
es6-symbol@3, es6-symbol@^3.0.2, es6-symbol@~3.1:
version "3.1.0"
resolved "http://registry.npm.taobao.org/es6-symbol/download/es6-symbol-3.1.0.tgz#94481c655e7a7cad82eba832d97d5433496d7ffa"
... ... @@ -933,6 +1003,10 @@ exit-on-epipe@:
version "0.1.0"
resolved "http://registry.npm.taobao.org/exit-on-epipe/download/exit-on-epipe-0.1.0.tgz#aa2f0155b78b34fe60dd2b462e84637ba5ed0697"
exit-on-epipe@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
expand-brackets@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
... ... @@ -994,6 +1068,13 @@ fill-range@^2.1.0:
repeat-element "^1.1.2"
repeat-string "^1.5.2"
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
dependencies:
path-exists "^2.0.0"
pinkie-promise "^2.0.0"
for-each@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4"
... ... @@ -1063,6 +1144,12 @@ frac@0.3.1:
version "0.3.1"
resolved "http://registry.npm.taobao.org/frac/download/frac-0.3.1.tgz#577677b7fdcbe6faf7c461f1801d34137cda4354"
frac@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.0.tgz#dc437e9c6a646b60b127d82ac4902464445cc1e3"
dependencies:
voc "~1.0.0"
fresh@^0.3.0:
version "0.3.0"
resolved "http://registry.npm.taobao.org/fresh/download/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f"
... ... @@ -1192,6 +1279,10 @@ generate-object-property@^1.1.0:
dependencies:
is-property "^1.0.0"
get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
... ... @@ -1523,6 +1614,14 @@ interpret@^1.0.0:
version "1.0.1"
resolved "http://registry.npm.taobao.org/interpret/download/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c"
invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
is-binary-path@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
... ... @@ -1666,6 +1765,10 @@ is-typedarray@~1.0.0:
version "1.0.0"
resolved "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
is-utf8@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
isarray@0.0.1:
version "0.0.1"
resolved "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
... ... @@ -1913,6 +2016,12 @@ lazy-cache@^1.0.3:
version "1.0.4"
resolved "http://registry.npm.taobao.org/lazy-cache/download/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
dependencies:
invert-kv "^1.0.0"
lie@3.0.2:
version "3.0.2"
resolved "http://registry.npm.taobao.org/lie/download/lie-3.0.2.tgz#ffda21d7bba26f377cad865d3649b2fc8ce39fea"
... ... @@ -1922,6 +2031,16 @@ lie@3.0.2:
inline-process-browser "^1.0.0"
unreachable-branch-transform "^0.3.0"
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
dependencies:
graceful-fs "^4.1.2"
parse-json "^2.2.0"
pify "^2.0.0"
pinkie-promise "^2.0.0"
strip-bom "^2.0.0"
localforage@^1.3.0:
version "1.4.3"
resolved "http://registry.npm.taobao.org/localforage/download/localforage-1.4.3.tgz#a212543c39c7c76424edd12bf474c489aaca494c"
... ... @@ -1986,6 +2105,10 @@ lodash.assign@^3.0.0:
lodash._createassigner "^3.0.0"
lodash.keys "^3.0.0"
lodash.assign@^4.1.0, lodash.assign@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
lodash.clonedeep@~4.5.0:
version "4.5.0"
resolved "http://registry.npm.taobao.org/lodash.clonedeep/download/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
... ... @@ -2029,7 +2152,7 @@ lodash.without@~4.4.0:
version "4.4.0"
resolved "http://registry.npm.taobao.org/lodash.without/download/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac"
lodash@^4.11.1:
lodash@^4.11.1, lodash@^4.17.4:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
... ... @@ -2351,6 +2474,15 @@ normalize-package-data@^2.0.0, "normalize-package-data@~1.0.1 || ^2.0.0", normal
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
normalize-package-data@^2.3.2:
version "2.4.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
dependencies:
hosted-git-info "^2.1.4"
is-builtin-module "^1.0.0"
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
normalize-path@^2.0.0, normalize-path@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
... ... @@ -2573,6 +2705,12 @@ os-homedir@^1.0.0:
version "1.0.2"
resolved "http://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
os-locale@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
dependencies:
lcid "^1.0.0"
os-name@~1.0.3:
version "1.0.3"
resolved "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf"
... ... @@ -2630,6 +2768,12 @@ parse-glob@^3.0.4:
is-extglob "^1.0.0"
is-glob "^2.0.0"
parse-json@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
dependencies:
error-ex "^1.2.0"
parsejson@0.0.1:
version "0.0.1"
resolved "http://registry.npm.taobao.org/parsejson/download/parsejson-0.0.1.tgz#9b10c6c0d825ab589e685153826de0a3ba278bcc"
... ... @@ -2658,6 +2802,12 @@ path-array@^1.0.0:
dependencies:
array-index "^1.0.0"
path-exists@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
dependencies:
pinkie-promise "^2.0.0"
path-is-absolute@1.0.0:
version "1.0.0"
resolved "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.0.tgz#263dada66ab3f2fb10bf7f9d24dd8f3e570ef912"
... ... @@ -2684,6 +2834,14 @@ path-to-regexp@^1.1.1:
dependencies:
isarray "0.0.1"
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
dependencies:
graceful-fs "^4.1.2"
pify "^2.0.0"
pinkie-promise "^2.0.0"
pause-stream@0.0.11, pause-stream@~0.0.11:
version "0.0.11"
resolved "http://registry.npm.taobao.org/pause-stream/download/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
... ... @@ -2698,7 +2856,7 @@ performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
pify@^2.3.0:
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
... ... @@ -2724,6 +2882,10 @@ printj@:
version "0.1.1"
resolved "http://registry.npm.taobao.org/printj/download/printj-0.1.1.tgz#9d07ef9db9234da8659579e468bd46a7510489b0"
printj@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.0.tgz#85487b5e8f96763b0b4a253613bef9dd9b387e3c"
private@~0.1.5:
version "0.1.6"
resolved "http://registry.npm.taobao.org/private/download/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1"
... ... @@ -2865,6 +3027,21 @@ read-package-tree@~5.1.5:
read-package-json "^2.0.0"
readdir-scoped-modules "^1.0.0"
read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
dependencies:
find-up "^1.0.0"
read-pkg "^1.0.0"
read-pkg@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
dependencies:
load-json-file "^1.0.0"
normalize-package-data "^2.3.2"
path-type "^1.0.0"
read@1, read@~1.0.1, read@~1.0.7:
version "1.0.7"
resolved "http://registry.npm.taobao.org/read/download/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
... ... @@ -3053,6 +3230,31 @@ request@2, request@^2.74.0:
tough-cookie "~2.3.0"
tunnel-agent "~0.4.1"
request@2.79.0:
version "2.79.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
caseless "~0.11.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
har-validator "~2.0.6"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
qs "~6.3.0"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
tunnel-agent "~0.4.1"
uuid "^3.0.0"
request@2.x:
version "2.82.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.82.0.tgz#2ba8a92cd7ac45660ea2b10a53ae67cd247516ea"
... ... @@ -3133,6 +3335,14 @@ request@~2.75.0:
tough-cookie "~2.3.0"
tunnel-agent "~0.4.1"
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
resolve-path@^1.3.1:
version "1.3.2"
resolved "http://registry.npm.taobao.org/resolve-path/download/resolve-path-1.3.2.tgz#c20924408aff77466e819da548d7ce40a81d561f"
... ... @@ -3200,7 +3410,7 @@ semver@^5.0.3, semver@^5.3.0:
version "5.4.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
set-blocking@~2.0.0:
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "http://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
... ... @@ -3366,6 +3576,12 @@ sqlstring@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.2.0.tgz#c3135c4ea8abcd7e7ee741a4966a891d86a4f191"
ssf@~0.10.1:
version "0.10.1"
resolved "https://registry.yarnpkg.com/ssf/-/ssf-0.10.1.tgz#f23d82b63792ef56089089c1cd0c848e911cdba6"
dependencies:
frac "~1.1.0"
ssf@~0.8.1:
version "0.8.2"
resolved "http://registry.npm.taobao.org/ssf/download/ssf-0.8.2.tgz#b9d4dc6a1c1bcf76f8abfa96d7d7656fb2abecd6"
... ... @@ -3428,7 +3644,7 @@ streamsearch@~0.1.2:
version "0.1.2"
resolved "http://registry.npm.taobao.org/streamsearch/download/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
string-width@^1.0.1:
string-width@^1.0.1, string-width@^1.0.2:
version "1.0.2"
resolved "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
dependencies:
... ... @@ -3477,6 +3693,12 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
dependencies:
is-utf8 "^0.2.0"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
... ... @@ -3784,12 +4006,20 @@ voc@:
version "0.5.0"
resolved "http://registry.npm.taobao.org/voc/download/voc-0.5.0.tgz#be6ca7c76e4a57d930cc80f6b31fbd80ca86045c"
voc@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/voc/-/voc-1.0.0.tgz#5465c0ce11d0881f7d8e36d8ca587043f33a25ae"
wcwidth@^1.0.0:
version "1.0.1"
resolved "http://registry.npm.taobao.org/wcwidth/download/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
dependencies:
defaults "^1.0.3"
which-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
which@1, which@~1.2.11:
version "1.2.11"
resolved "http://registry.npm.taobao.org/which/download/which-1.2.11.tgz#c8b2eeea6b8c1659fa7c1dd4fdaabe9533dc5e8b"
... ... @@ -3824,6 +4054,10 @@ window-size@0.1.0:
version "0.1.0"
resolved "http://registry.npm.taobao.org/window-size/download/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
window-size@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
wordwrap@0.0.2:
version "0.0.2"
resolved "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
... ... @@ -3832,6 +4066,13 @@ wordwrap@~0.0.2:
version "0.0.3"
resolved "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
wrap-ansi@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrappy@1, wrappy@~1.0.2:
version "1.0.2"
resolved "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
... ... @@ -3867,6 +4108,18 @@ xdg-basedir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
xlsx@^0.11.5:
version "0.11.5"
resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.11.5.tgz#8c66cd97140be072e3dd320d12baa099689ceb74"
dependencies:
adler-32 "~1.1.0"
cfb "~0.13.1"
codepage "~1.11.0"
commander "~2.11.0"
crc-32 "~1.1.1"
exit-on-epipe "~1.0.1"
ssf "~0.10.1"
xlsx@^0.8.0:
version "0.8.0"
resolved "http://registry.npm.taobao.org/xlsx/download/xlsx-0.8.0.tgz#253ca61c9e1e14aa4b905dece4ce4757ace99d26"
... ... @@ -3887,10 +4140,40 @@ xmlhttprequest-ssl@1.5.1:
version "4.0.1"
resolved "http://registry.npm.taobao.org/xtend/download/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
y18n@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
yargs-parser@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-3.2.0.tgz#5081355d19d9d0c8c5d81ada908cb4e6d186664f"
dependencies:
camelcase "^3.0.0"
lodash.assign "^4.1.0"
yargs@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-5.0.0.tgz#3355144977d05757dbb86d6e38ec056123b3a66e"
dependencies:
cliui "^3.2.0"
decamelize "^1.1.1"
get-caller-file "^1.0.1"
lodash.assign "^4.2.0"
os-locale "^1.4.0"
read-pkg-up "^1.0.1"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^1.0.2"
which-module "^1.0.0"
window-size "^0.2.0"
y18n "^3.2.1"
yargs-parser "^3.2.0"
yargs@~3.10.0:
version "3.10.0"
resolved "http://registry.npm.taobao.org/yargs/download/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
... ...