Showing
4 changed files
with
175 additions
and
72 deletions
@@ -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">×</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> |
-
Please register or login to post a comment