]> git.proxmox.com Git - pmg-gui.git/blame - js/Dashboard.js
collect and show errors on dashboard
[pmg-gui.git] / js / Dashboard.js
CommitLineData
ff735274 1/*global Proxmox*/
de0ebd99
DC
2/*jslint confusion: true*/
3/* load is a function and string
4 * hours is a number and string
5 * timespan is a number and string
6 * bind is a function and object
7 * handler is a function and string
8 */
5936e3ef
DC
9Ext.define('PMG.Dashboard', {
10 extend: 'Ext.panel.Panel',
11 xtype: 'pmgDashboard',
12
b047eec0
DC
13 controller: {
14 xclass: 'Ext.app.ViewController',
5936e3ef 15
b047eec0
DC
16 openDashboardOptions: function() {
17 var me = this;
18 var viewModel = me.getViewModel();
19 Ext.create('Ext.window.Window', {
20 modal: true,
21 width: 300,
22 title: gettext('Dashboard Options'),
23 layout: {
24 type: 'auto'
25 },
26 items: [{
27 xtype: 'form',
de0ebd99 28 bodyPadding: '10 10 10 10',
b047eec0
DC
29 defaultButton: 'savebutton',
30 items: [{
31 xtype: 'proxmoxintegerfield',
32 itemId: 'hours',
33 labelWidth: 100,
34 anchor: '100%',
35 allowBlank: false,
36 minValue: 1,
37 maxValue: 24,
38 value: viewModel.get('hours'),
39 fieldLabel: gettext('Hours to show')
40 }],
41 buttons: [{
42 text: gettext('Save'),
43 reference: 'loginButton',
44 formBind: true,
45 handler: function() {
46 var win = this.up('window');
47 var hours = win.down('#hours').getValue();
48 me.setHours(hours, true);
49 win.close();
50 }
51 }]
771bd0b9 52 }]
b047eec0
DC
53 }).show();
54 },
5936e3ef 55
b047eec0
DC
56 setHours: function(hours, setState) {
57 var me = this;
58 var viewModel = me.getViewModel();
59 viewModel.set('hours', hours);
60 viewModel.notify();
61
62 Ext.Array.forEach(['recentmails', 'receivers'], function(item) {
86109d3a 63 viewModel.getStore(item).reload();
b047eec0
DC
64 });
65
66 if (setState) {
67 var sp = Ext.state.Manager.getProvider();
68 sp.set('dashboard-hours', hours);
69 }
70 },
71
72 updateMailStats: function(store, records, success) {
73 if (!success) {
74 return;
75 }
76 var me = this;
77 var viewModel = me.getViewModel();
78
79 var count = 0;
80 var bytes_in = 0;
81 var bytes_out = 0;
82 var ptime = 0;
b6248f6e 83 var avg_ptime = 'N/A';
b047eec0
DC
84
85 records.forEach(function(item) {
86 bytes_in += item.data.bytes_in;
87 bytes_out += item.data.bytes_out;
b79fbba8
DC
88 // unnormalize
89 count += (item.data.count*item.data.timespan)/60;
b047eec0
DC
90 ptime += item.data.ptimesum;
91 });
92
93 if (count) {
b6248f6e 94 avg_ptime = (ptime/count).toFixed(2) + " s";
b047eec0
DC
95 }
96
97 viewModel.set('bytes_in', Proxmox.Utils.format_size(bytes_in));
98 viewModel.set('bytes_out', Proxmox.Utils.format_size(bytes_out));
b6248f6e 99 viewModel.set('avg_ptime', avg_ptime);
b047eec0
DC
100 },
101
102 updateClusterStats: function(store, records, success) {
103 if (!success) {
104 return;
105 }
106 var me = this;
107 var viewmodel = me.getViewModel();
108
109 var subStatus = 2; // 2 = all good, 1 = different leves, 0 = none
110 var subLevel = "";
111
112 var cpu = 0;
113 var mem = 0;
114 var hd = 0;
115 var count = records.length;
bb7ab2ba 116 var errors = [];
b047eec0
DC
117
118 records.forEach(function(item) {
119 // subscription level check
120 if (subStatus && item.data.level) {
121 if (subLevel !== "" && subLevel !== item.data.level) {
122 subStatus = 1;
123 } else if (subLevel === "") {
124 subLevel = item.data.level;
125 }
126 } else {
127 subStatus = 0;
128 }
129
130 // resources count
91c74e81
DC
131 cpu += item.data.cpu || 0;
132
133 var memory = item.data.memory || { used: 0, total: 1 };
134 mem += (memory.used/memory.total);
135
136 var rootfs = item.data.rootfs || { used: 0, total: 1 };
137 hd += (rootfs.used/rootfs.total);
138
bb7ab2ba
DC
139 if (item.data.conn_error && count > 1) {
140 count--;
141 errors.push({
142 name: item.data.name,
143 msg: item.data.conn_error
144 });
145 }
b047eec0
DC
146 });
147
148 var subscriptionPanel = me.lookup('subscription');
149 subscriptionPanel.setSubStatus(subStatus);
150
151 cpu = cpu/count;
152 mem = mem/count;
153 hd = hd/count;
154
155 var cpuPanel = me.lookup('cpu');
156 cpuPanel.updateValue(cpu);
157
131ba4f6 158 var memPanel = me.lookup('mem');
b047eec0
DC
159 memPanel.updateValue(mem);
160
131ba4f6 161 var hdPanel = me.lookup('hd');
b047eec0 162 hdPanel.updateValue(hd);
bb7ab2ba
DC
163
164 if (errors.length && !viewmodel.get('error_shown')) {
165 var text = "";
166 errors.forEach(function(error) {
167 text += error.name + ':<br>' + error.msg + '<br>';
168 });
169 Ext.Msg.alert(gettext('Error'), text);
170 viewmodel.set('error_shown', true);
171 }
b047eec0
DC
172 },
173
174 init: function(view) {
175 var me = this;
176 var sp = Ext.state.Manager.getProvider();
177 var hours = sp.get('dashboard-hours') || 12;
178 me.setHours(hours, false);
179 }
180 },
181
182 viewModel: {
183 data: {
184 timespan: 300, // in seconds
185 hours: 12, // in hours
bb7ab2ba 186 error_shown: false,
b047eec0
DC
187 'bytes_in': 0,
188 'bytes_out': 0,
771bd0b9 189 'avg_ptime': 0.0
b047eec0
DC
190 },
191
192 stores: {
193 cluster: {
194 storeid: 'dash-cluster',
195 type: 'update',
196 interval: 5000,
197 autoStart: true,
198 autoLoad: true,
199 autoDestroy: true,
200 proxy: {
929f40ff 201 extraParams: { list_single_node: 1 },
b047eec0
DC
202 type: 'proxmox',
203 url: '/api2/json/config/cluster/status'
204 },
205 listeners: {
206 load: 'updateClusterStats'
207 }
208 },
209 recentmails: {
210 storeid: 'dash-recent',
211 interval: 5000,
212 type: 'update',
213 autoStart: true,
214 autoLoad: true,
215 autoDestroy: true,
216 proxy: {
217 type: 'proxmox',
218 url: '/api2/json/statistics/recent',
219 extraParams: {
220 hours: '{hours}',
221 timespan: '{timespan}'
222 }
223 },
224 fields: [
b79fbba8
DC
225 {
226 type: 'number', name: 'count',
227 convert: PMG.Utils.convert_field_to_per_min
228 },
229 {
230 type: 'number', name: 'count_in',
231 convert: PMG.Utils.convert_field_to_per_min
232 },
233 {
234 type: 'number', name: 'count_out',
235 convert: PMG.Utils.convert_field_to_per_min
236 },
237 {
238 type: 'number', name: 'spam',
239 convert: PMG.Utils.convert_field_to_per_min
240 },
241 {
242 type: 'number', name: 'spam_in',
243 convert: PMG.Utils.convert_field_to_per_min
244 },
245 {
246 type: 'number', name: 'spam_out',
247 convert: PMG.Utils.convert_field_to_per_min
248 },
249 {
250 type: 'number', name: 'virus',
251 convert: PMG.Utils.convert_field_to_per_min
252 },
253 {
254 type: 'number', name: 'virus_in',
255 convert: PMG.Utils.convert_field_to_per_min
256 },
b047eec0
DC
257 { type: 'integer', name: 'virus_out' },
258 { type: 'integer', name: 'bytes_in' },
259 { type: 'integer', name: 'bytes_out' },
260 { type: 'number', name: 'ptimesum' },
261 { type: 'date', dateFormat: 'timestamp', name: 'time' }
262 ],
263 listeners: {
264 load: 'updateMailStats'
265 }
266 },
267 receivers: {
268 storeid: 'dash-receivers',
269 interval: 10000,
270 type: 'update',
271 autoStart: true,
272 autoLoad: true,
273 autoDestroy: true,
274 proxy: {
275 type: 'proxmox',
276 url: '/api2/json/statistics/recentreceivers',
277 extraParams: {
771bd0b9 278 hours: '{hours}'
b047eec0
DC
279 }
280 },
281 fields: [
282 { type: 'integer', name: 'count' },
283 { type: 'string', name: 'receiver' }
284 ]
285 }
286 }
287 },
288
289 bind: {
290 title: gettext('Dashboard') + ' (' +
291 Ext.String.format(gettext('{0} hours'), '{hours}') + ')'
292 },
293
de0ebd99
DC
294 layout: {
295 type: 'column'
296 },
b047eec0
DC
297 border: false,
298
299 bodyPadding: '20 0 0 20',
300
301 defaults: {
302 columnWidth: 0.5,
303 xtype: 'panel',
304 margin: '0 20 20 0'
305 },
306
307 tools: [
308 {
309 type: 'gear',
310 handler: 'openDashboardOptions'
311 }
312 ],
313
314 scrollable: true,
315
316 items: [
317 {
318 height: 300,
319 flex: 1,
320 iconCls: 'fa fa-tachometer',
321 title: gettext('E-Mail Volume'),
322 layout: {
323 type: 'vbox',
771bd0b9 324 align: 'stretch'
b047eec0
DC
325 },
326 defaults: {
327 xtype: 'pmgMiniGraph',
328 bind: {
329 store: '{recentmails}'
330 }
331 },
332 items: [
333 {
334 fields: ['count'],
b79fbba8 335 fieldTitles: [ gettext('Mails / min') ],
b047eec0
DC
336 seriesConfig: {
337 colors: [ '#00617F' ],
338 style: {
339 opacity: 0.60,
340 lineWidth: 1
341 },
342 highlightCfg: {
343 opacity: 1,
344 scaling: 1
771bd0b9
DC
345 }
346 }
b047eec0
DC
347 },
348 {
349 fields: ['spam'],
b79fbba8 350 fieldTitles: [ gettext('Spam / min') ],
b047eec0
DC
351 seriesConfig: {
352 colors: [ '#E67300' ],
353 style: {
354 opacity: 0.60,
355 lineWidth: 1
356 },
357 highlightCfg: {
358 opacity: 1,
359 scaling: 1
771bd0b9
DC
360 }
361 }
362 }
b047eec0
DC
363 ]
364 },
365 {
366 xtype: 'container',
367 height: 300,
368 layout: {
369 type: 'vbox',
771bd0b9 370 align: 'stretch'
b047eec0
DC
371 },
372 items: [
373 {
374 xtype: 'pmgMailProcessing',
375 title: gettext('E-Mail Processing'),
376 iconCls: 'fa fa-hourglass-half',
377 height: 180,
378 bind: {
379 data: {
7b18f75e
DC
380 'bytes_in': '{bytes_in}',
381 'bytes_out': '{bytes_out}',
382 'avg_ptime': '{avg_ptime}'
b047eec0 383 }
771bd0b9 384 }
b047eec0
DC
385 },
386 {
387 iconCls: 'fa fa-ticket',
388 title: 'Subscription',
389 reference: 'subscription',
390 xtype: 'pmgSubscriptionInfo',
391 margin: '10 0 0 0',
771bd0b9 392 height: 110
b047eec0
DC
393 }
394 ]
395 },
396 {
397 height: 250,
398 iconCls: 'fa fa-tasks',
64fb657f 399 title: gettext('Node Resources'),
b047eec0
DC
400 bodyPadding: '0 20 0 20',
401 layout: {
402 type: 'hbox',
403 align: 'center'
404 },
405 defaults: {
406 xtype: 'proxmoxGauge',
407 spriteFontSize: '20px',
408 flex: 1
409 },
410 items: [
411 {
412 title: gettext('CPU'),
413 reference: 'cpu'
414 },
415 {
416 title: gettext('Memory'),
417 reference: 'mem'
418 },
419 {
420 title: gettext('Storage'),
421 reference: 'hd'
422 }
423 ]
424 },
425 {
426 height: 250,
427 iconCls: 'fa fa-list',
428 title: gettext('Top Receivers'),
429
de0ebd99 430 bodyPadding: '20 20 20 20',
b047eec0
DC
431 layout: {
432 type: 'vbox',
433 pack: 'center',
434 align: 'stretch'
435 },
436 items: [{
437 xtype: 'grid',
438 bind: {
439 store: '{receivers}'
440 },
441
442 emptyText: gettext('No data in database'),
443
444 // remove all borders/lines/headers
445 border: false,
446 bodyBorder: false,
447 hideHeaders: true,
448 header: false,
449 columnLines: false,
450 rowLines: false,
451 viewConfig: {
771bd0b9 452 stripeRows: false
b047eec0
DC
453 },
454
455 columns: [
456 {
457 dataIndex: 'receiver',
458 flex: 1,
459 text: gettext('Receiver')
460 },
461 {
462 dataIndex: 'count',
463 align: 'right',
464 text: gettext('Count')
465 }
466 ]
467 }]
468 }
469 ]
5936e3ef 470});