Skip to content

Commit

Permalink
feat: show rate limit warning in services page when total RPS > 100 (S…
Browse files Browse the repository at this point in the history
…igNoz#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 <[email protected]>
  • Loading branch information
YounixM and makeavish authored Dec 21, 2023
1 parent 585d6e2 commit 2e0fdbb
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 18 deletions.
3 changes: 3 additions & 0 deletions frontend/public/locales/en-GB/services.json
Original file line number Diff line number Diff line change
@@ -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."
}
3 changes: 3 additions & 0 deletions frontend/public/locales/en/services.json
Original file line number Diff line number Diff line change
@@ -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."
}
2 changes: 2 additions & 0 deletions frontend/src/constants/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const MAX_RPS_LIMIT = 100;
export { MAX_RPS_LIMIT };
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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: [
Expand Down Expand Up @@ -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 (
<ResizeTable
columns={tableColumns}
loading={isLoading}
dataSource={services}
rowKey="serviceName"
/>
<>
{RPS > MAX_RPS_LIMIT && (
<Flex justify="center">
<Typography.Title level={5} type="warning" style={{ marginTop: 0 }}>
<WarningFilled /> {getText('rps_over_100')}
</Typography.Title>
</Flex>
)}

<ResourceAttributesFilter />

<ResizeTable
columns={tableColumns}
loading={isLoading}
dataSource={services}
rowKey="serviceName"
/>
</>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 (
<ResizeTable
columns={tableColumns}
loading={loading}
dataSource={services}
rowKey="serviceName"
/>
<>
{RPS > MAX_RPS_LIMIT && (
<Flex justify="flex-end">
<Typography.Text type="warning" style={{ marginTop: 0 }}>
<WarningFilled /> {getText('rps_over_100')}
</Typography.Text>
</Flex>
)}

<ResourceAttributesFilter />

<ResizeTable
columns={tableColumns}
loading={loading}
dataSource={services}
rowKey="serviceName"
/>
</>
);
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/container/ServiceApplication/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function Services(): JSX.Element {

return (
<ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
<Container>
<Container style={{ marginTop: 0 }}>
{isSpanMetricEnabled ? <ServiceMetrics /> : <ServiceTraces />}
</Container>
</ErrorBoundary>
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/hooks/analytics/useAnalytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import { extractDomain } from 'utils/app';
const useAnalytics = (): any => {
const { user } = useSelector<AppState, AppReducer>((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,
});
}
};

Expand All @@ -22,6 +25,9 @@ const useAnalytics = (): any => {
groupId: extractDomain(user?.email),
},
};

const updatedPropertes = { ...properties };
updatedPropertes.userId = user.email;
window.analytics.track(eventName, properties, context);
}
};
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/pages/Services/index.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -11,7 +10,6 @@ function Metrics(): JSX.Element {
<Space direction="vertical" style={{ width: '100%' }}>
<ReleaseNote path={location.pathname} />

<ResourceAttributesFilter />
<ServicesApplication />
</Space>
);
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/utils/services.ts
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 2e0fdbb

Please sign in to comment.