diff --git a/frontend/pages/status/index.js b/frontend/pages/status/index.js new file mode 100644 index 00000000..d9812f8e --- /dev/null +++ b/frontend/pages/status/index.js @@ -0,0 +1,263 @@ +import React, { useEffect, useState, useLayoutEffect } from "react"; +import { useStatus } from "../../src/core/hooks"; +import { + Heading, + Text, + Flex, + Spacer, + Stack, + chakra, + useMediaQuery, + useBreakpointValue, +} from "@chakra-ui/react"; +import { AWS_ASSETS_PATH } from "../../src/core/constants"; + +const assets = { + background720: `${AWS_ASSETS_PATH}/product-background-720x405.png`, + background1920: `${AWS_ASSETS_PATH}/product-background-720x405.png`, + background2880: `${AWS_ASSETS_PATH}/product-background-720x405.png`, + background3840: `${AWS_ASSETS_PATH}/product-background-720x405.png`, +}; + +const Status = () => { + const healthyStatusText = "Available"; + const downStatusText = "Unavailable"; + const healthyStatusColor = "green.900"; + const downStatusColor = "red.600"; + + const shortTimestamp = (rawTimestamp) => { + return rawTimestamp.replace(/^.+T/, "").replace(/\..+/, ""); + }; + + const { + apiServerStatusCache, + ethereumClusterServerStatusCache, + gethStatusCache, + crawlersStatusCache, + dbServerStatusCache, + latestBlockDBStatusCache, + } = useStatus(); + + const [background, setBackground] = useState("background720"); + const [backgroundLoaded720, setBackgroundLoaded720] = useState(false); + const [backgroundLoaded1920, setBackgroundLoaded1920] = useState(false); + const [backgroundLoaded2880, setBackgroundLoaded2880] = useState(false); + const [backgroundLoaded3840, setBackgroundLoaded3840] = useState(false); + + const [ + isLargerThan720px, + isLargerThan1920px, + isLargerThan2880px, + isLargerThan3840px, + ] = useMediaQuery([ + "(min-width: 720px)", + "(min-width: 1920px)", + "(min-width: 2880px)", + "(min-width: 3840px)", + ]); + + useEffect(() => { + assets[ + "background720" + ] = `${AWS_ASSETS_PATH}/product-background-720x405.png`; + assets[ + "background1920" + ] = `${AWS_ASSETS_PATH}/product-background-1920x1080.png`; + assets[ + "background2880" + ] = `${AWS_ASSETS_PATH}/product-background-2880x1620.png`; + assets[ + "background3840" + ] = `${AWS_ASSETS_PATH}/product-background-3840x2160.png`; + }, []); + + useLayoutEffect(() => { + if (backgroundLoaded3840) { + setBackground("background3840"); + } else if (backgroundLoaded2880) { + setBackground("background2880"); + } else if (backgroundLoaded1920) { + setBackground("background1920"); + } else { + setBackground("background720"); + } + }, [ + isLargerThan720px, + isLargerThan1920px, + isLargerThan2880px, + isLargerThan3840px, + backgroundLoaded720, + backgroundLoaded1920, + backgroundLoaded2880, + backgroundLoaded3840, + ]); + + useLayoutEffect(() => { + const imageLoader720 = new Image(); + imageLoader720.src = `${AWS_ASSETS_PATH}/product-background-720x405.png`; + imageLoader720.onload = () => { + setBackgroundLoaded720(true); + }; + }, []); + + useLayoutEffect(() => { + const imageLoader1920 = new Image(); + imageLoader1920.src = `${AWS_ASSETS_PATH}/product-background-1920x1080.png`; + imageLoader1920.onload = () => { + setBackgroundLoaded1920(true); + }; + }, []); + + useLayoutEffect(() => { + const imageLoader2880 = new Image(); + imageLoader2880.src = `${AWS_ASSETS_PATH}/product-background-2880x1620.png`; + imageLoader2880.onload = () => { + setBackgroundLoaded2880(true); + }; + }, []); + + useLayoutEffect(() => { + const imageLoader3840 = new Image(); + imageLoader3840.src = `${AWS_ASSETS_PATH}/product-background-3840x2160.png`; + imageLoader3840.onload = () => { + setBackgroundLoaded3840(true); + }; + }, []); + + const margin = useBreakpointValue({ + base: "1%", + sm: "2%", + md: "3%", + lg: "15%", + xl: "20%", + "2xl": "25%", + }); + + return ( + + + + {`Status page`} + + + + Backend server + + + {!apiServerStatusCache.isLoading && + apiServerStatusCache?.data?.status == "ok" + ? healthyStatusText + : downStatusText} + + +
+ + Crawlers server + + + {!ethereumClusterServerStatusCache.isLoading && + ethereumClusterServerStatusCache?.data + ? healthyStatusText + : downStatusText} + + + + Latest block in Geth + + + {!gethStatusCache.isLoading && + gethStatusCache?.data?.current_block + ? gethStatusCache.data.current_block + : 0} + + + + Txpool latest record ts + + + {!crawlersStatusCache.isLoading && + crawlersStatusCache?.data?.ethereum_txpool_timestamp + ? shortTimestamp( + crawlersStatusCache?.data?.ethereum_txpool_timestamp + ) + : downStatusText} + + + + Trending latest record ts + + + {!crawlersStatusCache.isLoading && + crawlersStatusCache?.data?.ethereum_trending_timestamp + ? shortTimestamp( + crawlersStatusCache?.data?.ethereum_trending_timestamp + ) + : downStatusText} + + +
+ + Database server + + + {!dbServerStatusCache.isLoading && + dbServerStatusCache?.data?.status == "ok" + ? healthyStatusText + : downStatusText} + + + + Latest block in Database + + + {!latestBlockDBStatusCache.isLoading && + latestBlockDBStatusCache?.data?.block_number + ? latestBlockDBStatusCache.data.block_number + : 0} + + +
+
+
+ ); +}; + +export default Status; diff --git a/frontend/sample.env b/frontend/sample.env index d2031fd0..ff12708b 100644 --- a/frontend/sample.env +++ b/frontend/sample.env @@ -1,3 +1,5 @@ export NEXT_PUBLIC_MIXPANEL_TOKEN="" export NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="" -export NEXT_PUBLIC_MOONSTREAM_API_URL=http://localhost:7481 \ No newline at end of file +export NEXT_PUBLIC_MOONSTREAM_API_URL="" +export NEXT_PUBLIC_MOONSTREAM_ETHEREUM_CLUSTER_URL="" +export NEXT_PUBLIC_MOONSTREAM_DB_URL="" diff --git a/frontend/src/core/hooks/index.js b/frontend/src/core/hooks/index.js index 0327ba50..f5fcb76a 100644 --- a/frontend/src/core/hooks/index.js +++ b/frontend/src/core/hooks/index.js @@ -14,6 +14,7 @@ export { default as useQuery } from "./useQuery"; export { default as useResetPassword } from "./useResetPassword"; export { default as useRouter } from "./useRouter"; export { default as useSignUp } from "./useSignUp"; +export { default as useStatus } from "./useStatus"; export { default as useStorage } from "./useStorage"; export { default as useStream } from "./useStream"; export { default as useStripe } from "./useStripe"; diff --git a/frontend/src/core/hooks/useStatus.js b/frontend/src/core/hooks/useStatus.js new file mode 100644 index 00000000..40908a09 --- /dev/null +++ b/frontend/src/core/hooks/useStatus.js @@ -0,0 +1,68 @@ +import { useQuery } from "react-query"; +import { queryCacheProps } from "./hookCommon"; +import { StatusService } from "../../core/services"; + +const useStatus = () => { + const getAPIServerStatus = async () => { + const response = await StatusService.apiServerStatus(); + return response.data; + }; + const getEthereumClusterServerStatus = async () => { + const response = await StatusService.ethereumClusterServerStatus(); + return response.data; + }; + const getGethStatus = async () => { + const response = await StatusService.gethStatus(); + return response.data; + }; + const getCrawlersStatus = async () => { + const response = await StatusService.crawlersStatus(); + return response.data; + }; + const getDBServerStatus = async () => { + const response = await StatusService.dbServerStatus(); + return response.data; + }; + const getLatestBlockDBStatus = async () => { + const response = await StatusService.latestBlockDBStatus(); + return response.data; + }; + + const apiServerStatusCache = useQuery("apiServer", getAPIServerStatus, { + ...queryCacheProps, + }); + const ethereumClusterServerStatusCache = useQuery( + "ethereumClusterServer", + getEthereumClusterServerStatus, + { + ...queryCacheProps, + } + ); + const gethStatusCache = useQuery("geth", getGethStatus, { + ...queryCacheProps, + }); + const crawlersStatusCache = useQuery("crawlers", getCrawlersStatus, { + ...queryCacheProps, + }); + const dbServerStatusCache = useQuery("dbServer", getDBServerStatus, { + ...queryCacheProps, + }); + const latestBlockDBStatusCache = useQuery( + "latestBlockDB", + getLatestBlockDBStatus, + { + ...queryCacheProps, + } + ); + + return { + apiServerStatusCache, + ethereumClusterServerStatusCache, + gethStatusCache, + crawlersStatusCache, + dbServerStatusCache, + latestBlockDBStatusCache, + }; +}; + +export default useStatus; diff --git a/frontend/src/core/services/index.js b/frontend/src/core/services/index.js index 6edb674a..ef4341d5 100644 --- a/frontend/src/core/services/index.js +++ b/frontend/src/core/services/index.js @@ -6,6 +6,7 @@ import * as GroupService from "./group.service"; import * as PreferencesService from "./preferences.service"; import * as HumbugService from "./humbug.service"; import * as InvitesService from "./invites.service"; +import * as StatusService from "./status.service"; import * as SubscriptionsService from "./subscriptions.service"; import * as StreamService from "./stream.service"; import * as TxInfoService from "./txinfo.service"; @@ -18,6 +19,7 @@ export { PreferencesService, HumbugService, InvitesService, + StatusService, SubscriptionsService, StreamService, TxInfoService, diff --git a/frontend/src/core/services/status.service.js b/frontend/src/core/services/status.service.js new file mode 100644 index 00000000..8666ccd7 --- /dev/null +++ b/frontend/src/core/services/status.service.js @@ -0,0 +1,48 @@ +import { http } from "../utils"; + +const API_URL = process.env.NEXT_PUBLIC_MOONSTREAM_API_URL; +const DB_URL = process.env.NEXT_PUBLIC_MOONSTREAM_DB_URL; +const ETHEREUM_CLUSTER_URL = + process.env.NEXT_PUBLIC_MOONSTREAM_ETHEREUM_CLUSTER_URL; + +export const apiServerStatus = () => { + return http({ + method: "GET", + url: `${API_URL}/ping`, + }); +}; + +export const ethereumClusterServerStatus = () => { + return http({ + method: "GET", + url: `${ETHEREUM_CLUSTER_URL}/ping`, + }); +}; + +export const gethStatus = () => { + return http({ + method: "GET", + url: `${ETHEREUM_CLUSTER_URL}/status`, + }); +}; + +export const crawlersStatus = () => { + return http({ + method: "GET", + url: `${API_URL}/status`, + }); +}; + +export const dbServerStatus = () => { + return http({ + method: "GET", + url: `${DB_URL}/ping`, + }); +}; + +export const latestBlockDBStatus = () => { + return http({ + method: "GET", + url: `${DB_URL}/block/latest`, + }); +};