Skip to content

Commit

Permalink
Merge pull request #290 from torchiaf/fix/270-metrics
Browse files Browse the repository at this point in the history
Node metrics integrations
  • Loading branch information
torchiaf authored Aug 21, 2023
2 parents 04a06c6 + ce33365 commit 6e50a1e
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 16 deletions.
4 changes: 4 additions & 0 deletions dashboard/pkg/epinio/l10n/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ epinio:
description: Create instances of your services. Instances can be bound to your Applications to provide data.
linkText: Create Instance
slotTitle: Quick start with
metrics:
availability: 'Available node resources: { availableCpu }% cpu, { availableMemory }% memory. '
link:
label: Show Metrics in Cluster Explorer
tableHeaders:
namespace: Namespace
instances:
Expand Down
98 changes: 88 additions & 10 deletions dashboard/pkg/epinio/pages/c/_cluster/dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
import Vue from 'vue';
import DashboardCard from '../../../components/dashboard/Cards.vue';
import { createEpinioRoute } from '../../../utils/custom-routing';
import { EpinioApplicationResource, EpinioCatalogService, EPINIO_TYPES } from '../../../types';
import { EpinioApplicationResource, EpinioCatalogService, EPINIO_MGMT_STORE, EPINIO_TYPES } from '../../../types';
import ConsumptionGauge from '@shell/components/ConsumptionGauge.vue';
import Namespace from '@shell/models/namespace';
import { parseSi, createMemoryValues } from '@shell/utils/units';
import EpinioServiceModel from '../../../models/services';
import isEqual from 'lodash/isEqual';
import { sortBy } from 'lodash';
import { Location } from 'vue-router';
import Banner from '@components/Banner/Banner.vue';
import { METRIC } from '@shell/config/types';
import { allHash } from '@shell/utils/promise';
type ComponentService = {
name: string,
Expand All @@ -17,15 +21,21 @@ type ComponentService = {
}
export default Vue.extend<any, any, any, any>({
components: { DashboardCard, ConsumptionGauge },
components: {
Banner,
DashboardCard,
ConsumptionGauge
},
async fetch() {
await Promise.all([
this.$store.dispatch(`epinio/findAll`, { type: EPINIO_TYPES.CATALOG_SERVICE }),
this.$store.dispatch(`epinio/findAll`, { type: EPINIO_TYPES.NAMESPACE }),
this.$store.dispatch(`epinio/findAll`, { type: EPINIO_TYPES.SERVICE_INSTANCE })
]);
const hash: { [key:string]: any } = await allHash({
ns: this.$store.dispatch(`epinio/findAll`, { type: EPINIO_TYPES.NAMESPACE }),
svc: this.$store.dispatch(`epinio/findAll`, { type: EPINIO_TYPES.SERVICE_INSTANCE }),
catalogSvc: this.$store.dispatch(`epinio/findAll`, { type: EPINIO_TYPES.CATALOG_SERVICE }),
version: this.$store.dispatch('epinio/version'),
showMetrics: this.calcAvailableResources()
});
this.version = await this.$store.dispatch('epinio/version');
this.version = hash.version;
},
data() {
return {
Expand Down Expand Up @@ -63,8 +73,11 @@ export default Vue.extend<any, any, any, any>({
colorStops: {
0: '--info', 30: '--info', 70: '--info'
},
version: null,
aboutLink: !this.$store.getters['isSingleProduct'] ? createEpinioRoute('c-cluster-about', { cluster: this.$store.getters['clusterId'] }) : null
version: null,
aboutLink: !this.$store.getters['isSingleProduct'] ? createEpinioRoute('c-cluster-about', { cluster: this.$store.getters['clusterId'] }) : null,
availableCpu: 100,
availableMemory: 100,
showMetricsInfo: false
};
},
created() {
Expand Down Expand Up @@ -94,6 +107,34 @@ export default Vue.extend<any, any, any, any>({
}
},
methods: {
async calcAvailableResources() {
if (this.$store.getters['isSingleProduct']) {
return;
}
const nodeMetricsSchema = this.$store.getters[`epinio/schemaFor`](METRIC.NODE);
if (nodeMetricsSchema) {
const id = this.$store.getters['clusterId'];
const nodeMetrics = await this.$store.dispatch(`cluster/request`, { url: `/k8s/clusters/${ id }/v1/metrics.k8s.io.nodemetrics` }, { root: true });
const currentCluster = this.$store.getters[`${ EPINIO_MGMT_STORE }/byId`](EPINIO_TYPES.INSTANCE, id);
const cpu = {
total: parseSi(currentCluster.mgmtCluster?.status?.capacity?.cpu, null),
useful: parseSi(nodeMetrics.data[0].usage.cpu, null)
};
const memory = createMemoryValues(currentCluster.mgmtCluster?.status?.capacity?.memory, nodeMetrics.data[0].usage.memory);
this.availableCpu = Math.floor(100 - cpu.useful / cpu.total * 100);
this.availableMemory = Math.floor(100 - memory.useful / memory.total * 100);
this.showMetricsInfo = true;
}
},
redoCards() {
// Handles titles
this.sectionContent[0].title = this.t('typeLabel.withCount.namespaces', { n: this.namespaces.totalNamespaces });
Expand All @@ -113,6 +154,12 @@ export default Vue.extend<any, any, any, any>({
this.sectionContent[2].isLoaded = true;
this.sectionContent[2].isEnable = true;
}
},
openMetricsDetails() {
this.$router.replace({
name: 'c-cluster-explorer',
params: { cluster: this.$store.getters['clusterId'] }
});
}
},
computed: {
Expand Down Expand Up @@ -198,6 +245,21 @@ export default Vue.extend<any, any, any, any>({
</n-link>
</div>
</div>

<Banner
v-if="showMetricsInfo"
class="metrics"
color="info"
>
<span>
{{ t('epinio.intro.metrics.availability', { availableCpu, availableMemory }) }}
</span>
<a
class="cluster-link"
@click="openMetricsDetails"
>{{ t('epinio.intro.metrics.link.label') }}</a>
</Banner>

<div class="get-started">
<div
v-for="(card, index) in sectionContent"
Expand Down Expand Up @@ -326,3 +388,19 @@ export default Vue.extend<any, any, any, any>({
}
}
</style>

<style lang="scss">
.metrics {
&.banner {
margin-top: 0;
margin-bottom: 20px;
}
.banner__content {
.cluster-link {
cursor: pointer;
}
}
}
</style>
31 changes: 25 additions & 6 deletions dashboard/pkg/epinio/store/epinio-store/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SCHEMA } from '@shell/config/types';
import { METRIC, SCHEMA } from '@shell/config/types';
import { handleSpoofedRequest } from '@shell/plugins/dashboard-store/actions';
import { classify } from '@shell/plugins/dashboard-store/classify';
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
Expand Down Expand Up @@ -170,8 +170,10 @@ export default {
await commit('reset');
},

loadSchemas: ( ctx: any ) => {
const { commit, rootGetters } = ctx;
loadSchemas: async( ctx: any ) => {
const { commit, dispatch, rootGetters } = ctx;

const clusterId = rootGetters['clusterId'];

const res = {
data: [{
Expand Down Expand Up @@ -228,17 +230,34 @@ export default {
const spoofedSchemas = rootGetters['type-map/spoofedSchemas'](EPINIO_PRODUCT_NAME);
const excludeInstances = spoofedSchemas.filter((schema: any) => schema.id !== EPINIO_TYPES.INSTANCE);

res.data = res.data.concat(excludeInstances);
const data = [
...res.data,
...excludeInstances,
];

const isSingleProduct = ctx.getters['isSingleProduct'];

if (!isSingleProduct) {
try {
const nodeMetricsSchema = await dispatch(`cluster/request`, { url: `/k8s/clusters/${ clusterId }/v1/schemas/${ METRIC.NODE }` }, { root: true });

if (nodeMetricsSchema) {
data.push(nodeMetricsSchema);
}
} catch (e) {
console.warn(`Unable to fetch Node metrics schema for epinio cluster: ${ clusterId }`);// eslint-disable-line no-console
}
}

res.data.forEach((schema: any) => {
data.forEach((schema: any) => {
schema._id = normalizeType(schema.id);
schema._group = normalizeType(schema.attributes?.group);
});

commit('loadAll', {
ctx,
type: SCHEMA,
data: res.data
data
});
},

Expand Down

0 comments on commit 6e50a1e

Please sign in to comment.