import "@mantine/core/styles.css"; import "@mantine/code-highlight/styles.css"; import "@mantine/notifications/styles.css"; import "@mantine/dates/styles.css"; import classes from "./App.module.css"; import PrometheusLogo from "./images/prometheus-logo.svg"; import { AppShell, Box, Burger, Button, Group, MantineProvider, Menu, Skeleton, Text, createTheme, rem, } from "@mantine/core"; import { useDisclosure } from "@mantine/hooks"; import { IconBellFilled, IconChevronDown, IconChevronRight, IconCloudDataConnection, IconDatabase, IconFlag, IconHeartRateMonitor, IconInfoCircle, IconSearch, IconServer, IconServerCog, } from "@tabler/icons-react"; import { BrowserRouter, Link, NavLink, Navigate, Route, Routes, } from "react-router-dom"; import { IconTable } from "@tabler/icons-react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import QueryPage from "./pages/query/QueryPage"; import AlertsPage from "./pages/AlertsPage"; import RulesPage from "./pages/RulesPage"; import TargetsPage from "./pages/targets/TargetsPage"; import StatusPage from "./pages/StatusPage"; import TSDBStatusPage from "./pages/TSDBStatusPage"; import FlagsPage from "./pages/FlagsPage"; import ConfigPage from "./pages/ConfigPage"; import AgentPage from "./pages/AgentPage"; import { Suspense } from "react"; import ErrorBoundary from "./components/ErrorBoundary"; import { ThemeSelector } from "./components/ThemeSelector"; import { Notifications } from "@mantine/notifications"; import { useAppDispatch } from "./state/hooks"; import { updateSettings, useSettings } from "./state/settingsSlice"; import SettingsMenu from "./components/SettingsMenu"; import ReadinessWrapper from "./components/ReadinessWrapper"; import { QueryParamProvider } from "use-query-params"; import { ReactRouter6Adapter } from "use-query-params/adapters/react-router-6"; import ServiceDiscoveryPage from "./pages/service-discovery/ServiceDiscoveryPage"; const queryClient = new QueryClient(); const navIconStyle = { width: rem(16), height: rem(16) }; const mainNavPages = [ { title: "Query", path: "/query", icon: , element: , inAgentMode: false, }, { title: "Alerts", path: "/alerts", icon: , element: , inAgentMode: false, }, ]; const monitoringStatusPages = [ { title: "Target health", path: "/targets", icon: , element: , inAgentMode: true, }, { title: "Rule health", path: "/rules", icon: , element: , inAgentMode: false, }, { title: "Service discovery", path: "/service-discovery", icon: , element: , inAgentMode: true, }, ]; const serverStatusPages = [ { title: "Runtime & build information", path: "/status", icon: , element: , inAgentMode: true, }, { title: "TSDB status", path: "/tsdb-status", icon: , element: , inAgentMode: false, }, { title: "Command-line flags", path: "/flags", icon: , element: , inAgentMode: true, }, { title: "Configuration", path: "/config", icon: , element: , inAgentMode: true, }, ]; const allStatusPages = [...monitoringStatusPages, ...serverStatusPages]; const theme = createTheme({ colors: { "codebox-bg": [ "#f5f5f5", "#e7e7e7", "#cdcdcd", "#b2b2b2", "#9a9a9a", "#8b8b8b", "#848484", "#717171", "#656565", "#575757", ], }, }); // This dynamically/generically determines the pathPrefix by stripping the first known // endpoint suffix from the window location path. It works out of the box for both direct // hosting and reverse proxy deployments with no additional configurations required. const getPathPrefix = (path: string) => { if (path.endsWith("/")) { path = path.slice(0, -1); } const pagePaths = [ ...mainNavPages, ...allStatusPages, { path: "/agent" }, ].map((p) => p.path); const pagePath = pagePaths.find((p) => path.endsWith(p)); return path.slice(0, path.length - (pagePath || "").length); }; const navLinkXPadding = "md"; function App() { const [opened, { toggle }] = useDisclosure(); const pathPrefix = getPathPrefix(window.location.pathname); const dispatch = useAppDispatch(); dispatch(updateSettings({ pathPrefix })); const { agentMode } = useSettings(); const navLinks = ( <> {mainNavPages .filter((p) => !agentMode || p.inAgentMode) .map((p) => ( ))} {allStatusPages .filter((p) => !agentMode || p.inAgentMode) .map((p) => ( } /> ))} } /> Monitoring status {monitoringStatusPages .filter((p) => !agentMode || p.inAgentMode) .map((p) => ( {p.title} ))} Server status {serverStatusPages .filter((p) => !agentMode || p.inAgentMode) .map((p) => ( {p.title} ))} {/* */} ); return ( Prometheus{agentMode && " Agent"} {navLinks} {navLinks} {Array.from(Array(10), (_, i) => ( ))} } > } /> {agentMode ? ( } /> ) : ( <> } /> } /> )} {allStatusPages.map((p) => ( {p.element} } /> ))} {/* */} ); } export default App;