diff --git a/web/oss/src/components/pages/observability/components/EmptyObservability/index.tsx b/web/oss/src/components/pages/observability/components/EmptyObservability/index.tsx index 902bdf92a1..ac16fae612 100644 --- a/web/oss/src/components/pages/observability/components/EmptyObservability/index.tsx +++ b/web/oss/src/components/pages/observability/components/EmptyObservability/index.tsx @@ -1,25 +1,66 @@ import {memo} from "react" -import {BranchesOutlined} from "@ant-design/icons" +import {BranchesOutlined, StopOutlined} from "@ant-design/icons" import {Typography} from "antd" import {useSetAtom} from "jotai" +import Link from "next/link" import EmptyState from "@/oss/components/EmptyState" import {EMPTY_STATE_VIDEOS} from "@/oss/components/EmptyState/videos" import EmptyComponent from "@/oss/components/Placeholders/EmptyComponent" +import useURL from "@/oss/hooks/useURL" import {setOnboardingWidgetActivationAtom} from "@/oss/lib/onboarding" interface EmptyObservabilityProps { showOnboarding?: boolean + rateLimited?: boolean + rateLimitMessage?: string } -const EmptyObservability = ({showOnboarding = true}: EmptyObservabilityProps) => { +const EmptyObservability = ({ + showOnboarding = true, + rateLimited = false, + rateLimitMessage, +}: EmptyObservabilityProps) => { const setOnboardingWidgetActivation = useSetAtom(setOnboardingWidgetActivationAtom) + const {projectURL} = useURL() + const subscriptionHref = projectURL + ? `${projectURL}/settings?tab=billing&upgrade=true` + : undefined const handleSetupTracing = () => { setOnboardingWidgetActivation("tracing-snippet") } + if (rateLimited) { + return ( +
+ } + description={ +
+ + Rate limit reached + + + {rateLimitMessage || + "You have reached your monthly quota limit. Please try again later or upgrade your plan."} + {subscriptionHref && ( + <> + {" "} + + Upgrade + + + )} + +
+ } + /> +
+ ) + } + if (!showOnboarding) { return (
diff --git a/web/oss/src/components/pages/observability/components/ObservabilityTable/index.tsx b/web/oss/src/components/pages/observability/components/ObservabilityTable/index.tsx index c8ffa73b42..3ad9f25a52 100644 --- a/web/oss/src/components/pages/observability/components/ObservabilityTable/index.tsx +++ b/web/oss/src/components/pages/observability/components/ObservabilityTable/index.tsx @@ -75,6 +75,8 @@ const ObservabilityTable = () => { isFetchingMore, autoRefresh, fetchAnnotations, + isRateLimited, + rateLimitMessage, } = useObservability() const setTraceDrawerActiveSpan = useSetAtom(setTraceDrawerActiveSpanAtom) const isNewUser = useAtomValue(isNewUserAtom) @@ -186,7 +188,7 @@ const ObservabilityTable = () => { } const showTableLoading = isLoading && traces.length === 0 - const isEmptyState = traces.length === 0 && !isLoading + const isEmptyState = traces.length === 0 && !isLoading && !isRateLimited const showOnboarding = isNewUser && !hasReceivedTraces useEffect(() => { @@ -226,7 +228,9 @@ const ObservabilityTable = () => { refreshTrigger={refreshTrigger} /> - {isEmptyState ? ( + {isRateLimited ? ( + + ) : isEmptyState ? ( ) : (
diff --git a/web/oss/src/state/newObservability/hooks/index.ts b/web/oss/src/state/newObservability/hooks/index.ts index 850f96280d..19d7622490 100644 --- a/web/oss/src/state/newObservability/hooks/index.ts +++ b/web/oss/src/state/newObservability/hooks/index.ts @@ -52,6 +52,8 @@ export const useObservability = () => { isLoading: isLoadingTraces, isFetching: isFetchingTraces, isRefetching: isRefetchingTraces, + isError: isTracesError, + error: tracesError, }, ] = useAtom(tracesQueryAtom) @@ -82,6 +84,11 @@ export const useObservability = () => { [isFetchingTraces, isFetchingAnnotations, isRefetchingTraces, isRefetchingAnnotations], ) + const isRateLimited = isTracesError && (tracesError as {status?: number})?.status === 429 + const rateLimitMessage = isRateLimited + ? (tracesError as Error)?.message || "You have reached your monthly quota limit." + : undefined + const fetchTraces = useCallback(async () => { const res = await refetchTraces() return res.data @@ -111,6 +118,8 @@ export const useObservability = () => { annotations, isLoading: isLoadingObservability || isLoadingTraces || isLoadingAnnotations || isRefreshing, + isRateLimited, + rateLimitMessage, fetchMoreTraces, hasMoreTraces: hasNextPage, isFetchingMore: isFetchingNextPage,