Authored by htoooth

fix

@@ -12,7 +12,7 @@ const endpoint = (server) => `http://${server.host}:${server.port}`; @@ -12,7 +12,7 @@ const endpoint = (server) => `http://${server.host}:${server.port}`;
12 const r = new Router; 12 const r = new Router;
13 13
14 const TABLE = { 14 const TABLE = {
15 - DURATION: 'web-client-duration', 15 + CLIENT: 'web-client-duration',
16 REPORT: 'error-report', 16 REPORT: 'error-report',
17 SERVER: 'web-server-duration' 17 SERVER: 'web-server-duration'
18 }; 18 };
@@ -24,6 +24,11 @@ const APP_NAME = { @@ -24,6 +24,11 @@ const APP_NAME = {
24 h5: 'yohobuywap-node' 24 h5: 'yohobuywap-node'
25 }; 25 };
26 26
  27 +const APP_NAME2 = {
  28 + pc: 'www.yohobuy.com',
  29 + h5: 'm.yohobuy.com'
  30 +};
  31 +
27 const TYPE = { 32 const TYPE = {
28 DOMContentLoaded: 0, 33 DOMContentLoaded: 0,
29 load: 0, 34 load: 0,
@@ -31,8 +36,8 @@ const TYPE = { @@ -31,8 +36,8 @@ const TYPE = {
31 }; 36 };
32 37
33 const profile_sql = { 38 const profile_sql = {
34 - duration() {  
35 - return SqlBuilder.of(TABLE.DURATION); 39 + client() {
  40 + return SqlBuilder.of(TABLE.CLIENT);
36 }, 41 },
37 error() { 42 error() {
38 return SqlBuilder.of(TABLE.REPORT); 43 return SqlBuilder.of(TABLE.REPORT);
@@ -62,6 +67,12 @@ const APP = { @@ -62,6 +67,12 @@ const APP = {
62 h5: {field: 'app', op: '=', value: APP_NAME.h5} 67 h5: {field: 'app', op: '=', value: APP_NAME.h5}
63 }; 68 };
64 69
  70 +const APP2 = {
  71 + default: {field: '', op: '', value: ''},
  72 + pc: {field: 'app', op: '=', value: APP_NAME2.pc},
  73 + h5: {field: 'app', op: '=', value: APP_NAME2.h5}
  74 +};
  75 +
65 const SERVER = { 76 const SERVER = {
66 aws: endpoint(config.apm.aws), 77 aws: endpoint(config.apm.aws),
67 qcloud: endpoint(config.apm.qcloud) 78 qcloud: endpoint(config.apm.qcloud)
@@ -77,6 +88,14 @@ function handleZip(items) { @@ -77,6 +88,14 @@ function handleZip(items) {
77 }); 88 });
78 } 89 }
79 90
  91 +function handleZip2(item) {
  92 + const col = _.get(item, 'columns', []);
  93 + const values = _.get(item, "values[0]", []);
  94 + const tags = _.get(item, "tags", []);
  95 +
  96 + return Object.assign({}, _.zipObject(col, values), tags)
  97 +}
  98 +
80 function handleRows(rows) { 99 function handleRows(rows) {
81 let stats = rows.reduce((acc, cur) => { 100 let stats = rows.reduce((acc, cur) => {
82 _.updateWith(acc, [cur.route, cur.type, 'duration'], function(n) { 101 _.updateWith(acc, [cur.route, cur.type, 'duration'], function(n) {
@@ -126,9 +145,21 @@ function handleRows(rows) { @@ -126,9 +145,21 @@ function handleRows(rows) {
126 return result; 145 return result;
127 } 146 }
128 147
  148 +function handleApi(totalRows, apiRows) {
  149 + let totalObj = totalRows.map(handleZip2);
  150 + let apiObj = apiRows.map(handleZip2);
  151 +
  152 + totalObj.forEach(i => {
  153 + i.detail = jp.query(apiObj, `$..[?(@.route=="${i.route}")]`);
  154 + i.length = i.detail.length;
  155 + });
  156 +
  157 + return totalObj;
  158 +}
  159 +
129 const profile_service = { 160 const profile_service = {
130 - async mean(server, start, end, app, lastTime) {  
131 - const model = profile_sql.duration() 161 + async client_time(server, start, end, app, lastTime) {
  162 + const model = profile_sql.client()
132 .select('*') 163 .select('*')
133 .where(APP[app]); 164 .where(APP[app]);
134 165
@@ -149,10 +180,12 @@ const profile_service = { @@ -149,10 +180,12 @@ const profile_service = {
149 180
150 return {code: 200, data: rows} 181 return {code: 200, data: rows}
151 }, 182 },
152 - async time(server, start, end, app, lastTime) {  
153 - const model = profile_sql.duration()  
154 - .select('*')  
155 - .where(APP[app]); 183 + async server_time(server, start, end, app, lastTime) {
  184 + const model = profile_sql.server()
  185 + .select('count("duration"), mean("duration")')
  186 + .where(APP2[app])
  187 + .where('type', '=', 'route')
  188 + .groupBy(['route']);
156 189
157 if (lastTime) { 190 if (lastTime) {
158 model.where('time', '>=', SqlBuilder.raw(`now() - ${lastTime}`)) 191 model.where('time', '>=', SqlBuilder.raw(`now() - ${lastTime}`))
@@ -163,9 +196,28 @@ const profile_service = { @@ -163,9 +196,28 @@ const profile_service = {
163 .where('time', '<', end); 196 .where('time', '<', end);
164 } 197 }
165 198
166 - const rows = await exec(SERVER[server], model.toSql())  
167 - .then(result => _.get(result, 'results[0].series[0]', []))  
168 - .then(handleZip); 199 + const total = await exec(SERVER[server], model.toSql())
  200 + .then(result => _.get(result, 'results[0].series', []));
  201 +
  202 + const apiModel = profile_sql.server()
  203 + .select('count("duration"), mean("duration")')
  204 + .where(APP2[app])
  205 + .where('type', '=', 'api')
  206 + .groupBy(['route', 'api']);
  207 +
  208 + if (lastTime) {
  209 + apiModel.where('time', '>=', SqlBuilder.raw(`now() - ${lastTime}`))
  210 + }
  211 +
  212 + if (start && end) {
  213 + apiModel.where('time', '>=', start)
  214 + .where('time', '<', end);
  215 + }
  216 +
  217 + const api = await exec(SERVER[server], apiModel.toSql())
  218 + .then(result => _.get(result, 'results[0].series', []));
  219 +
  220 + const rows = handleApi(total, api);
169 221
170 return {cde: 200, data: rows}; 222 return {cde: 200, data: rows};
171 }, 223 },
@@ -192,30 +244,30 @@ const profile_service = { @@ -192,30 +244,30 @@ const profile_service = {
192 }; 244 };
193 245
194 const profile_controller = { 246 const profile_controller = {
195 - async mean_report_index(ctx) {  
196 - await ctx.render('action/profile_mean'); 247 + async client_mean_report_index(ctx) {
  248 + await ctx.render('action/profile_client');
197 }, 249 },
198 - async mean_report_json(ctx) { 250 + async client_mean_report_json(ctx) {
199 const start = ctx.query.start; 251 const start = ctx.query.start;
200 const end = ctx.query.end; 252 const end = ctx.query.end;
201 const app = ctx.query.app; 253 const app = ctx.query.app;
202 const server = ctx.query.server || 'aws'; 254 const server = ctx.query.server || 'aws';
203 const lastTime = ctx.query.lastTime; 255 const lastTime = ctx.query.lastTime;
204 256
205 - const result = await profile_service.mean(server, start, end, app, lastTime); 257 + const result = await profile_service.client_time(server, start, end, app, lastTime);
206 ctx.body = result; 258 ctx.body = result;
207 }, 259 },
208 - async time_report_index(ctx) {  
209 - await ctx.render('action/profile_time'); 260 + async server_mean_report_index(ctx) {
  261 + await ctx.render('action/profile_server');
210 }, 262 },
211 - async time_report_json(ctx) { 263 + async server_mean_report_json(ctx) {
212 const start = ctx.query.start; 264 const start = ctx.query.start;
213 const end = ctx.query.end; 265 const end = ctx.query.end;
214 const app = ctx.query.app; 266 const app = ctx.query.app;
215 const server = ctx.query.server || 'aws'; 267 const server = ctx.query.server || 'aws';
216 const lastTime = ctx.query.lastTime; 268 const lastTime = ctx.query.lastTime;
217 269
218 - const result = await profile_service.time(server, start, end, app, lastTime); 270 + const result = await profile_service.server_time(server, start, end, app, lastTime);
219 ctx.body = result; 271 ctx.body = result;
220 }, 272 },
221 async error_report_index(ctx) { 273 async error_report_index(ctx) {
@@ -234,11 +286,11 @@ const profile_controller = { @@ -234,11 +286,11 @@ const profile_controller = {
234 286
235 }; 287 };
236 288
237 -r.get('/mean', profile_controller.mean_report_index);  
238 -r.get('/mean.json', profile_controller.mean_report_json); 289 +r.get('/client', profile_controller.client_mean_report_index);
  290 +r.get('/client.json', profile_controller.client_mean_report_json);
239 291
240 -r.get('/time', profile_controller.time_report_index);  
241 -r.get('/time.json', profile_controller.time_report_json); 292 +r.get('/server', profile_controller.server_mean_report_index);
  293 +r.get('/server.json', profile_controller.server_mean_report_json);
242 294
243 r.get('/error', profile_controller.error_report_index); 295 r.get('/error', profile_controller.error_report_index);
244 r.get('/error.json', profile_controller.error_report_json); 296 r.get('/error.json', profile_controller.error_report_json);
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 <ul class="breadcrumb"> 7 <ul class="breadcrumb">
8 <li><a href=""><i class="glyphicon glyphicon-home"></i></a></li> 8 <li><a href=""><i class="glyphicon glyphicon-home"></i></a></li>
9 <li><a href="">性能监控</a></li> 9 <li><a href="">性能监控</a></li>
10 - <li>调用时间统计</li> 10 + <li>客户端调用时间统计</li>
11 </ul> 11 </ul>
12 - <h4>调用时间统计</h4> 12 + <h4>客户端调用时间统计</h4>
13 </div> 13 </div>
14 </div> 14 </div>
15 <!-- media --> 15 <!-- media -->
@@ -103,7 +103,7 @@ @@ -103,7 +103,7 @@
103 103
104 <script> 104 <script>
105 var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime; 105 var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime;
106 - var data_end_point = '/profile/mean.json'; 106 + var data_end_point = '/profile/client.json';
107 var dataTable = null, detailTable = null; 107 var dataTable = null, detailTable = null;
108 108
109 function ajaxUrl() { 109 function ajaxUrl() {
@@ -170,7 +170,7 @@ @@ -170,7 +170,7 @@
170 $('#table-servers tbody').on( 'click', 'button', function (e) { 170 $('#table-servers tbody').on( 'click', 'button', function (e) {
171 var data = dataTable.row($(this).parents('tr')).data(); 171 var data = dataTable.row($(this).parents('tr')).data();
172 172
173 - var modal = $('#myModal'), modalBody = $('#myModal .modal-body'); 173 + var modal = $('#myModal');
174 174
175 modal.on('show.bs.modal', function () { 175 modal.on('show.bs.modal', function () {
176 detailTable.clear().rows.add(data.detail).draw(); 176 detailTable.clear().rows.add(data.detail).draw();
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 <ul class="breadcrumb"> 7 <ul class="breadcrumb">
8 <li><a href=""><i class="glyphicon glyphicon-home"></i></a></li> 8 <li><a href=""><i class="glyphicon glyphicon-home"></i></a></li>
9 <li><a href="">性能监控</a></li> 9 <li><a href="">性能监控</a></li>
10 - <li>耗时分析</li> 10 + <li>服务器调用时间统计</li>
11 </ul> 11 </ul>
12 - <h4>耗时分析</h4> 12 + <h4>服务器调用时间统计</h4>
13 </div> 13 </div>
14 </div> 14 </div>
15 <!-- media --> 15 <!-- media -->
@@ -21,8 +21,7 @@ @@ -21,8 +21,7 @@
21 <div class="panel-heading" style="overflow: hidden"> 21 <div class="panel-heading" style="overflow: hidden">
22 22
23 <div class="pull-left"> 23 <div class="pull-left">
24 - <select id="selectedServer" class="selectpicker show-menu-arrow form-control"  
25 - style="margin-left: 10px;"> 24 + <select id="selectedServer" class="selectpicker show-menu-arrow form-control" style="margin-left: 10px;">
26 <option value="aws" selected>aws</option> 25 <option value="aws" selected>aws</option>
27 <option value="qcloud">qcloud</option> 26 <option value="qcloud">qcloud</option>
28 </select> 27 </select>
@@ -48,33 +47,57 @@ @@ -48,33 +47,57 @@
48 </div> 47 </div>
49 <!-- panel-heading --> 48 <!-- panel-heading -->
50 49
51 - <table id="table-servers" class="table table-striped table-bordered responsive"> 50 + <table id="table-servers" class="table table-striped table-bordered">
52 <thead class=""> 51 <thead class="">
53 <tr> 52 <tr>
54 - <th>时间</th>  
55 - <th>应用</th>  
56 - <th>类型</th>  
57 - <td>接口名称</td>  
58 - <td>请求路由</td>  
59 - <td>耗时</td>  
60 - <th>请求ID</th>  
61 - <td>用户ID</td>  
62 - <td>访客ID</td>  
63 - </tr> 53 + <td >接口名称</td>
  54 + <td >调用次数</td>
  55 + <td >耗时</td>
  56 + <td >调用接口数</td>
  57 + <td >详细情况</td>
64 </thead> 58 </thead>
65 59
66 <tbody> 60 <tbody>
67 </tbody> 61 </tbody>
68 </table> 62 </table>
69 </div> 63 </div>
  64 +
  65 +
  66 + <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  67 + <div class="modal-dialog modal-lg" role="document" style="display:table;">
  68 + <div class="modal-content">
  69 + <div class="modal-header">
  70 + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
  71 + <h4 class="modal-title" id="myModalLabel">详细信息</h4>
  72 + </div>
  73 + <div class="modal-body">
  74 + <table id="table-detail" class="table table-striped table-bordered">
  75 + <thead class="">
  76 + <tr>
  77 + <td >time</td>
  78 + <td >api</td>
  79 + <td >count</td>
  80 + <td >mean</td>
  81 + </thead>
  82 +
  83 + <tbody>
  84 + </tbody>
  85 + </table>
  86 + </div>
  87 + <div class="modal-footer">
  88 + <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
  89 + </div>
  90 + </div>
  91 + </div>
  92 + </div>
70 <!-- panel --> 93 <!-- panel -->
71 </div> 94 </div>
72 95
73 96
74 <script> 97 <script>
75 var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime; 98 var selectedServer, selectedStarTime, selectedEndTime, selectedApp, lastTime;
76 - var data_end_point = '/profile/time.json';  
77 - var dataTable = null; 99 + var data_end_point = '/profile/server.json';
  100 + var dataTable = null, detailTable = null;
78 101
79 function ajaxUrl() { 102 function ajaxUrl() {
80 let url = `${data_end_point}?app=${selectedApp}&server=${selectedServer}`; 103 let url = `${data_end_point}?app=${selectedApp}&server=${selectedServer}`;
@@ -99,8 +122,6 @@ @@ -99,8 +122,6 @@
99 122
100 function init() { 123 function init() {
101 selectedServer = 'aws'; 124 selectedServer = 'aws';
102 - selectedStarTime = moment();  
103 - selectedEndTime = moment().add(1, 'days');  
104 selectedApp = 'default'; 125 selectedApp = 'default';
105 } 126 }
106 127
@@ -108,33 +129,64 @@ @@ -108,33 +129,64 @@
108 dataTable = $("#table-servers").DataTable({ 129 dataTable = $("#table-servers").DataTable({
109 pageLength: 20, 130 pageLength: 20,
110 retrieve: true, 131 retrieve: true,
111 - responsive: true,  
112 searching: true, 132 searching: true,
113 dataSrc: 'data', 133 dataSrc: 'data',
114 pageLength: 25, 134 pageLength: 25,
115 - deferLoading: 0,  
116 columns: [ 135 columns: [
117 - {data: "time"},  
118 - {data: "app"},  
119 - {data: "type"},  
120 - {data: "api"},  
121 - {data: "route"},  
122 - {data: "duration"},  
123 - {data: "reqID"},  
124 - {data: "uid"},  
125 - {data: "udid"} 136 + {data: 'route'},
  137 + {data: 'count'},
  138 + {data: 'mean'},
  139 + {data: 'length'},
  140 + {data: 'detail'}
  141 + ],
  142 + data: [{
  143 + route: '',
  144 + count: 0,
  145 + mean: 0,
  146 + length: 0,
  147 + detail: ''
  148 + }],
  149 + order: [[ 2, "desc" ]],
  150 + columnDefs: [ {
  151 + targets: -1,
  152 + data: null,
  153 + render: function ( data, type, row ) {
  154 + return '<button data-toggle="modal" data-target="#myModal">查看</button>';
  155 + },
  156 + }]
  157 + });
  158 +
  159 + $('#table-servers tbody').on( 'click', 'button', function (e) {
  160 + var data = dataTable.row($(this).parents('tr')).data();
  161 +
  162 + var modal = $('#myModal');
  163 +
  164 + modal.on('show.bs.modal', function () {
  165 + detailTable.clear().rows.add(data.detail).draw();
  166 + });
  167 +
  168 + e.preventDefault();
  169 + });
  170 +
  171 + detailTable = $("#table-detail").DataTable({
  172 + pageLength: 20,
  173 + retrieve: true,
  174 + searching: true,
  175 + dataSrc: 'data',
  176 + pageLength: 25,
  177 + columns: [
  178 + {data: 'time'},
  179 + {data: 'api'},
  180 + {data: 'count'},
  181 + {data: 'mean'}
126 ], 182 ],
127 data: [{ 183 data: [{
128 - time: "",  
129 - app: "",  
130 - type: "",  
131 - api: "",  
132 - route: "",  
133 - duration: "",  
134 - reqID: "",  
135 - uid: "",  
136 - udid: "" 184 + time: '',
  185 + api: '',
  186 + count: '',
  187 + mean: ''
137 }], 188 }],
  189 + order: [[ 0, "desc" ]],
138 columnDefs: [ 190 columnDefs: [
139 { 191 {
140 render: function(data, type, row) { 192 render: function(data, type, row) {
@@ -143,13 +195,12 @@ @@ -143,13 +195,12 @@
143 targets: 0 195 targets: 0
144 } 196 }
145 ], 197 ],
146 - order: [[0, "desc"]]  
147 }); 198 });
148 } 199 }
149 200
150 const TIME = { 201 const TIME = {
151 '最近1分钟': '1m', 202 '最近1分钟': '1m',
152 - '最近30分钟': '30m', 203 + '最近30分钟': '30m',
153 '最近1小时': '1h', 204 '最近1小时': '1h',
154 '最近3小时': '3h', 205 '最近3小时': '3h',
155 '最近6小时': '6h', 206 '最近6小时': '6h',
@@ -169,7 +220,7 @@ @@ -169,7 +220,7 @@
169 if (label && label !== '自定义日期') { 220 if (label && label !== '自定义日期') {
170 $('#reportrange span').html(label); 221 $('#reportrange span').html(label);
171 lastTime = TIME[label]; 222 lastTime = TIME[label];
172 - } else if (label && label === '自定义日期') { 223 + } else if (label && label === '自定义日期'){
173 $('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD')); 224 $('#reportrange span').html(start.format('YYYY-MM-DD') + ' 至 ' + end.format('YYYY-MM-DD'));
174 selectedStarTime = start.format('YYYY-MM-DD'); 225 selectedStarTime = start.format('YYYY-MM-DD');
175 selectedEndTime = end.format('YYYY-MM-DD'); 226 selectedEndTime = end.format('YYYY-MM-DD');
@@ -77,8 +77,8 @@ @@ -77,8 +77,8 @@
77 77
78 <li class="parent"><a><i class="fa fa-list"></i> <span>性能统计</span></a> 78 <li class="parent"><a><i class="fa fa-list"></i> <span>性能统计</span></a>
79 <ul class="children"> 79 <ul class="children">
80 - <li><a href="/profile/mean"> <span>客户端调用时间统计</span></a></li>  
81 - <li><a href="/profile/time"> <span>调用时间统计</span></a></li> 80 + <li><a href="/profile/client"> <span>客户端调用时间统计</span></a></li>
  81 + <li><a href="/profile/server"> <span>服务器调用时间统计</span></a></li>
82 <li><a href="/profile/error"> <span>错误信息统计</span></a></li> 82 <li><a href="/profile/error"> <span>错误信息统计</span></a></li>
83 </ul> 83 </ul>
84 </li> 84 </li>