Merge pull request #2682 from codyrancher/extra-metrics

Adding metrics to workloads, pods and nodes
This commit is contained in:
codyrancher 2021-05-12 23:46:09 -07:00 committed by GitHub
commit fe62a22bcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 163 additions and 35 deletions

View File

@ -1856,6 +1856,7 @@ node:
tab: tab:
conditions: Conditions conditions: Conditions
images: Images images: Images
metrics: Metrics
info: info:
label: Info label: Info
key: key:
@ -3492,6 +3493,7 @@ workload:
networkSettings: Network Settings networkSettings: Network Settings
podAnnotations: Pod Annotations podAnnotations: Pod Annotations
podLabels: Pod Labels podLabels: Pod Labels
metrics: Metrics
podScheduling: Pod Scheduling podScheduling: Pod Scheduling
nodeScheduling: Node Scheduling nodeScheduling: Node Scheduling
ports: Ports ports: Ports

View File

@ -14,6 +14,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
vars: {
type: Object,
default: () => ({})
},
graphHeight: { graphHeight: {
type: String, type: String,
required: true required: true
@ -55,6 +59,7 @@ export default {
:refresh-rate="graphOptions.refreshRate" :refresh-rate="graphOptions.refreshRate"
:range="graphOptions.range" :range="graphOptions.range"
:url="detailUrl" :url="detailUrl"
:vars="vars"
/> />
<GrafanaDashboard <GrafanaDashboard
v-else v-else
@ -64,6 +69,7 @@ export default {
:refresh-rate="graphOptions.refreshRate" :refresh-rate="graphOptions.refreshRate"
:range="graphOptions.range" :range="graphOptions.range"
:url="summaryUrl" :url="summaryUrl"
:vars="vars"
/> />
</div> </div>
</div> </div>

View File

@ -10,6 +10,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
vars: {
type: Object,
default: () => ({})
},
range: { range: {
type: String, type: String,
default: null default: null
@ -127,6 +131,14 @@ export default {
params.refresh = this.refreshRate; params.refresh = this.refreshRate;
} }
if (Object.keys(this.vars).length > 0) {
Object.entries(this.vars).forEach((entry) => {
const paramName = `var-${ entry[0] }`;
params[paramName] = entry[1];
});
}
params.theme = this.theme; params.theme = this.theme;
return params; return params;

View File

@ -15,7 +15,13 @@ import Poller from '@/utils/poller';
import { METRIC, POD } from '@/config/types'; import { METRIC, POD } from '@/config/types';
import createEditView from '@/mixins/create-edit-view'; import createEditView from '@/mixins/create-edit-view';
import { formatSi, exponentNeeded, UNITS } from '@/utils/units'; import { formatSi, exponentNeeded, UNITS } from '@/utils/units';
import DashboardMetrics from '@/components/DashboardMetrics';
import { mapGetters } from 'vuex';
import { allDashboardsExist } from '@/utils/grafana';
import Loading from '@/components/Loading';
const NODE_METRICS_DETAIL_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-node-detail-1/rancher-node-detail?orgId=1';
const NODE_METRICS_SUMMARY_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-node-1/rancher-node?orgId=1';
const METRICS_POLL_RATE_MS = 30000; const METRICS_POLL_RATE_MS = 30000;
const MAX_FAILURES = 2; const MAX_FAILURES = 2;
@ -25,6 +31,8 @@ export default {
components: { components: {
Alert, Alert,
ConsumptionGauge, ConsumptionGauge,
DashboardMetrics,
Loading,
ResourceTabs, ResourceTabs,
Tab, Tab,
SortableTable, SortableTable,
@ -39,8 +47,10 @@ export default {
}, },
}, },
fetch() { async fetch() {
this.$store.dispatch('cluster/findAll', { type: POD }); this.showMetrics = await allDashboardsExist(this.$store.dispatch, this.currentCluster.id, [NODE_METRICS_DETAIL_URL, NODE_METRICS_SUMMARY_URL]);
return this.$store.dispatch('cluster/findAll', { type: POD });
}, },
data() { data() {
@ -70,11 +80,15 @@ export default {
VALUE, VALUE,
EFFECT EFFECT
], ],
podTableHeaders: this.$store.getters['type-map/headersFor'](podSchema) podTableHeaders: this.$store.getters['type-map/headersFor'](podSchema),
NODE_METRICS_DETAIL_URL,
NODE_METRICS_SUMMARY_URL,
showMetrics: false
}; };
}, },
computed: { computed: {
...mapGetters(['currentCluster']),
memoryUnits() { memoryUnits() {
const exponent = exponentNeeded(this.value.ramCapacity, 1024); const exponent = exponentNeeded(this.value.ramCapacity, 1024);
@ -118,6 +132,10 @@ export default {
taintTableRows() { taintTableRows() {
return this.value.spec.taints || []; return this.value.spec.taints || [];
}, },
graphVars() {
return { instance: `${ this.value.internalIp }:9796` };
}
}, },
mounted() { mounted() {
@ -160,7 +178,8 @@ export default {
</script> </script>
<template> <template>
<div class="node"> <Loading v-if="$fetchState.pending" />
<div v-else class="node">
<div class="spacer"></div> <div class="spacer"></div>
<div class="alerts"> <div class="alerts">
<Alert class="mr-10" :status="pidPressureStatus" :message="t('node.detail.glance.pidPressure')" /> <Alert class="mr-10" :status="pidPressureStatus" :message="t('node.detail.glance.pidPressure')" />
@ -175,7 +194,7 @@ export default {
</div> </div>
<div class="spacer"></div> <div class="spacer"></div>
<ResourceTabs v-model="value" :mode="mode"> <ResourceTabs v-model="value" :mode="mode">
<Tab name="pods" :label="t('node.detail.tab.pods')" :weight="3"> <Tab name="pods" :label="t('node.detail.tab.pods')" :weight="4">
<SortableTable <SortableTable
key-field="_key" key-field="_key"
:headers="podTableHeaders" :headers="podTableHeaders"
@ -185,6 +204,17 @@ export default {
:search="false" :search="false"
/> />
</Tab> </Tab>
<Tab v-if="showMetrics" :label="t('node.detail.tab.metrics')" name="node-metrics" :weight="3">
<template #default="props">
<DashboardMetrics
v-if="props.active"
:detail-url="NODE_METRICS_DETAIL_URL"
:summary-url="NODE_METRICS_SUMMARY_URL"
:vars="graphVars"
graph-height="825px"
/>
</template>
</Tab>
<Tab name="info" :label="t('node.detail.tab.info.label')" class="bordered-table" :weight="2"> <Tab name="info" :label="t('node.detail.tab.info.label')" class="bordered-table" :weight="2">
<SortableTable <SortableTable
key-field="_key" key-field="_key"

View File

@ -6,11 +6,20 @@ import SortableTable from '@/components/SortableTable';
import { STATE, SIMPLE_NAME, IMAGE } from '@/config/table-headers'; import { STATE, SIMPLE_NAME, IMAGE } from '@/config/table-headers';
import { sortableNumericSuffix } from '@/utils/sort'; import { sortableNumericSuffix } from '@/utils/sort';
import { findBy } from '@/utils/array'; import { findBy } from '@/utils/array';
import DashboardMetrics from '@/components/DashboardMetrics';
import { mapGetters } from 'vuex';
import { allDashboardsExist } from '@/utils/grafana';
import Loading from '@/components/Loading';
const POD_METRICS_DETAIL_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-pod-containers-1/rancher-pod-containers?orgId=1';
const POD_METRICS_SUMMARY_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-pod-1/rancher-pod?orgId=1';
export default { export default {
name: 'PodDetail', name: 'PodDetail',
components: { components: {
DashboardMetrics,
Loading,
ResourceTabs, ResourceTabs,
Tab, Tab,
SortableTable, SortableTable,
@ -18,7 +27,20 @@ export default {
mixins: [CreateEditView], mixins: [CreateEditView],
async fetch() {
this.showMetrics = await allDashboardsExist(this.$store.dispatch, this.currentCluster.id, [POD_METRICS_DETAIL_URL, POD_METRICS_SUMMARY_URL]);
},
data() {
return {
POD_METRICS_DETAIL_URL,
POD_METRICS_SUMMARY_URL,
showMetrics: false
};
},
computed: { computed: {
...mapGetters(['currentCluster']),
containers() { containers() {
const { containerStatuses = [] } = this.value.status; const { containerStatuses = [] } = this.value.status;
@ -68,12 +90,21 @@ export default {
} }
]; ];
}, },
graphVars() {
return {
namespace: this.value.namespace,
pod: this.value.name
};
},
}, },
}; };
</script> </script>
<template> <template>
<ResourceTabs mode="view" class="mt-20" :value="value"> <Loading v-if="$fetchState.pending" />
<ResourceTabs v-else mode="view" class="mt-20" :value="value">
<Tab :label="t('workload.container.titles.containers')" name="containers" :weight="3"> <Tab :label="t('workload.container.titles.containers')" name="containers" :weight="3">
<SortableTable <SortableTable
:rows="containers" :rows="containers"
@ -85,5 +116,16 @@ export default {
:table-actions="false" :table-actions="false"
/> />
</Tab> </Tab>
<Tab v-if="showMetrics" :label="t('workload.container.titles.metrics')" name="pod-metrics" :weight="2.5">
<template #default="props">
<DashboardMetrics
v-if="props.active"
:detail-url="POD_METRICS_DETAIL_URL"
:summary-url="POD_METRICS_SUMMARY_URL"
:vars="graphVars"
graph-height="550px"
/>
</template>
</Tab>
</ResourceTabs> </ResourceTabs>
</template> </template>

View File

@ -9,9 +9,26 @@ import ResourceTabs from '@/components/form/ResourceTabs';
import CountGauge from '@/components/CountGauge'; import CountGauge from '@/components/CountGauge';
import { allHash } from '@/utils/promise'; import { allHash } from '@/utils/promise';
import { get } from '@/utils/object'; import { get } from '@/utils/object';
import DashboardMetrics from '@/components/DashboardMetrics';
import { mapGetters } from 'vuex';
import { allDashboardsExist } from '@/utils/grafana';
const WORKLOAD_METRICS_DETAIL_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-workload-pods-1/rancher-workload-pods?orgId=1';
const WORKLOAD_METRICS_SUMMARY_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-workload-1/rancher-workload?orgId=1';
export const WORKLOAD_TYPE_TO_KIND_MAPPING = {
[WORKLOAD_TYPES.DEPLOYMENT]: 'Deployment',
[WORKLOAD_TYPES.CRON_JOB]: 'CronJob',
[WORKLOAD_TYPES.DAEMON_SET]: 'DaemonSet',
[WORKLOAD_TYPES.JOB]: 'Job',
[WORKLOAD_TYPES.STATEFUL_SET]: 'StatefulSet',
[WORKLOAD_TYPES.REPLICA_SET]: 'ReplicaSet',
[WORKLOAD_TYPES.REPLICATION_CONTROLLER]: 'ReplicationController',
};
export default { export default {
components: { components: {
DashboardMetrics,
Tab, Tab,
Loading, Loading,
ResourceTabs, ResourceTabs,
@ -32,13 +49,18 @@ export default {
for ( const k in res ) { for ( const k in res ) {
this[k] = res[k]; this[k] = res[k];
} }
this.showMetrics = await allDashboardsExist(this.$store.dispatch, this.currentCluster.id, [WORKLOAD_METRICS_DETAIL_URL, WORKLOAD_METRICS_SUMMARY_URL]);
}, },
data() { data() {
return { allPods: null, allJobs: [] }; return {
allPods: null, allJobs: [], WORKLOAD_METRICS_DETAIL_URL, WORKLOAD_METRICS_SUMMARY_URL, showMetrics: false
};
}, },
computed: { computed: {
...mapGetters(['currentCluster']),
pods() { pods() {
const relationships = get(this.value, 'metadata.relationships') || []; const relationships = get(this.value, 'metadata.relationships') || [];
const podRelationship = relationships.filter(relationship => relationship.toType === POD)[0]; const podRelationship = relationships.filter(relationship => relationship.toType === POD)[0];
@ -200,6 +222,14 @@ export default {
POD_IMAGES POD_IMAGES
]; ];
}, },
graphVars() {
return {
namespace: this.value.namespace,
kind: WORKLOAD_TYPE_TO_KIND_MAPPING[this.value.type],
workload: this.value.id
};
}
}, },
}; };
</script> </script>
@ -233,7 +263,7 @@ export default {
</template> </template>
</div> </div>
<ResourceTabs :value="value"> <ResourceTabs :value="value">
<Tab v-if="isCronJob" name="jobs" :label="t('tableHeaders.jobs')"> <Tab v-if="isCronJob" name="jobs" :label="t('tableHeaders.jobs')" :weight="4">
<SortableTable <SortableTable
:rows="jobs" :rows="jobs"
:headers="jobHeaders" :headers="jobHeaders"
@ -243,7 +273,7 @@ export default {
:search="false" :search="false"
/> />
</Tab> </Tab>
<Tab v-else name="pods" :label="t('tableHeaders.pods')"> <Tab v-else name="pods" :label="t('tableHeaders.pods')" :weight="4">
<SortableTable <SortableTable
v-if="pods" v-if="pods"
:rows="pods" :rows="pods"
@ -255,6 +285,17 @@ export default {
:search="false" :search="false"
/> />
</Tab> </Tab>
<Tab v-if="showMetrics" :label="t('workload.container.titles.metrics')" name="workload-metrics" :weight="3">
<template #default="props">
<DashboardMetrics
v-if="props.active"
:detail-url="WORKLOAD_METRICS_DETAIL_URL"
:summary-url="WORKLOAD_METRICS_SUMMARY_URL"
:vars="graphVars"
graph-height="550px"
/>
</template>
</Tab>
</ResourceTabs> </ResourceTabs>
</div> </div>
</template> </template>

View File

@ -1,5 +1,4 @@
<script> <script>
import { mapGetters } from 'vuex';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import InstallRedirect from '@/utils/install-redirect'; import InstallRedirect from '@/utils/install-redirect';
@ -25,74 +24,70 @@ export default {
middleware: InstallRedirect(NAME, CHART_NAME), middleware: InstallRedirect(NAME, CHART_NAME),
async fetch() {
await this.fetchDeps();
},
data() { data() {
const grafanaSrc = require('~/assets/images/vendor/grafana.svg');
const prometheusSrc = require('~/assets/images/vendor/prometheus.svg');
const currentCluster = this.$store.getters['currentCluster'];
return { return {
availableLinks: { availableLinks: {
alertmanager: false, alertmanager: false,
grafana: false, grafana: false,
prometheus: false, prometheus: false,
}, },
grafanaSrc: require('~/assets/images/vendor/grafana.svg'),
prometheusSrc: require('~/assets/images/vendor/prometheus.svg'),
resources: [MONITORING.ALERTMANAGER, MONITORING.PROMETHEUS], resources: [MONITORING.ALERTMANAGER, MONITORING.PROMETHEUS],
v1Installed: false, v1Installed: false,
}; externalLinks: [
},
computed: {
...mapGetters(['currentCluster']),
externalLinks() {
return [
{ {
enabled: false, enabled: false,
group: 'alertmanager', group: 'alertmanager',
iconSrc: this.prometheusSrc, iconSrc: prometheusSrc,
label: 'monitoring.overview.linkedList.alertManager.label', label: 'monitoring.overview.linkedList.alertManager.label',
description: description:
'monitoring.overview.linkedList.alertManager.description', 'monitoring.overview.linkedList.alertManager.description',
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-alertmanager:9093/proxy`, link: `/k8s/clusters/${ currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-alertmanager:9093/proxy`,
}, },
{ {
enabled: false, enabled: false,
group: 'grafana', group: 'grafana',
iconSrc: this.grafanaSrc, iconSrc: grafanaSrc,
label: 'monitoring.overview.linkedList.grafana.label', label: 'monitoring.overview.linkedList.grafana.label',
description: 'monitoring.overview.linkedList.grafana.description', description: 'monitoring.overview.linkedList.grafana.description',
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy`, link: `/k8s/clusters/${ currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy`,
}, },
{ {
enabled: false, enabled: false,
group: 'prometheus', group: 'prometheus',
iconSrc: this.prometheusSrc, iconSrc: prometheusSrc,
label: 'monitoring.overview.linkedList.prometheusPromQl.label', label: 'monitoring.overview.linkedList.prometheusPromQl.label',
description: description:
'monitoring.overview.linkedList.prometheusPromQl.description', 'monitoring.overview.linkedList.prometheusPromQl.description',
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/graph`, link: `/k8s/clusters/${ currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/graph`,
}, },
{ {
enabled: false, enabled: false,
group: 'prometheus', group: 'prometheus',
iconSrc: this.prometheusSrc, iconSrc: prometheusSrc,
label: 'monitoring.overview.linkedList.prometheusRules.label', label: 'monitoring.overview.linkedList.prometheusRules.label',
description: description:
'monitoring.overview.linkedList.prometheusRules.description', 'monitoring.overview.linkedList.prometheusRules.description',
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/rules`, link: `/k8s/clusters/${ currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/rules`,
}, },
{ {
enabled: false, enabled: false,
group: 'prometheus', group: 'prometheus',
iconSrc: this.prometheusSrc, iconSrc: prometheusSrc,
label: 'monitoring.overview.linkedList.prometheusTargets.label', label: 'monitoring.overview.linkedList.prometheusTargets.label',
description: description:
'monitoring.overview.linkedList.prometheusTargets.description', 'monitoring.overview.linkedList.prometheusTargets.description',
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/targets`, link: `/k8s/clusters/${ currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/targets`,
}, },
]; ]
}, };
},
mounted() {
this.fetchDeps();
}, },
methods: { methods: {