cloudfoundry/stratos

View on GitHub
src/frontend/packages/kubernetes/src/kubernetes/pod-metrics/pod-metrics.component.ts

Summary

Maintainability
B
6 hrs
Test Coverage
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { getIdFromRoute } from '../../../../core/src/core/utils.service';
import { MetricsConfig } from '../../../../core/src/shared/components/metrics-chart/metrics-chart.component';
import { MetricsLineChartConfig } from '../../../../core/src/shared/components/metrics-chart/metrics-chart.types';
import {
  ChartDataTypes,
  getMetricsChartConfigBuilder,
} from '../../../../core/src/shared/components/metrics-chart/metrics.component.helpers';
import { IHeaderBreadcrumb } from '../../../../core/src/shared/components/page-header/page-header.types';
import { EntityInfo } from '../../../../store/src/types/api.types';
import { ChartSeries, IMetricMatrixResult } from '../../../../store/src/types/base-metric.types';
import { IMetricApplication } from '../../../../store/src/types/metric.types';
import { kubeEntityCatalog } from '../kubernetes-entity-generator';
import { formatAxisCPUTime, formatCPUTime } from '../kubernetes-metrics.helpers';
import { BaseKubeGuid } from '../kubernetes-page.types';
import { KubernetesEndpointService } from '../services/kubernetes-endpoint.service';
import { KubernetesService } from '../services/kubernetes.service';
import { KubernetesPod } from '../store/kube.types';
import { FetchKubernetesMetricsAction } from '../store/kubernetes.actions';

@Component({
  selector: 'app-pod-metrics',
  templateUrl: './pod-metrics.component.html',
  styleUrls: ['./pod-metrics.component.scss'],
  providers: [
    {
      provide: BaseKubeGuid,
      useFactory: (activatedRoute: ActivatedRoute) => {
        return {
          guid: activatedRoute.snapshot.params.endpointId
        };
      },
      deps: [
        ActivatedRoute
      ]
    },
    KubernetesService,
    KubernetesEndpointService
  ]
})
export class PodMetricsComponent {
  podName: string;
  podEntity$: Observable<EntityInfo<KubernetesPod>>;
  namespaceName: any;
  public breadcrumbs$: Observable<IHeaderBreadcrumb[]>;

  public instanceMetricConfigs: [
    MetricsConfig<IMetricMatrixResult<IMetricApplication>>,
    MetricsLineChartConfig
  ][];

  constructor(
    public activatedRoute: ActivatedRoute,
    public kubeEndpointService: KubernetesEndpointService
  ) {
    this.podName = activatedRoute.snapshot.params.podName;
    this.namespaceName = getIdFromRoute(activatedRoute, 'namespaceName');
    const namespace = getIdFromRoute(activatedRoute, 'namespace') ? getIdFromRoute(activatedRoute, 'namespace') : this.namespaceName;
    const chartConfigBuilder = getMetricsChartConfigBuilder<IMetricApplication>(result => `${result.metric.container}`);
    const cpuChartConfigBuilder = getMetricsChartConfigBuilder<IMetricApplication>
      (result => !!result.metric.cpu ? `${result.metric.container}:${result.metric.cpu}` : `${result.metric.container}`);
    const networkChartConfigBuilder = getMetricsChartConfigBuilder<IMetricApplication>
      (result => `Network Interface: ${result.metric.interface}`);
    this.instanceMetricConfigs = [
      chartConfigBuilder(
        new FetchKubernetesMetricsAction(
          this.podName,
          kubeEndpointService.kubeGuid,
          `container_memory_usage_bytes{pod="${this.podName}",namespace="${namespace}"}`
        ),
        'Memory Usage (MB)',
        ChartDataTypes.BYTES,
        (series: ChartSeries[]) => {
          // Remove the metric series for pod overhead and for the total!
          return series.filter(s => !!s.metadata.container && s.metadata.container !== 'POD');
        },
        null,
        (value: string) => value + ' MB'
      ),
      cpuChartConfigBuilder(
        new FetchKubernetesMetricsAction(
          this.podName,
          kubeEndpointService.kubeGuid,
          `container_cpu_usage_seconds_total{pod="${this.podName}",namespace="${namespace}"}`
        ),
        'CPU Usage',
        ChartDataTypes.CPU_TIME,
        (series: ChartSeries[]) => {
          return series.filter(s => !!s.metadata.container && s.metadata.container !== 'POD');
        },
        (tick: string) => formatAxisCPUTime(tick),
        (value: string) => formatCPUTime(value),
      ),
      networkChartConfigBuilder(
        new FetchKubernetesMetricsAction(
          this.podName,
          kubeEndpointService.kubeGuid,
          `container_network_transmit_bytes_total{pod="${this.podName}",namespace="${namespace}"}`
        ),
        'Cumulative Data transmitted (MB)',
        ChartDataTypes.BYTES,
        null,
        null,
        (value: string) => value + ' MB'
      ),
      networkChartConfigBuilder(
        new FetchKubernetesMetricsAction(
          this.podName,
          kubeEndpointService.kubeGuid,
          `container_network_receive_bytes_total{pod="${this.podName}",namespace="${namespace}"}`
        ),
        'Cumulative Data received (MB)',
        ChartDataTypes.BYTES,
        null,
        null,
        (value: string) => value + ' MB'
      )
    ];


    this.breadcrumbs$ = kubeEndpointService.endpoint$.pipe(
      map(endpoint => {

        // check if this is being invoked from the node path
        const nodeName = getIdFromRoute(activatedRoute, 'nodeName');
        if (!!nodeName) {
          return [{
            breadcrumbs: [
              { value: endpoint.entity.name, routerLink: `/kubernetes/${endpoint.entity.guid}/nodes` },
              { value: nodeName, routerLink: `/kubernetes/${endpoint.entity.guid}/nodes/${nodeName}/pods` },
            ]
          }];
        }
        // check if this is being invoked from the namespace path
        if (!!this.namespaceName) {
          return [{
            breadcrumbs: [
              { value: endpoint.entity.name, routerLink: `/kubernetes/${endpoint.entity.guid}/namespaces` },
              { value: this.namespaceName, routerLink: `/kubernetes/${endpoint.entity.guid}/namespaces/${this.namespaceName}/pods` },
            ]
          }];
        }
        // Finally, check if this is being invoked from the helm-release path
        const releaseName = getIdFromRoute(activatedRoute, 'releaseName');
        if (!!releaseName) {
          return [{
            breadcrumbs: [
              { value: endpoint.entity.name, routerLink: `/kubernetes/${endpoint.entity.guid}/apps` },
              { value: releaseName, routerLink: `/kubernetes/${endpoint.entity.guid}/apps/${releaseName}/pods` },
            ]
          }];
        }
        return [{
          breadcrumbs: [
            { value: endpoint.entity.name, routerLink: `/kubernetes/${endpoint.entity.guid}/pods` },
          ]
        }];
      })
    );
    this.podEntity$ = kubeEntityCatalog.pod.store.getEntityService(this.podName, this.kubeEndpointService.kubeGuid, {
      namespace: this.namespaceName
    }).entityObs$;
  }
}