ui/lib/shared/addon/mixins/metrics.js

434 lines
9.4 KiB
JavaScript

import Mixin from '@ember/object/mixin';
import { get, set, setProperties } from '@ember/object';
import { inject as service } from '@ember/service';
const SINGLE_METRICS = ['etcd-leader-change', 'etcd-server-leader-sum', 'etcd-server-failed-proposal', 'ingresscontroller-upstream-response-seconds'];
const GRAPHS = {
'apiserver-request-count': {
'priority': 301,
'unit': 'number'
},
'apiserver-request-latency': {
'priority': 300,
'unit': 'ms'
},
'cluster-cpu-load': {
'priority': 101,
'unit': 'number'
},
'cluster-cpu-usage': {
'priority': 100,
'unit': 'percent'
},
'cluster-disk-io': {
'priority': 104,
'unit': 'bps'
},
'cluster-fs-usage-percent': {
'priority': 103,
'unit': 'percent'
},
'cluster-memory-usage': {
'priority': 102,
'unit': 'percent'
},
'cluster-network-io': {
'priority': 106,
'unit': 'bps'
},
'cluster-network-packet': {
'priority': 105,
'unit': 'pps'
},
'controllermanager-queue-depth': {
'priority': 310,
'unit': 'number'
},
'etcd-db-bytes-sum': {
'priority': 204,
'unit': 'byte'
},
'etcd-disk-operate': {
'priority': 209,
'unit': 'seconds'
},
'etcd-grpc-client': {
'priority': 203,
'unit': 'bps'
},
'etcd-leader-change': {
'priority': 202,
'unit': 'number'
},
'etcd-peer-traffic': {
'priority': 206,
'unit': 'bps'
},
'etcd-raft-proposals': {
'priority': 207,
'unit': 'number'
},
'etcd-rpc-rate': {
'priority': 208,
'unit': 'ops'
},
'etcd-server-failed-proposal': {
'priority': 201,
'unit': 'number'
},
'etcd-server-leader-sum': {
'priority': 200,
'unit': 'number'
},
'etcd-stream': {
'priority': 205,
'unit': 'number'
},
'etcd-sync-duration': {
'priority': 210,
'unit': 'seconds'
},
'fluentd-buffer-queue-length': {
'priority': 300,
'unit': 'number'
},
'fluentd-input-record-number': {
'priority': 301,
'unit': 'number'
},
'fluentd-output-errors': {
'priority': 302,
'unit': 'number'
},
'fluentd-output-record-number': {
'priority': 303,
'unit': 'number'
},
'ingresscontroller-nginx-connection': {
'priority': 330,
'unit': 'number'
},
'ingresscontroller-request-process-time': {
'priority': 331,
'unit': 'seconds'
},
'ingresscontroller-upstream-response-seconds': {
'priority': 332,
'unit': 'seconds'
},
'node-cpu-load': {
'priority': 501,
'unit': 'number'
},
'node-cpu-usage': {
'priority': 500,
'unit': 'percent'
},
'node-disk-io': {
'priority': 504,
'unit': 'bps'
},
'node-fs-usage-percent': {
'priority': 503,
'unit': 'percent'
},
'node-memory-usage': {
'priority': 502,
'unit': 'percent'
},
'node-network-io': {
'priority': 506,
'unit': 'bps'
},
'node-network-packet': {
'priority': 505,
'unit': 'pps'
},
'scheduler-e-2-e-scheduling-latency-seconds-quantile': {
'priority': 320,
'unit': 'seconds'
},
'scheduler-pod-unscheduler': {
'priority': 322,
'unit': 'number'
},
'scheduler-total-preemption-attempts': {
'priority': 321,
'unit': 'number'
},
'container-cpu-usage': {
'priority': 800,
'unit': 'mcpu'
},
'container-disk-io': {
'priority': 804,
'unit': 'bps'
},
'container-memory-usage-bytes-sum': {
'priority': 801,
'unit': 'byte'
},
'container-network-io': {
'priority': 803,
'unit': 'bps'
},
'container-network-packet': {
'priority': 802,
'unit': 'pps'
},
'pod-cpu-usage': {
'priority': 700,
'unit': 'mcpu'
},
'pod-disk-io': {
'priority': 704,
'unit': 'bps'
},
'pod-memory-usage-bytes-sum': {
'priority': 701,
'unit': 'byte'
},
'pod-network-io': {
'priority': 703,
'unit': 'bps'
},
'pod-network-packet': {
'priority': 702,
'unit': 'pps'
},
'workload-cpu-usage': {
'priority': 600,
'unit': 'mcpu'
},
'workload-disk-io': {
'priority': 604,
'unit': 'bps'
},
'workload-memory-usage-bytes-sum': {
'priority': 601,
'unit': 'byte'
},
'workload-network-io': {
'priority': 603,
'unit': 'bps'
},
'workload-network-packet': {
'priority': 602,
'unit': 'pps'
},
'istio-global-request-volume': {
'priority': 1001,
'unit': 'ops'
},
'istio-global-success-rate': {
'priority': 1002,
'unit': 'percent'
},
'istio-4xxs': {
'priority': 1003,
'unit': 'number'
},
'istio-5xxs': {
'priority': 1004,
'unit': 'number'
},
'istio-global-request-volume-top10': {
'priority': 1005,
'unit': 'ops'
},
'istio-4xxs-top10': {
'priority': 1006,
'unit': 'number'
},
'istio-5xxs-top10': {
'priority': 1007,
'unit': 'number'
},
'istio-request-duration-p99-top10': {
'priority': 1008,
'unit': 'seconds'
},
'istio-request-duration-p90-top10': {
'priority': 1009,
'unit': 'seconds'
},
'istio-request-duration-p50-top10': {
'priority': 1010,
'unit': 'seconds'
},
}
export default Mixin.create({
globalStore: service(),
scope: service(),
growl: service(),
filters: null,
graphs: null,
state: null,
projectScope: false,
metricParams: null,
timeOutAnchor: null,
largeScale: false,
istio: false,
init() {
this._super(...arguments);
set(this, 'state', {
loading: false,
detail: !get(this, 'largeScale'),
noGraphs: false,
isCustom: false,
from: null,
to: null,
interval: null,
})
},
willDestroyElement() {
this.clearTimeOut();
this._super();
},
updateData(out) {
const single = [];
const graphs = [];
out.sortBy('graph.priority').forEach((item) => {
if ( SINGLE_METRICS.indexOf(get(item, 'graph.title')) > -1 ) {
single.push(item);
} else if ((get(item, 'series') || []).find((serie) => get(serie, 'points.length') > 1)){
graphs.push(item);
}
})
setProperties(this, {
'state.noGraphs': get(graphs, 'length') === 0,
graphs,
single
});
if ( !get(this, 'state.isCustom') ) {
const interval = get(this, 'state.interval');
let timeout = parseInt(interval.substr(0, get(interval, 'length') - 1), 10);
if ( get(this, 'istio') ) {
timeout = timeout * 5;
}
timeout = timeout > 5 ? timeout : 5;
const timeOutAnchor = setTimeout(() => {
this.send('query', false);
}, timeout * 1000);
set(this, 'timeOutAnchor', timeOutAnchor);
}
},
clearTimeOut() {
const timeOutAnchor = get(this, 'timeOutAnchor');
if (timeOutAnchor){
clearTimeout(timeOutAnchor);
set(this, 'timeOutAnchor', timeOutAnchor);
}
},
actions: {
query(showLoading = true){
this.clearTimeOut();
const gs = get(this, 'globalStore');
if ( showLoading ) {
set(this, 'state.loading', true);
}
let metricParams = {};
if ( get(this, 'resourceId') ) {
if ( get(this, 'metricParams') ) {
metricParams = get(this, 'metricParams');
} else {
set(metricParams, 'instance', get(this, 'resourceId'));
}
}
let url;
if ( get(this, 'projectScope') ) {
url = '/v3/projectmonitorgraphs?action=query';
} else {
url = '/v3/clustermonitorgraphs?action=query';
}
const filters = get(this, 'filters') || {};
const cluster = get(this, 'scope.currentCluster.id');
const project = get(this, 'scope.currentProject.id');
if ( project ) {
set(filters, 'projectId', project);
} else if (cluster) {
set(filters, 'clusterId', cluster);
}
gs.rawRequest({
url,
method: 'POST',
data: {
filters,
metricParams,
interval: get(this, 'state.interval'),
isDetails: get(this, 'state.detail'),
from: get(this, 'state.from'),
to: get(this, 'state.to'),
}
}).then((metrics) => {
if (this.isDestroyed || this.isDestroying) {
return;
}
const metricsBody = get(JSON.parse(get(metrics, 'body')) || {}, 'data') || [];
const out = metricsBody.map((metric) => {
const title = get(metric, 'graphID').split(':')[1];
const graph = GRAPHS[title];
if ( graph ) {
set(graph, 'title', title);
}
return {
graph,
series: (get(metric, 'series') || []).sortBy('name')
}
})
this.updateData(out);
}).catch((err) => {
if (this.isDestroyed || this.isDestroying) {
return;
}
setProperties(this, {
'state.noGraphs': true,
graphs: [],
single: []
});
if ( get(this, 'scope.currentCluster.isMonitoringReady') ) {
get(this, 'growl').fromError(get(err, 'body.message') || get(err, 'message') || err);
}
}).finally(() => {
if (this.isDestroyed || this.isDestroying) {
return;
}
if ( showLoading ) {
set(this, 'state.loading', false);
}
});
}
}
});