From 2e0fdbb498a530d34c2649453652d82be6066c14 Mon Sep 17 00:00:00 2001 From: Yunus M Date: Fri, 22 Dec 2023 00:51:37 +0530 Subject: [PATCH] feat: show rate limit warning in services page when total RPS > 100 (#4266) * feat: show rate limit warning in services page when total rps > 100 * feat: update message * feat: rate limit message should be shown only to cloud users on trail --------- Co-authored-by: Vishal Sharma --- frontend/public/locales/en-GB/services.json | 3 ++ frontend/public/locales/en/services.json | 3 ++ frontend/src/constants/global.ts | 2 + .../ServiceMetrics/ServiceMetricTable.tsx | 50 ++++++++++++++++--- .../ServiceTraces/ServiceTracesTable.tsx | 49 +++++++++++++++--- .../container/ServiceApplication/index.tsx | 2 +- frontend/src/hooks/analytics/useAnalytics.tsx | 8 ++- frontend/src/pages/Services/index.tsx | 2 - frontend/src/utils/services.ts | 4 ++ 9 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 frontend/public/locales/en-GB/services.json create mode 100644 frontend/public/locales/en/services.json create mode 100644 frontend/src/constants/global.ts create mode 100644 frontend/src/utils/services.ts diff --git a/frontend/public/locales/en-GB/services.json b/frontend/public/locales/en-GB/services.json new file mode 100644 index 0000000000..4c49847031 --- /dev/null +++ b/frontend/public/locales/en-GB/services.json @@ -0,0 +1,3 @@ +{ + "rps_over_100": "You are sending data at more than 100 RPS, your ingestion may be rate limited. Please reach out to us via Intercom support." +} diff --git a/frontend/public/locales/en/services.json b/frontend/public/locales/en/services.json new file mode 100644 index 0000000000..4c49847031 --- /dev/null +++ b/frontend/public/locales/en/services.json @@ -0,0 +1,3 @@ +{ + "rps_over_100": "You are sending data at more than 100 RPS, your ingestion may be rate limited. Please reach out to us via Intercom support." +} diff --git a/frontend/src/constants/global.ts b/frontend/src/constants/global.ts new file mode 100644 index 0000000000..d2a455ea57 --- /dev/null +++ b/frontend/src/constants/global.ts @@ -0,0 +1,2 @@ +const MAX_RPS_LIMIT = 100; +export { MAX_RPS_LIMIT }; diff --git a/frontend/src/container/ServiceApplication/ServiceMetrics/ServiceMetricTable.tsx b/frontend/src/container/ServiceApplication/ServiceMetrics/ServiceMetricTable.tsx index 154cc4ab11..4fee7aeb3a 100644 --- a/frontend/src/container/ServiceApplication/ServiceMetrics/ServiceMetricTable.tsx +++ b/frontend/src/container/ServiceApplication/ServiceMetrics/ServiceMetricTable.tsx @@ -1,12 +1,20 @@ +import { WarningFilled } from '@ant-design/icons'; +import { Flex, Typography } from 'antd'; import { ResizeTable } from 'components/ResizeTable'; +import { MAX_RPS_LIMIT } from 'constants/global'; +import ResourceAttributesFilter from 'container/ResourceAttributesFilter'; import { useGetQueriesRange } from 'hooks/queryBuilder/useGetQueriesRange'; +import useLicense from 'hooks/useLicense'; import { useNotifications } from 'hooks/useNotifications'; -import { useMemo } from 'react'; +import { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { useLocation } from 'react-router-dom'; import { AppState } from 'store/reducers'; import { ServicesList } from 'types/api/metrics/getService'; import { GlobalReducer } from 'types/reducer/globalTime'; +import { isCloudUser } from 'utils/app'; +import { getTotalRPS } from 'utils/services'; import { getColumns } from '../Columns/ServiceColumn'; import { ServiceMetricsTableProps } from '../types'; @@ -22,6 +30,10 @@ function ServiceMetricTable({ >((state) => state.globalTime); const { notifications } = useNotifications(); + const { t: getText } = useTranslation(['services']); + + const { data: licenseData, isFetching } = useLicense(); + const isCloudUserVal = isCloudUser(); const queries = useGetQueriesRange(queryRangeRequestData, { queryKey: [ @@ -53,14 +65,38 @@ function ServiceMetricTable({ const { search } = useLocation(); const tableColumns = useMemo(() => getColumns(search, true), [search]); + const [RPS, setRPS] = useState(0); + + useEffect(() => { + if (!isFetching && licenseData?.payload?.onTrial && isCloudUserVal) { + if (services.length > 0) { + const rps = getTotalRPS(services); + setRPS(rps); + } else { + setRPS(0); + } + } + }, [services, licenseData, isFetching, isCloudUserVal]); return ( - + <> + {RPS > MAX_RPS_LIMIT && ( + + + {getText('rps_over_100')} + + + )} + + + + + ); } diff --git a/frontend/src/container/ServiceApplication/ServiceTraces/ServiceTracesTable.tsx b/frontend/src/container/ServiceApplication/ServiceTraces/ServiceTracesTable.tsx index b5c4f6e7a1..3b21acba6e 100644 --- a/frontend/src/container/ServiceApplication/ServiceTraces/ServiceTracesTable.tsx +++ b/frontend/src/container/ServiceApplication/ServiceTraces/ServiceTracesTable.tsx @@ -1,6 +1,14 @@ +import { WarningFilled } from '@ant-design/icons'; +import { Flex, Typography } from 'antd'; import { ResizeTable } from 'components/ResizeTable'; -import { useMemo } from 'react'; +import { MAX_RPS_LIMIT } from 'constants/global'; +import ResourceAttributesFilter from 'container/ResourceAttributesFilter'; +import useLicense from 'hooks/useLicense'; +import { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useLocation } from 'react-router-dom'; +import { isCloudUser } from 'utils/app'; +import { getTotalRPS } from 'utils/services'; import { getColumns } from '../Columns/ServiceColumn'; import ServiceTableProps from '../types'; @@ -10,16 +18,43 @@ function ServiceTraceTable({ loading, }: ServiceTableProps): JSX.Element { const { search } = useLocation(); + const [RPS, setRPS] = useState(0); + const { t: getText } = useTranslation(['services']); + const { data: licenseData, isFetching } = useLicense(); + const isCloudUserVal = isCloudUser(); const tableColumns = useMemo(() => getColumns(search, false), [search]); + useEffect(() => { + if (!isFetching && licenseData?.payload?.onTrial && isCloudUserVal) { + if (services.length > 0) { + const rps = getTotalRPS(services); + setRPS(rps); + } else { + setRPS(0); + } + } + }, [services, licenseData, isFetching, isCloudUserVal]); + return ( - + <> + {RPS > MAX_RPS_LIMIT && ( + + + {getText('rps_over_100')} + + + )} + + + + + ); } diff --git a/frontend/src/container/ServiceApplication/index.tsx b/frontend/src/container/ServiceApplication/index.tsx index 9a5157061d..b7b22018e1 100644 --- a/frontend/src/container/ServiceApplication/index.tsx +++ b/frontend/src/container/ServiceApplication/index.tsx @@ -13,7 +13,7 @@ function Services(): JSX.Element { return ( - + {isSpanMetricEnabled ? : } diff --git a/frontend/src/hooks/analytics/useAnalytics.tsx b/frontend/src/hooks/analytics/useAnalytics.tsx index 9a2d9765bc..23d535063d 100644 --- a/frontend/src/hooks/analytics/useAnalytics.tsx +++ b/frontend/src/hooks/analytics/useAnalytics.tsx @@ -6,9 +6,12 @@ import { extractDomain } from 'utils/app'; const useAnalytics = (): any => { const { user } = useSelector((state) => state.app); + // Segment Page View - analytics.page([category], [name], [properties], [options], [callback]); const trackPageView = (pageName: string): void => { if (user && user.email) { - window.analytics.page(pageName); + window.analytics.page(null, pageName, { + userId: user.email, + }); } }; @@ -22,6 +25,9 @@ const useAnalytics = (): any => { groupId: extractDomain(user?.email), }, }; + + const updatedPropertes = { ...properties }; + updatedPropertes.userId = user.email; window.analytics.track(eventName, properties, context); } }; diff --git a/frontend/src/pages/Services/index.tsx b/frontend/src/pages/Services/index.tsx index 7d1ef713d6..2c2b1f5c17 100644 --- a/frontend/src/pages/Services/index.tsx +++ b/frontend/src/pages/Services/index.tsx @@ -1,6 +1,5 @@ import { Space } from 'antd'; import ReleaseNote from 'components/ReleaseNote'; -import ResourceAttributesFilter from 'container/ResourceAttributesFilter'; import ServicesApplication from 'container/ServiceApplication'; import { useLocation } from 'react-router-dom'; @@ -11,7 +10,6 @@ function Metrics(): JSX.Element { - ); diff --git a/frontend/src/utils/services.ts b/frontend/src/utils/services.ts new file mode 100644 index 0000000000..a35c5af1db --- /dev/null +++ b/frontend/src/utils/services.ts @@ -0,0 +1,4 @@ +import { ServicesList } from 'types/api/metrics/getService'; + +export const getTotalRPS = (services: ServicesList[]): number => + services.reduce((accumulator, service) => accumulator + service.callRate, 0);