Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add no logs and metrics banner when cluster is offline #317

Merged
merged 1 commit into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/apps/console/page-components/no-logs-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { motion } from 'framer-motion';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Evaluate necessity of Framer Motion

Consider the performance implications of using Framer Motion for this simple animation. React's built-in transitions might be sufficient and more lightweight for this use case.

import Pulsable from '~/components/atoms/pulsable';
import { EmptyState } from '~/console/components/empty-state';
import { SmileySad } from '~/console/components/icons';
import Wrapper from '~/console/components/wrapper';

export const NoLogsAndMetricsBanner = ({
title,
description,
}: {
title: string;
description: string;
}) => {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ ease: 'anticipate', duration: 0.1 }}
className="flex flex-col py-4xl"
>
<Wrapper>
<Pulsable isLoading={false}>
<EmptyState
{...{
image: <SmileySad size={48} />,
heading: <span>{title}</span>,
footer: (
<span className="flex items-center justify-center text-sm">
{description}
</span>
),
}}
/>
</Pulsable>
</Wrapper>
</motion.div>
);
};
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import { useOutletContext } from '@remix-run/react';
import { ApexOptions } from 'apexcharts';
import axios from 'axios';
import Chart from '~/console/components/charts/charts-client';
import useDebounce from '~/lib/client/hooks/use-debounce';
import { useState } from 'react';
import { dayjs } from '~/components/molecule/dayjs';
import Chart from '~/console/components/charts/charts-client';
import { findClusterStatusv3 } from '~/console/hooks/use-cluster-status';
import { useClusterStatusV3 } from '~/console/hooks/use-cluster-status-v3';
import { useDataState } from '~/console/page-components/common-state';
import LogAction from '~/console/page-components/log-action';
import { NoLogsAndMetricsBanner } from '~/console/page-components/no-logs-banner';
import { parseValue } from '~/console/page-components/util';
import { ApexOptions } from 'apexcharts';
import { parseName } from '~/console/server/r-utils/common';
import { useDataState } from '~/console/page-components/common-state';
import { observeUrl } from '~/lib/configs/base-url.cjs';
import LogComp from '~/lib/client/components/logger';
import LogAction from '~/console/page-components/log-action';
import useDebounce from '~/lib/client/hooks/use-debounce';
import { observeUrl } from '~/lib/configs/base-url.cjs';
import { generatePlainColor } from '~/root/lib/utils/color-generator';
import { IAppContext } from '../_layout';

const LogsAndMetrics = () => {
const { app, environment, account } = useOutletContext<IAppContext>();

const { clustersMap: clusterStatus } = useClusterStatusV3({
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider extracting cluster status checks and conditional rendering into a separate component.

The added cluster status checks and conditional rendering have increased the complexity of the LogsAndMetrics component. To improve readability and maintainability, consider extracting this logic into a separate component or custom hook. Here's a suggested refactor:

// Create a new component
const LogsAndMetricsContent = ({ environment, isClusterOnline, children }) => {
  if (environment.clusterName === '') {
    return (
      <NoLogsAndMetricsBanner
        title="Logs and Metrics Unavailable for Template Applications"
        description="Logs and metrics will become available once your app is associated with a cluster."
      />
    );
  }

  if (isClusterOnline === false) {
    return (
      <NoLogsAndMetricsBanner
        title="Logs and Metrics Unavailable for Offline Cluster-Based Applications"
        description="Logs and metrics will be accessible once the cluster is back online."
      />
    );
  }

  return children;
};

// Modify the main component
const LogsAndMetrics = () => {
  const { app, environment, account } = useOutletContext<IAppContext>();

  const { clustersMap: clusterStatus } = useClusterStatusV3({
    clusterName: environment.clusterName,
  });

  const isClusterOnline = findClusterStatusv3(
    clusterStatus[environment.clusterName]
  );

  // ... rest of your component logic ...

  return (
    <LogsAndMetricsContent environment={environment} isClusterOnline={isClusterOnline}>
      <div className="flex flex-col gap-6xl pt-6xl">
        {/* ... your existing JSX ... */}
      </div>
    </LogsAndMetricsContent>
  );
};

This refactoring maintains all the new functionality while reducing nesting in the main component. It separates the concerns of checking cluster status and rendering the appropriate content, making the code more modular and easier to understand at a glance.

clusterName: environment.clusterName,
});

const isClusterOnline = findClusterStatusv3(
clusterStatus[environment.clusterName]
);

type tData = {
metric: {
pod_name: string;
Expand Down Expand Up @@ -158,6 +169,24 @@ const LogsAndMetrics = () => {
timestampVisible: boolean;
}>('logs');

if (environment.clusterName === '') {
return (
<NoLogsAndMetricsBanner
title="Logs and Metrics Unavailable for Template Applications"
description="Logs and metrics will become available once your app is associated with a cluster."
/>
);
}

if (isClusterOnline === false) {
return (
<NoLogsAndMetricsBanner
title="Logs and Metrics Unavailable for Offline Cluster-Based Applications"
description="Logs and metrics will be accessible once the cluster is back online."
/>
);
}

return (
<div className="flex flex-col gap-6xl pt-6xl">
<div className="gap-6xl items-center flex-col grid sm:grid-cols-2 lg:grid-cols-2">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { useOutletContext } from '@remix-run/react';
import { ApexOptions } from 'apexcharts';
import axios from 'axios';
import Chart from '~/console/components/charts/charts-client';
import useDebounce from '~/lib/client/hooks/use-debounce';
import { useState } from 'react';
import { dayjs } from '~/components/molecule/dayjs';
import { parseValue } from '~/console/page-components/util';
import { ApexOptions } from 'apexcharts';
import Chart from '~/console/components/charts/charts-client';
import { findClusterStatusv3 } from '~/console/hooks/use-cluster-status';
import { useClusterStatusV3 } from '~/console/hooks/use-cluster-status-v3';
import { useDataState } from '~/console/page-components/common-state';
import { observeUrl } from '~/lib/configs/base-url.cjs';
import LogComp from '~/lib/client/components/logger';
import LogAction from '~/console/page-components/log-action';
import { NoLogsAndMetricsBanner } from '~/console/page-components/no-logs-banner';
import { parseValue } from '~/console/page-components/util';
import { parseName } from '~/console/server/r-utils/common';
import LogComp from '~/lib/client/components/logger';
import useDebounce from '~/lib/client/hooks/use-debounce';
import { observeUrl } from '~/lib/configs/base-url.cjs';
import { generatePlainColor } from '~/root/lib/utils/color-generator';
import { IManagedServiceContext } from '../_layout';

Expand All @@ -19,6 +22,13 @@ const LogsAndMetrics = () => {
useOutletContext<IManagedServiceContext>();

const { clusterName } = managedService;

const { clustersMap: clusterStatus } = useClusterStatusV3({
clusterName,
});

const isClusterOnline = findClusterStatusv3(clusterStatus[clusterName]);

type tData = {
metric: {
exported_pod: string;
Expand Down Expand Up @@ -160,6 +170,15 @@ const LogsAndMetrics = () => {
timestampVisible: boolean;
}>('logs');

if (isClusterOnline === false) {
return (
<NoLogsAndMetricsBanner
title="Logs and Metrics Unavailable for Offline Cluster-Based Services"
description="Logs and metrics will become available once the cluster is online again."
/>
);
}

return (
<div className="flex flex-col gap-6xl pt-6xl">
<div className="gap-6xl items-center flex-col grid sm:grid-cols-2 lg:grid-cols-2">
Expand Down
Loading