From 9d7ac64b3e904435c0b83225f91d3f4299543913 Mon Sep 17 00:00:00 2001
From: Eric <menwe@amazon.com>
Date: Sat, 9 Nov 2024 23:48:04 +0000
Subject: [PATCH] change nav structure and add cluster overiew

Signed-off-by: Eric <menwe@amazon.com>
---
 .../kubernetes/common/gourp_dashboards.tsx    |  58 +++--
 public/components/kubernetes/home.tsx         | 211 ++++++++++++++++--
 .../visualizations/visualization.tsx          |   1 +
 .../visualizations/visualization_chart.tsx    |   1 +
 public/index.scss                             |   1 +
 public/plugin.tsx                             | 137 +++++++++++-
 6 files changed, 364 insertions(+), 45 deletions(-)

diff --git a/public/components/kubernetes/common/gourp_dashboards.tsx b/public/components/kubernetes/common/gourp_dashboards.tsx
index ea1dfdde32..3956dd5749 100644
--- a/public/components/kubernetes/common/gourp_dashboards.tsx
+++ b/public/components/kubernetes/common/gourp_dashboards.tsx
@@ -11,6 +11,7 @@ import {
   EuiCompressedSuperDatePicker,
   EuiSpacer,
   EuiPageHeader,
+  EuiText,
 } from '@elastic/eui';
 import { Responsive, WidthProvider } from 'react-grid-layout';
 import { PlotlyHTMLElement } from 'plotly.js';
@@ -20,6 +21,7 @@ import PPLService from '../../../services/requests/ppl';
 import { coreRefs } from '../../../framework/core_refs';
 import { uiSettingsService } from '../../../../common/utils';
 import { Plt } from '../../../components/visualizations/plotly/plot';
+import { PLOTLY_COLOR } from '../../../../common/constants/shared';
 
 const ResponsiveGridLayout = WidthProvider(Responsive);
 
@@ -52,19 +54,19 @@ const layouts = {
   lg: [
     // Top row with global usage and counts
     { i: 'clusterCPUUsage', x: 0, y: 0, w: 5, h: 2 },
-    { i: 'clusterMemoryUsage', x: 2, y: 0, w: 2, h: 2 },
-    { i: 'nodesCount', x: 4, y: 0, w: 1, h: 1 },
-    { i: 'namespacesCount', x: 5, y: 0, w: 1, h: 2 },
-    { i: 'runningPodsCount', x: 6, y: 0, w: 2, h: 2 },
+    { i: 'clusterMemoryUsage', x: 0, y: 3, w: 5, h: 2 },
+    { i: 'nodesCount', x: 5, y: 0, w: 1, h: 1 },
+    { i: 'namespacesCount', x: 5, y: 1, w: 1, h: 1 },
+    { i: 'runningPodsCount', x: 5, y: 2, w: 1, h: 1 },
 
     // Middle row with CPU and RAM utilization
-    // { i: 'cpuUsage', x: 0, y: 2, w: 2, h: 1 },
-    // { i: 'ramUsage', x: 2, y: 2, w: 2, h: 1 },
+    // { i: 'ramUsage', x: 5, y: 4, w: 2, h: 1 },
     // { i: 'clusterCPUUtilization', x: 4, y: 2, w: 2, h: 1 },
     // { i: 'clusterMemoryUtilization', x: 6, y: 2, w: 2, h: 1 },
 
     // Additional information panels
-    { i: 'runningPodsCategory', x: 0, y: 3, w: 3, h: 2 },
+    { i: 'runningPodsCategory', x: 7, y: 0, w: 2, h: 2 },
+    { i: 'cpuCoreCount', x: 5, y: 3, w: 1, h: 1 },
     { i: 'totalNetworkTraffic', x: 3, y: 3, w: 5, h: 2 },
 
     // Visualization row with detailed charts
@@ -85,7 +87,7 @@ const layouts = {
     { i: 'nodesCount', x: 4, y: 0, w: 1, h: 2 },
     { i: 'namespacesCount', x: 5, y: 0, w: 1, h: 2 },
     { i: 'runningPodsCount', x: 6, y: 0, w: 2, h: 2 },
-    { i: 'cpuUsage', x: 0, y: 2, w: 2, h: 1 },
+    { i: 'cpuCoreCount', x: 0, y: 2, w: 2, h: 1 },
     { i: 'ramUsage', x: 2, y: 2, w: 2, h: 1 },
     { i: 'clusterCPUUtilization', x: 4, y: 2, w: 2, h: 1 },
     { i: 'clusterMemoryUtilization', x: 6, y: 2, w: 2, h: 1 },
@@ -104,7 +106,7 @@ const layouts = {
     { i: 'nodesCount', x: 0, y: 2, w: 2, h: 2 },
     { i: 'namespacesCount', x: 2, y: 2, w: 2, h: 2 },
     { i: 'runningPodsCount', x: 0, y: 4, w: 2, h: 2 },
-    { i: 'cpuUsage', x: 2, y: 4, w: 2, h: 1 },
+    { i: 'cpuCoreCount', x: 2, y: 4, w: 2, h: 1 },
     { i: 'ramUsage', x: 0, y: 5, w: 2, h: 1 },
     { i: 'clusterCPUUtilization', x: 2, y: 5, w: 2, h: 1 },
     { i: 'clusterMemoryUtilization', x: 0, y: 6, w: 2, h: 1 },
@@ -149,10 +151,22 @@ export const GroupDashboards = ({
     gKeys: string[],
     traceConfig: {}
   ) => {
-    console.log('data: ', data);
-    console.log('xKeys[0]: ', xKeys[0]);
-    console.log('yKeys[0]: ', yKeys[0]);
-    if (gKeys.length === 0) {
+    if (traceConfig.type === 'pie') {
+      return [
+        {
+          labels: data.data[xKeys[0]],
+          values: data.data[yKeys[0]],
+          ...traceConfig,
+        },
+      ];
+    } else if (traceConfig.type === 'indicator') {
+      return [
+        {
+          value: data?.data[yKeys[0]][0] || 0,
+          ...traceConfig,
+        },
+      ];
+    } else if (gKeys.length === 0) {
       return [
         {
           x: data.data[xKeys[0]],
@@ -187,14 +201,13 @@ export const GroupDashboards = ({
   const renderPanel = (metrics: IMetrics[]) => {
     console.log('metrics', metrics);
     return metrics.map((metric, index) => {
-      if (!metric) {
-        return null;
-      }
+      // if (!metric) {
+      //   return [];
+      // }
 
       const visXaxisKeys = prometheusQueries[index].vis.xKeys;
       const visYaxisKeys = prometheusQueries[index].vis.yKeys;
       const visGroupingKeys = prometheusQueries[index].vis.gKeys;
-      console.log('metric: ', metric);
       const visualizationData = getProcessedMetricsVizData(
         metric,
         visXaxisKeys,
@@ -202,7 +215,6 @@ export const GroupDashboards = ({
         visGroupingKeys,
         prometheusQueries[index].vis.config
       );
-      console.log('visualizationData: ', visualizationData);
 
       // metric
       // jdbc
@@ -214,6 +226,9 @@ export const GroupDashboards = ({
       return (
         <div key={prometheusQueries[index].title + index} data-grid={layouts.lg[index]}>
           <EuiPanel paddingSize="m">
+            <EuiText>
+              <h4>{prometheusQueries[index].title}</h4>
+            </EuiText>
             <Plt
               // data={[
               //   {
@@ -224,6 +239,10 @@ export const GroupDashboards = ({
               // ]}
               data={visualizationData}
               layout={{
+                // width: 200, // Set custom width
+                // height: 150, // Set custom height
+                margin: { t: 0, b: 0, l: 0, r: 0 }, // Minimal margins
+                padding: { t: 0, b: 0, l: 0, r: 0 }, // Minimal padding
                 showlegend: true,
                 ...(prometheusQueries[index].vis.layout || {}),
                 xaxis: {
@@ -243,10 +262,10 @@ export const GroupDashboards = ({
                   zeroline: false,
                   rangemode: 'normal',
                 },
+                colorway: PLOTLY_COLOR
               }}
               // config={prometheusQueries[index].vis.component.config}
             />
-            <EuiSpacer size="m" />
             {/* <Visualization
             visualizations={{
               data: {
@@ -269,6 +288,7 @@ export const GroupDashboards = ({
             }}
           /> */}
           </EuiPanel>
+          <EuiSpacer size="m" />
         </div>
       );
     });
diff --git a/public/components/kubernetes/home.tsx b/public/components/kubernetes/home.tsx
index 0a5abdd21f..79c06ebc32 100644
--- a/public/components/kubernetes/home.tsx
+++ b/public/components/kubernetes/home.tsx
@@ -7,29 +7,30 @@ import React from 'react';
 import { GroupDashboards } from './common/gourp_dashboards';
 import { Line } from '../visualizations/charts/lines/line';
 import { convertDateTime } from '../common/query_utils';
+import { Pie } from '../visualizations/charts/pie/pie';
 
-// function determineExactSpan(startTime: number, endTime: number): string {
-//   const durationInSeconds = Math.round(
-//     (new Date(endTime).getTime() - new Date(startTime).getTime()) / 1000
-//   ); // Round to nearest second
+function determineExactSpan(startTime: number, endTime: number): string {
+  const durationInSeconds = Math.round(
+    (new Date(endTime).getTime() - new Date(startTime).getTime()) / 1000
+  ); // Round to nearest second
 
-//   // Convert the duration into the appropriate PPL-compatible span format
-//   if (durationInSeconds < 60) {
-//     return `${durationInSeconds}s`; // Duration in seconds
-//   } else if (durationInSeconds < 3600) {
-//     return `${Math.floor(durationInSeconds / 60)}m`; // Duration in minutes
-//   } else if (durationInSeconds < 86400) {
-//     return `${Math.floor(durationInSeconds / 3600)}h`; // Duration in hours
-//   } else if (durationInSeconds < 604800) {
-//     return `${Math.floor(durationInSeconds / 86400)}d`; // Duration in days
-//   } else if (durationInSeconds < 2592000) {
-//     return `${Math.floor(durationInSeconds / 604800)}w`; // Duration in weeks
-//   } else if (durationInSeconds < 31536000) {
-//     return `${Math.floor(durationInSeconds / 2592000)}M`; // Duration in months
-//   } else {
-//     return `${Math.floor(durationInSeconds / 31536000)}y`; // Duration in years
-//   }
-// }
+  // Convert the duration into the appropriate PPL-compatible span format
+  if (durationInSeconds < 60) {
+    return `${durationInSeconds}s`; // Duration in seconds
+  } else if (durationInSeconds < 3600) {
+    return `${Math.floor(durationInSeconds / 60)}m`; // Duration in minutes
+  } else if (durationInSeconds < 86400) {
+    return `${Math.floor(durationInSeconds / 3600)}h`; // Duration in hours
+  } else if (durationInSeconds < 604800) {
+    return `${Math.floor(durationInSeconds / 86400)}d`; // Duration in days
+  } else if (durationInSeconds < 2592000) {
+    return `${Math.floor(durationInSeconds / 604800)}w`; // Duration in weeks
+  } else if (durationInSeconds < 31536000) {
+    return `${Math.floor(durationInSeconds / 2592000)}M`; // Duration in months
+  } else {
+    return `${Math.floor(durationInSeconds / 31536000)}y`; // Duration in years
+  }
+}
 
 function getSpanFromTimeRange(startTime, endTime) {
   const durationInSeconds = new Date(endTime).getTime() - new Date(startTime).getTime();
@@ -52,7 +53,7 @@ export const Home = () => {
 
   const start = convertDateTime(startTime, true);
   const end = convertDateTime(endTime, false);
-  // const exactTimeInterval = determineExactSpan(start, end);
+  const exactTimeInterval = determineExactSpan(start, end);
   const timeInterval = getSpanFromTimeRange(start, end);
 
   return (
@@ -65,9 +66,9 @@ export const Home = () => {
         {
           cluster: 'eks-cluster-with-vpc',
           name: 'clusterCPUUsage',
-          title: 'Cluster CPU Usage',
+          title: 'Cluster Total CPU Usage',
           // query: `source = prometheus_k8s_cluster.\`cluster:node_cpu:sum_rate5m\` | where @timestamp >= '${start}' and @timestamp <= '${end}'`,
-          query: `source = prometheus_k8s_cluster.container_cpu_usage_seconds_total | where @timestamp >= '${start}' and @timestamp <= '${end}' | where \`cluster\` = 'eks-cluster-with-vpc' | stats sum(@value) as total_cpu_usage by span(@timestamp,${timeInterval})`,
+          query: `source = prometheus_k8s_cluster.container_cpu_usage_seconds_total | where @timestamp >= '${start}' and @timestamp <= '${end}' | where \`cluster\` = 'eks-cluster-with-vpc' | stats sum(@value) as total_cpu_usage by container, span(@timestamp,${timeInterval})`,
           endpoint: 'prometheus',
           datasource: { name: 'prometheus_k8s', type: 'prometheus' },
           vis: {
@@ -85,6 +86,168 @@ export const Home = () => {
             },
             xKeys: [`span(@timestamp,${timeInterval})`],
             yKeys: ['total_cpu_usage'],
+            gKeys: ['container'],
+          },
+        },
+        {
+          cluster: 'eks-cluster-with-vpc',
+          name: 'clusterMemoryUsage',
+          title: 'Cluster Total Memory Usage',
+          // query: `source = prometheus_k8s_cluster.\`cluster:node_cpu:sum_rate5m\` | where @timestamp >= '${start}' and @timestamp <= '${end}'`,
+          query: `source = prometheus_k8s_cluster.node_memory_MemTotal_bytes | where cluster = 'eks-cluster-with-vpc' | stats sum(@value) as total_memory_usage by nodename, span(@timestamp, ${timeInterval})`,
+          endpoint: 'prometheus',
+          datasource: { name: 'prometheus_k8s', type: 'prometheus' },
+          vis: {
+            component: Line,
+            x: 'timestamp',
+            y: 'total_memory_usage',
+            xaxisKey: '@timestamp',
+            yaxisKey: 'total_memory_usage',
+            config: {
+              type: 'line',
+              mode: 'lines',
+              line: {
+                shape: 'spline', // This makes the line smooth
+              },
+            },
+            xKeys: [`span(@timestamp,${timeInterval})`],
+            yKeys: ['total_memory_usage'],
+            gKeys: ['nodename'],
+          },
+        },
+        {
+          cluster: 'eks-cluster-with-vpc',
+          name: 'nodesCount',
+          title: 'Nodes',
+          query: `source = prometheus_k8s_cluster.\`count:up1\` |  where @timestamp >= '${start}' and @timestamp <= '${end}' and cluster = 'eks-cluster-with-vpc' and @value=1 | stats count() as running_node_count by span(@timestamp, ${exactTimeInterval})`,
+          //query: `source = prometheus_k8s_cluster.\`count:up1\` | where \`cluster\` = 'eks-cluster-with-vpc' | dedup k8s_node_name | stats count() as running_node_count by k8s_node_name`,
+          endpoint: 'prometheus',
+          datasource: { name: 'prometheus_k8s', type: 'prometheus' },
+          vis: {
+            component: Pie,
+            x: 'timestamp',
+            y: 'Number of Nodes',
+            xaxisKey: '@timestamp',
+            yaxisKey: 'total_memory_usage',
+            config: {
+              type: 'indicator',
+              mode: "number"
+            },
+            layout: {
+              width: 250,
+              height: 190
+            },
+            xKeys: [`k8s_node_name`],
+            yKeys: ['running_node_count'],
+            gKeys: [],
+          },
+        },
+        {
+          cluster: 'eks-cluster-with-vpc',
+          name: 'namespacesCount',
+          title: 'Namespaces',
+          query: `source = prometheus_k8s_cluster.\`count:up1\` |  where @timestamp >= '${start}' and @timestamp <= '${end}' and cluster = 'eks-cluster-with-vpc' and @value=1 | stats count() as running_node_count by span(@timestamp, ${exactTimeInterval})`,
+          //query: `source = prometheus_k8s_cluster.\`count:up1\` | where \`cluster\` = 'eks-cluster-with-vpc' | dedup k8s_node_name | stats count() as running_node_count by k8s_node_name`,
+          endpoint: 'prometheus',
+          datasource: { name: 'prometheus_k8s', type: 'prometheus' },
+          vis: {
+            component: Pie,
+            x: 'timestamp',
+            y: 'Number of Nodes',
+            xaxisKey: '@timestamp',
+            yaxisKey: 'total_memory_usage',
+            config: {
+              type: 'indicator',
+              mode: "number"
+            },
+            layout: {
+              width: 250,
+              height: 190
+            },
+            xKeys: [`k8s_node_name`],
+            yKeys: ['running_node_count'],
+            gKeys: [],
+          },
+        },
+        {
+          cluster: 'eks-cluster-with-vpc',
+          name: 'runningPodsCount',
+          title: 'Running Pods',
+          query: `source = prometheus_k8s_cluster.\`count:up1\` |  where @timestamp >= '${start}' and @timestamp <= '${end}' and cluster = 'eks-cluster-with-vpc' and @value=1 | stats count() as running_node_count by span(@timestamp, ${exactTimeInterval})`,
+          //query: `source = prometheus_k8s_cluster.\`count:up1\` | where \`cluster\` = 'eks-cluster-with-vpc' | dedup k8s_node_name | stats count() as running_node_count by k8s_node_name`,
+          endpoint: 'prometheus',
+          datasource: { name: 'prometheus_k8s', type: 'prometheus' },
+          vis: {
+            component: Pie,
+            x: 'timestamp',
+            y: 'Number of Nodes',
+            xaxisKey: '@timestamp',
+            yaxisKey: 'total_memory_usage',
+            config: {
+              type: 'indicator',
+              mode: "number"
+            },
+            layout: {
+              width: 250,
+              height: 190
+            },
+            xKeys: [`k8s_node_name`],
+            yKeys: ['running_node_count'],
+            gKeys: [],
+          },
+        },
+        {
+          cluster: 'eks-cluster-with-vpc',
+          name: 'runningPodsCategory',
+          title: 'Failed Pods',
+          query: `source = prometheus_k8s_cluster.kube_pod_status_phase | where @timestamp >= '${start}' and @timestamp <= '${end}' and cluster = 'eks-cluster-with-vpc' | fields service_name | stats count() as node_count by service_name`,
+          //query: `source = prometheus_k8s_cluster.\`count:up1\` | where \`cluster\` = 'eks-cluster-with-vpc' | dedup k8s_node_name | stats count() as running_node_count by k8s_node_name`,
+          endpoint: 'prometheus',
+          datasource: { name: 'prometheus_k8s', type: 'prometheus' },
+          vis: {
+            component: Pie,
+            x: 'timestamp',
+            y: 'Number of Nodes',
+            xaxisKey: '@timestamp',
+            yaxisKey: 'total_memory_usage',
+            config: {
+              type: 'pie',
+              hole: .4,
+              textposition: 'inside',
+              showlegend: false
+            },
+            // layout: {
+            //   width: 267,
+            //   height: 190
+            // },
+            xKeys: [`pod`],
+            yKeys: ['running_node_count'],
+            gKeys: [],
+          },
+        },
+        {
+          cluster: 'eks-cluster-with-vpc',
+          name: 'cpuCoreCount',
+          title: 'Cluster CPU Cores',
+          query: `source = prometheus_k8s_cluster.machine_cpu_cores | where @timestamp >= '${start}' and @timestamp <= '${end}' and cluster = 'eks-cluster-with-vpc' | fields @value | stats count() as core_count`,
+          endpoint: 'prometheus',
+          datasource: { name: 'prometheus_k8s', type: 'prometheus' },
+          vis: {
+            component: Pie,
+            x: 'timestamp',
+            y: 'Number of cores',
+            xaxisKey: '@timestamp',
+            yaxisKey: 'total_memory_usage',
+            config: {
+              type: 'indicator',
+              mode: "number"
+            },
+            layout: {
+              width: 250,
+              height: 190
+            },
+            xKeys: [`k8s_node_name`],
+            yKeys: ['core_count'],
             gKeys: [],
           },
         },
diff --git a/public/components/visualizations/visualization.tsx b/public/components/visualizations/visualization.tsx
index dc963ec9c8..c0ed1d0062 100644
--- a/public/components/visualizations/visualization.tsx
+++ b/public/components/visualizations/visualization.tsx
@@ -55,6 +55,7 @@ export const Visualization = ({
   };
 
   const [isValid, erroInfo] = isVisDataValid(visualizations);
+  console.log('isValid', isValid);
   return (
     <>
       {isValid ? (
diff --git a/public/components/visualizations/visualization_chart.tsx b/public/components/visualizations/visualization_chart.tsx
index 3700f758db..232ca48673 100644
--- a/public/components/visualizations/visualization_chart.tsx
+++ b/public/components/visualizations/visualization_chart.tsx
@@ -9,6 +9,7 @@ export const VisualizationChart = ({ visualizations }) => {
   const { vis } = visualizations;
   const { layout = {}, config = {} } = visualizations?.data?.userConfigs;
   const Visualization = visualizations?.vis?.component;
+  console.log('Visualization: ', Visualization);
   const finalFigureConfig = useMemo(() => {
     return {
       ...vis.visconfig?.config,
diff --git a/public/index.scss b/public/index.scss
index 3188643388..9b0f5a7449 100644
--- a/public/index.scss
+++ b/public/index.scss
@@ -11,6 +11,7 @@
 
 // event analytics
 @import 'components/event_analytics/index';
+@import 'components/kubernetes/index';
 
 .synopsisIcon {
   height: 40px;
diff --git a/public/plugin.tsx b/public/plugin.tsx
index 196f8d61d1..5fbe11b53d 100644
--- a/public/plugin.tsx
+++ b/public/plugin.tsx
@@ -12,6 +12,7 @@ import {
   CoreSetup,
   CoreStart,
   DEFAULT_APP_CATEGORIES,
+  DEFAULT_NAV_GROUPS,
   Plugin,
   PluginInitializerContext,
   SavedObject,
@@ -119,6 +120,7 @@ import {
   ObservabilityStart,
   SetupDependencies,
 } from './types';
+import cluster from 'cluster';
 
 interface PublicConfig {
   query_assist: {
@@ -252,6 +254,34 @@ export class ObservabilityPlugin
         }),
         order: observabilityPluginOrder,
       },
+      kubernetes: {
+        id: 'observability-kubernetes',
+        label: i18n.translate('core.ui.observabilityNavList.label', {
+          defaultMessage: 'Kubenetes',
+        }),
+        order: 5095,
+      },
+      cluster: {
+        id: 'observability-kubernetes-cluster',
+        label: i18n.translate('core.ui.observabilityNavList.label', {
+          defaultMessage: 'Cluster',
+        }),
+        order: 5096,
+      },
+      namespaces: {
+        id: 'observability-kubernetes-namespaces',
+        label: i18n.translate('core.ui.observabilityNavList.label', {
+          defaultMessage: 'Namespaces',
+        }),
+        order: 5097,
+      },
+      pod: {
+        id: 'observability-kubernetes-pod',
+        label: i18n.translate('core.ui.observabilityNavList.label', {
+          defaultMessage: 'Pod',
+        }),
+        order: 5098,
+      }
     });
 
     // Adding a variation entails associating a key-value pair, where a change in the key results in
@@ -331,6 +361,39 @@ export class ObservabilityPlugin
       );
     };
 
+    // core.application.register({
+    //   id: 'observability-kubernetes',
+    //   title: 'Kubernetes',
+    //   description: 'OpenSearch Dashboards Kubernetes Plugin',
+    //   category: {
+    //     id: 'opensearch',
+    //     label: 'OpenSearch Plugins',
+    //     order: 2000,
+    //   },
+    //   order: 4000,
+    //   mount: async (params) => {
+    //     const { renderApp } = await import('./components/kubernetes/home');
+    //     const [coreStart] = await core.getStartServices();
+    //     return renderApp(coreStart, params);
+    //   },
+    // });
+
+    core.chrome.navGroup.addNavLinksToGroup(OBSERVABILITY_APP_CATEGORIES.kubernetes, [
+      {
+        id: 'observability-kubernetes',
+        category: DEFAULT_APP_CATEGORIES.observability,
+        parentNavLinkId: DEFAULT_APP_CATEGORIES.observability.id,
+      },
+    ]);
+
+    // core.chrome.navGroup.addNavLinksToGroup(OBSERVABILITY_APP_CATEGORIES.cluster, [
+    //   {
+    //     id: 'observability-kubernetes-cluster',
+    //     category: DEFAULT_APP_CATEGORIES.observability,
+    //     parentNavLinkId: DEFAULT_APP_CATEGORIES.observability.id,
+    //   },
+    // ]);
+
     core.application.register({
       id: observabilityMetricsID,
       title: observabilityMetricsTitle,
@@ -356,7 +419,7 @@ export class ObservabilityPlugin
       order: observabilityIntegrationsPluginOrder,
       mount: appMountWithStartPage('integrations'),
     });
-
+    console.log('core.chrome.navGroup.getNavGroupEnabled(): ', core.chrome.navGroup.getNavGroupEnabled());
     if (core.chrome.navGroup.getNavGroupEnabled()) {
       core.application.register({
         id: observabilityOverviewID,
@@ -389,6 +452,20 @@ export class ObservabilityPlugin
         category: DEFAULT_APP_CATEGORIES.investigate,
         mount: appMountWithStartPage('traces', '/services'),
       });
+
+      // core.application.register({
+      //   id: 'observability-kubernetes',
+      //   title: 'Kubernetes',
+      //   category: DEFAULT_APP_CATEGORIES.observability,
+      //   // category: {
+      //   //   id: 'observability',
+      //   //   label: 'Observability',
+      //   //   order: 3000,
+      //   // },
+      //   order: 5095,
+      //   mount: appMountWithStartPage('kubernetes'),
+      // });
+
     } else {
       core.application.register({
         id: observabilityTracesID,
@@ -427,11 +504,67 @@ export class ObservabilityPlugin
     core.application.register({
       id: 'observability-kubernetes',
       title: 'Kubernetes',
-      category: OBSERVABILITY_APP_CATEGORIES.observability,
+      category: DEFAULT_APP_CATEGORIES.observability,
       order: 5095,
       mount: appMountWithStartPage('kubernetes'),
     });
 
+    core.application.register({
+      id: 'kubernetes-overview',
+      title: 'Overview',
+      category: OBSERVABILITY_APP_CATEGORIES.kubernetes,
+      order: 5096,
+      mount: appMountWithStartPage('kubernetes-overview'),
+    });
+
+    core.application.register({
+      id: 'kubernetes-cluster',
+      title: 'Cluster',
+      category: OBSERVABILITY_APP_CATEGORIES.kubernetes,
+      order: 5096,
+      mount: appMountWithStartPage('kubernetes-cluster'),
+    });
+
+    core.application.register({
+      id: 'kubernetes-namespaces',
+      title: 'Namespace',
+      category: OBSERVABILITY_APP_CATEGORIES.kubernetes,
+      order: 5096,
+      mount: appMountWithStartPage('kubernetes-namespaces'),
+    });
+
+    core.application.register({
+      id: 'kubernetes-pod',
+      title: 'Pod',
+      category: OBSERVABILITY_APP_CATEGORIES.kubernetes,
+      order: 5096,
+      mount: appMountWithStartPage('kubernetes-pod'),
+    });
+
+    const navLinks = [
+      {
+        id: 'kubernetes-overview',
+        parentNavLinkId: OBSERVABILITY_APP_CATEGORIES.kubernetes.id,
+      },
+      {
+        id: 'kubernetes-cluster',
+        parentNavLinkId: OBSERVABILITY_APP_CATEGORIES.kubernetes.id,
+      },
+      {
+        id: 'kubernetes-namespaces',
+        parentNavLinkId: OBSERVABILITY_APP_CATEGORIES.kubernetes.id,
+      },
+      {
+        id: 'kubernetes-pod',
+        parentNavLinkId: OBSERVABILITY_APP_CATEGORIES.kubernetes.id,
+      },
+    ];
+
+    core.chrome.navGroup.addNavLinksToGroup(
+      OBSERVABILITY_APP_CATEGORIES.kubernetes,
+      navLinks
+    );
+
     registerAllPluginNavGroups(core);
 
     const embeddableFactory = new ObservabilityEmbeddableFactoryDefinition(async () => ({