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); } }); } } });