diff --git a/keep-ui/app/(health)/health/check.tsx b/keep-ui/app/(health)/health/check.tsx deleted file mode 100644 index dc41d688e8..0000000000 --- a/keep-ui/app/(health)/health/check.tsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client"; - -import ProvidersTiles from "@/app/(keep)/providers/providers-tiles"; -import React, { useEffect, useState } from "react"; -import { defaultProvider, Provider } from "@/shared/api/providers"; -import { useProvidersWithHealthCheck } from "@/utils/hooks/useProviders"; -import Loading from "@/app/(keep)/loading"; -import HealthPageBanner from "@/components/banners/health-page-banner"; - -const useFetchProviders = () => { - const [providers, setProviders] = useState([]); - const { data, error, mutate } = useProvidersWithHealthCheck(); - - if (error) { - throw error; - } - - const isLocalhost: boolean = true; - - useEffect(() => { - if (data) { - const fetchedProviders = data.providers - .filter((provider: Provider) => { - return provider.health; - }) - .map((provider) => ({ - ...defaultProvider, - ...provider, - id: provider.type, - installed: provider.installed ?? false, - health: provider.health, - })); - - setProviders(fetchedProviders); - } - }, [data]); - - return { - providers, - error, - isLocalhost, - mutate, - }; -}; - -export default function ProviderHealthPage() { - const { providers, isLocalhost, mutate } = useFetchProviders(); - - if (!providers || providers.length <= 0) { - return ; - } - - return ( - <> - - - - ); -} diff --git a/keep-ui/app/(health)/health/modal.tsx b/keep-ui/app/(health)/health/modal.tsx deleted file mode 100644 index be3f6a2851..0000000000 --- a/keep-ui/app/(health)/health/modal.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import React from "react"; -import Modal from "@/components/ui/Modal"; -import { - Badge, - BarChart, - Button, - Card, - DonutChart, - Subtitle, - Title, -} from "@tremor/react"; -import { CheckCircle2Icon } from "lucide-react"; - -interface ProviderHealthResultsModalProps { - handleClose: () => void; - isOpen: boolean; - healthResults: any; -} - -const ProviderHealthResultsModal = ({ - handleClose, - isOpen, - healthResults, -}: ProviderHealthResultsModalProps) => { - const handleModalClose = () => { - handleClose(); - }; - - return ( - -
-
- - Spammy Alerts - {healthResults?.spammy?.length ? ( - <> - - Sorry to say, but looks like your alerts are spammy - - ) : ( - <> -
- -
- Everything is ok - - )} -
- - Rules Quality - {healthResults?.rules?.unused ? ( - <> - - - {healthResults?.rules.unused} of your{" "} - {healthResults.rules.used + healthResults.rules.unused} alert - rules are not in use - - - ) : ( - <> -
- -
- Everything is ok - - )} -
- - Actionable -
- -
- Everything is ok -
- - - Topology coverage - {healthResults?.topology?.uncovered.length ? ( - <> - - - Not of your services are covered. Alerts are missing for: - {healthResults?.topology?.uncovered.map((service: any) => { - return ( - - {service.display_name - ? service.display_name - : service.service} - - ); - })} - - - ) : ( - <> -
- -
- Everything is ok - - )} -
-
- - - Want to improve your observability? - - -
-
- ); -}; - -export default ProviderHealthResultsModal; diff --git a/keep-ui/app/(health)/health/opengraph-image.png b/keep-ui/app/(health)/health/opengraph-image.png deleted file mode 100644 index 6ca6f2de82..0000000000 Binary files a/keep-ui/app/(health)/health/opengraph-image.png and /dev/null differ diff --git a/keep-ui/app/(health)/health/page.tsx b/keep-ui/app/(health)/health/page.tsx deleted file mode 100644 index 7ba3f47ca8..0000000000 --- a/keep-ui/app/(health)/health/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Metadata } from "next"; -import ProviderHealthPage from "./check"; - -export const metadata: Metadata = { - title: "Keep – Check your alerts quality", - description: - "Easily check the configuration quality of your observability tools such as Datadog, Grafana, Prometheus, and more without the need to sign up.", -}; - -export default ProviderHealthPage; - diff --git a/keep-ui/app/(health)/layout.tsx b/keep-ui/app/(health)/layout.tsx deleted file mode 100644 index 370f8b70ea..0000000000 --- a/keep-ui/app/(health)/layout.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React, { ReactNode } from "react"; -import { NextAuthProvider } from "../auth-provider"; -import { Mulish } from "next/font/google"; -import { ToastContainer } from "react-toastify"; -import { getConfig } from "@/shared/lib/server/getConfig"; -import { ConfigProvider } from "../config-provider"; -import { PHProvider } from "../posthog-provider"; -import ReadOnlyBanner from "@/components/banners/read-only-banner"; -import { auth } from "@/auth"; -import { ThemeScript, WatchUpdateTheme } from "@/shared/ui"; -import "@/app/globals.css"; -import "react-toastify/dist/ReactToastify.css"; -import { PostHogPageView } from "@/shared/ui/PostHogPageView"; - -// If loading a variable font, you don't need to specify the font weight -const mulish = Mulish({ - subsets: ["latin"], - display: "swap", -}); - -type RootLayoutProps = { - children: ReactNode; -}; - -export default async function RootLayout({ children }: RootLayoutProps) { - const config = getConfig(); - const session = await auth(); - - return ( - - - {/* ThemeScript must be the first thing to avoid flickering */} - - - - - {/* @ts-ignore-error Server Component */} - - {/* https://discord.com/channels/752553802359505017/1068089513253019688/1117731746922893333 */} -
- {/* Add the banner here, before the navbar */} - {config.READ_ONLY && } -
{children}
- {/** footer */} - {process.env.GIT_COMMIT_HASH && - process.env.SHOW_BUILD_INFO !== "false" && ( -
-
- Version: {process.env.KEEP_VERSION} | Build:{" "} - {process.env.GIT_COMMIT_HASH.slice(0, 6)} -
-
- )} - -
-
-
-
- - - - ); -} diff --git a/keep-ui/app/(keep)/providers/provider-form.tsx b/keep-ui/app/(keep)/providers/provider-form.tsx index 2992131247..1d3cc3b1c0 100644 --- a/keep-ui/app/(keep)/providers/provider-form.tsx +++ b/keep-ui/app/(keep)/providers/provider-form.tsx @@ -72,47 +72,29 @@ import { UpdateIcon, } from "@radix-ui/react-icons"; -type HealthResults = { - spammy: any[]; - rules: { - total: number; - used: number; - unused: number; - }; - topology: { - covered: any[]; - uncovered: any[]; - }; -}; - type ProviderFormProps = { provider: Provider; onConnectChange?: ( isConnecting: boolean, isConnected: boolean, - healthResults: HealthResults | null + installedProvider?: Provider | null ) => void; closeModal: () => void; isProviderNameDisabled?: boolean; installedProvidersMode: boolean; isLocalhost?: boolean; - isHealthCheck?: boolean; mutate: () => void; }; -function getInitialFormValues(provider: Provider, isHealthCheck?: boolean) { +function getInitialFormValues(provider: Provider) { const initialValues: ProviderFormData = { provider_id: provider.id, - install_webhook: !isHealthCheck - ? (provider.can_setup_webhook ?? false) - : false, + install_webhook: provider.can_setup_webhook ?? false, pulling_enabled: provider.pulling_enabled, }; Object.assign(initialValues, { - provider_name: - provider.details?.name || - (isHealthCheck ? `${provider.id} health check` : undefined), + provider_name: provider.details?.name || undefined, ...provider.details?.authentication, }); @@ -141,13 +123,12 @@ const ProviderForm = ({ isProviderNameDisabled, installedProvidersMode, isLocalhost, - isHealthCheck, mutate, }: ProviderFormProps) => { console.log("Loading the ProviderForm component"); const searchParams = useSearchParams(); const [formValues, setFormValues] = useState(() => - getInitialFormValues(provider, isHealthCheck) + getInitialFormValues(provider) ); const [formErrors, setFormErrors] = useState(null); const [inputErrors, setInputErrors] = useState({}); @@ -436,13 +417,12 @@ const ProviderForm = ({ if (!validate()) return; setIsLoading(true); onConnectChange?.(true, false, null); - submit(isHealthCheck ? `/providers/healthcheck` : `/providers/install`) + submit(`/providers/install`) .then(async (data) => { console.log("Connect Result:", data); setIsLoading(false); - onConnectChange?.(false, true, data); + onConnectChange?.(false, true, data as Provider); if ( - !isHealthCheck && formValues.install_webhook && provider.can_setup_webhook && !isLocalhost @@ -487,7 +467,7 @@ const ProviderForm = ({ config={providerNameFieldConfig} value={(formValues["provider_name"] ?? "").toString()} error={inputErrors["provider_name"]} - disabled={(isProviderNameDisabled || isHealthCheck) ?? false} + disabled={isProviderNameDisabled ?? false} title={ isProviderNameDisabled ? "This field is disabled because it is pre-filled from the workflow." @@ -551,9 +531,7 @@ const ProviderForm = ({ )}
- {!isHealthCheck && - provider.can_setup_webhook && - !installedProvidersMode && ( + {provider.can_setup_webhook && !installedProvidersMode && (
)} - {!isHealthCheck && - !provider.can_setup_webhook && + {!provider.can_setup_webhook && !installedProvidersMode && provider.pulling_available && (
- {!isHealthCheck && - provider.can_setup_webhook && - installedProvidersMode && ( + {provider.can_setup_webhook && installedProvidersMode && ( <>
- {isHealthCheck ? `Check health` : `Connect`} + Connect )}
diff --git a/keep-ui/app/(keep)/providers/providers-tiles.tsx b/keep-ui/app/(keep)/providers/providers-tiles.tsx index c80c6a48ce..f2d9728319 100644 --- a/keep-ui/app/(keep)/providers/providers-tiles.tsx +++ b/keep-ui/app/(keep)/providers/providers-tiles.tsx @@ -7,7 +7,6 @@ import ProviderTile from "./provider-tile"; import { useSearchParams } from "next/navigation"; import { QuestionMarkCircleIcon } from "@heroicons/react/24/outline"; import { Tooltip } from "@/shared/ui"; -import ProviderHealthResultsModal from "@/app/(health)/health/modal"; import { Drawer } from "@/shared/ui/Drawer"; const ProvidersTiles = ({ @@ -16,7 +15,6 @@ const ProvidersTiles = ({ installedProvidersMode = false, linkedProvidersMode = false, isLocalhost = false, - isHealthCheck = false, mutate, }: { title: string; @@ -24,13 +22,10 @@ const ProvidersTiles = ({ installedProvidersMode?: boolean; linkedProvidersMode?: boolean; isLocalhost?: boolean; - isHealthCheck?: boolean; mutate: () => void; }) => { const searchParams = useSearchParams(); const [openPanel, setOpenPanel] = useState(false); - const [openHealthModal, setOpenHealthModal] = useState(false); - const [healthResults, setHealthResults] = useState({}); const [selectedProvider, setSelectedProvider] = useState( null ); @@ -64,24 +59,8 @@ const ProvidersTiles = ({ setSelectedProvider(null); }; - const handleShowHealthModal = () => { - setOpenHealthModal(true); - }; - - const handleCloseHealthModal = () => { - setOpenHealthModal(false); - }; - - const handleConnecting = ( - isConnecting: boolean, - isConnected: boolean, - healthResults: any - ) => { + const handleConnecting = (isConnecting: boolean, isConnected: boolean) => { if (isConnected) handleCloseModal(); - if (isConnected && isHealthCheck) { - setHealthResults(healthResults); - handleShowHealthModal(); - } }; const sortedProviders = providers @@ -141,17 +120,10 @@ const ProvidersTiles = ({ installedProvidersMode={installedProvidersMode} isProviderNameDisabled={installedProvidersMode} isLocalhost={isLocalhost} - isHealthCheck={isHealthCheck} mutate={mutate} /> )} - -
); }; diff --git a/keep-ui/components/banners/health-page-banner.tsx b/keep-ui/components/banners/health-page-banner.tsx deleted file mode 100644 index 7c099885e7..0000000000 --- a/keep-ui/components/banners/health-page-banner.tsx +++ /dev/null @@ -1,16 +0,0 @@ -"use client"; -import React from "react"; -import KeepBanner from "@/components/banners/BannerBase"; - -const HealthPageBanner = () => { - return - Easily check the configuration quality of your observability tools without the need to sign up. -
Your credentials will not be stored at any point. - } - newWindow={false} - /> -}; - -export default HealthPageBanner; diff --git a/keep-ui/features/workflows/builder/ui/Editor/StepEditor.tsx b/keep-ui/features/workflows/builder/ui/Editor/StepEditor.tsx index 6067bb69fb..bca94a59c3 100644 --- a/keep-ui/features/workflows/builder/ui/Editor/StepEditor.tsx +++ b/keep-ui/features/workflows/builder/ui/Editor/StepEditor.tsx @@ -203,7 +203,6 @@ function InstallProviderButton({ closeModal={closeModal} isProviderNameDisabled={false} isLocalhost={false} - isHealthCheck={false} /> diff --git a/keep-ui/middleware.ts b/keep-ui/middleware.ts index bdd5ffd7b1..f18179b1a5 100644 --- a/keep-ui/middleware.ts +++ b/keep-ui/middleware.ts @@ -51,7 +51,6 @@ export const middleware = auth(async (request) => { if ( !isAuthenticated && !pathname.startsWith("/signin") && - !pathname.startsWith("/health") && !pathname.startsWith("/error") && !pathname.startsWith("/api/healthcheck") ) { diff --git a/keep-ui/utils/hooks/useProviders.ts b/keep-ui/utils/hooks/useProviders.ts index c9e6986851..4ff5cf250a 100644 --- a/keep-ui/utils/hooks/useProviders.ts +++ b/keep-ui/utils/hooks/useProviders.ts @@ -14,15 +14,3 @@ export const useProviders = ( options ); }; - -export const useProvidersWithHealthCheck = ( - options: SWRConfiguration = { revalidateOnFocus: false } -) => { - const api = useApi(); - - return useSWRImmutable( - api.isReady() ? "/providers/healthcheck" : null, - (url) => api.get(url), - options - ); -}; diff --git a/keep/api/routes/providers.py b/keep/api/routes/providers.py index 6dff2ce1ea..2952106ccd 100644 --- a/keep/api/routes/providers.py +++ b/keep/api/routes/providers.py @@ -4,7 +4,7 @@ import random import time import uuid -from typing import Any, Callable, Dict, Optional +from typing import Callable, Optional from fastapi import APIRouter, Body, Depends, HTTPException, Request from fastapi.encoders import jsonable_encoder @@ -833,43 +833,6 @@ def get_webhook_settings( ) -@router.post("/healthcheck", description="Run healthcheck on a provider") -async def healthcheck_provider( - request: Request, -) -> Dict[str, Any]: - try: - provider_info = await request.json() - except Exception: - form_data = await request.form() - provider_info = dict(form_data) - - if not provider_info: - raise HTTPException(status_code=400, detail="No valid data provided") - - try: - provider_id = provider_info.pop("provider_id") - provider_type = provider_info.pop("provider_type", None) or provider_id - provider_name = f"{provider_type} healthcheck" - except KeyError as e: - raise HTTPException( - status_code=400, detail=f"Missing required field: {e.args[0]}" - ) - - for key, value in provider_info.items(): - if isinstance(value, UploadFile): - provider_info[key] = value.file.read().decode() - - provider = ProvidersService.prepare_provider( - provider_id, - provider_name, - provider_type, - provider_info, - ) - - result = provider.get_health_report() - return result - - @router.get("/healthcheck", description="Get all providers for healthcheck") def get_healthcheck_providers(): logger.info("Getting all providers for healthcheck") diff --git a/pyproject.toml b/pyproject.toml index 7188003d6c..86853c8ba4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.54.1" +version = "0.54.2" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] packages = [{include = "keep"}]