Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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 (
<div className="py-16">
<EmptyComponent
image={<StopOutlined style={{fontSize: 32}} />}
description={
<div className="flex flex-col gap-2">
<Typography.Text className="text-lg font-medium">
Rate limit reached
</Typography.Text>
<Typography.Text type="secondary">
{rateLimitMessage ||
"You have reached your monthly quota limit. Please try again later or upgrade your plan."}
{subscriptionHref && (
<>
{" "}
<Link href={subscriptionHref} className="font-medium">
Upgrade
</Link>
</>
)}
</Typography.Text>
</div>
}
/>
</div>
)
}

if (!showOnboarding) {
return (
<div className="py-16">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ const ObservabilityTable = () => {
isFetchingMore,
autoRefresh,
fetchAnnotations,
isRateLimited,
rateLimitMessage,
} = useObservability()
const setTraceDrawerActiveSpan = useSetAtom(setTraceDrawerActiveSpanAtom)
const isNewUser = useAtomValue(isNewUserAtom)
Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -226,7 +228,9 @@ const ObservabilityTable = () => {
refreshTrigger={refreshTrigger}
/>

{isEmptyState ? (
{isRateLimited ? (
<EmptyObservability rateLimited rateLimitMessage={rateLimitMessage} />
) : isEmptyState ? (
<EmptyObservability showOnboarding={showOnboarding} />
) : (
<div className="flex flex-col gap-2">
Expand Down
9 changes: 9 additions & 0 deletions web/oss/src/state/newObservability/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export const useObservability = () => {
isLoading: isLoadingTraces,
isFetching: isFetchingTraces,
isRefetching: isRefetchingTraces,
isError: isTracesError,
error: tracesError,
},
] = useAtom(tracesQueryAtom)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -111,6 +118,8 @@ export const useObservability = () => {
annotations,
isLoading:
isLoadingObservability || isLoadingTraces || isLoadingAnnotations || isRefreshing,
isRateLimited,
rateLimitMessage,
fetchMoreTraces,
hasMoreTraces: hasNextPage,
isFetchingMore: isFetchingNextPage,
Expand Down
Loading