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
78 changes: 39 additions & 39 deletions apps/studio/components/interfaces/HomeNew/ActivityStats.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import dayjs from 'dayjs'
import { GitBranch } from 'lucide-react'
import Link from 'next/link'
import { Archive, Database, GitBranch } from 'lucide-react'
import { useMemo } from 'react'

import { useParams } from 'common'
import { SingleStat } from 'components/ui/SingleStat'
import { useBranchesQuery } from 'data/branches/branches-query'
import { useBackupsQuery } from 'data/database/backups-query'
import { useMigrationsQuery } from 'data/database/migrations-query'
Expand Down Expand Up @@ -55,17 +55,15 @@ export const ActivityStats = () => {

return (
<div className="@container">
<div className="grid grid-cols-2 xl:flex xl:gap-10 gap-4 flex-wrap">
<div className="block">
<p className="heading-meta text-foreground-light mb-1">Status</p>
<ServiceStatus />
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 flex-wrap">
<ServiceStatus />

<Link className="block" href={`/project/${ref}/database/migrations`}>
<h4 className="heading-meta text-foreground-light mb-1">Last migration</h4>

<div className={cn('h-[34px] flex items-center capitalize-sentence')}>
{isLoadingMigrations ? (
<SingleStat
href={`/project/${ref}/database/migrations`}
icon={<Database size={18} strokeWidth={1.5} className="text-foreground" />}
label={<span>Last migration</span>}
value={
isLoadingMigrations ? (
<Skeleton className="h-6 w-24" />
) : latestMigration ? (
<TimestampInfo
Expand All @@ -75,15 +73,16 @@ export const ActivityStats = () => {
/>
) : (
<p className="text-foreground-lighter">No migrations</p>
)}
</div>
</Link>

<Link className="block" href={`/project/${ref}/database/backups/scheduled`}>
<h4 className="heading-meta text-foreground-light mb-1">Last backup</h4>
)
}
/>

<div className={cn('h-[34px] flex items-center capitalize-sentence')}>
{isLoadingBackups ? (
<SingleStat
href={`/project/${ref}/database/backups/scheduled`}
icon={<Archive size={18} strokeWidth={1.5} className="text-foreground" />}
label={<span>Last backup</span>}
value={
isLoadingBackups ? (
<Skeleton className="h-6 w-24" />
) : backupsData?.pitr_enabled ? (
<p>PITR enabled</p>
Expand All @@ -95,25 +94,26 @@ export const ActivityStats = () => {
/>
) : (
<p className="text-foreground-lighter">No backups</p>
)}
</div>
</Link>

<Link className="block" href={`/project/${ref}/branches`}>
<h4 className="heading-meta text-foreground-light mb-1">
{isDefaultProject ? 'Recent branch' : 'Branch Created'}
</h4>
)
}
/>

<div className="text-foreground truncate h-[34px] flex items-center capitalize-sentence">
{isLoadingBranches ? (
<SingleStat
href={`/project/${ref}/branches`}
icon={<GitBranch size={18} strokeWidth={1.5} className="text-foreground" />}
label={<span>{isDefaultProject ? 'Recent branch' : 'Branch Created'}</span>}
value={
isLoadingBranches ? (
<Skeleton className="h-6 w-24" />
) : isDefaultProject ? (
<div className="flex items-center gap-2">
<GitBranch size={16} strokeWidth={1.5} className="text-foreground-lighter" />
<p className={cn('truncate', !latestNonDefaultBranch && 'text-foreground-lighter')}>
{latestNonDefaultBranch?.name ?? 'No branches'}
</p>
</div>
<p
className={cn(
'truncate',
!latestNonDefaultBranch && 'text-foreground-lighter truncate'
)}
>
{latestNonDefaultBranch?.name ?? 'No branches'}
</p>
) : currentBranch?.created_at ? (
<TimestampInfo
className="text-base"
Expand All @@ -122,9 +122,9 @@ export const ActivityStats = () => {
/>
) : (
<p className="text-foreground-lighter">Unknown</p>
)}
</div>
</Link>
)
}
/>
</div>
</div>
)
Expand Down
54 changes: 24 additions & 30 deletions apps/studio/components/interfaces/HomeNew/ServiceStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { AlertTriangle, CheckCircle2, ChevronDown, ChevronRight, Loader2 } from 'lucide-react'
import { AlertTriangle, CheckCircle2, ChevronRight, Loader2 } from 'lucide-react'
import Link from 'next/link'
import { useState } from 'react'

import { PopoverSeparator } from '@ui/components/shadcn/ui/popover'
import { useParams } from 'common'
import { SingleStat } from 'components/ui/SingleStat'
import { useBranchesQuery } from 'data/branches/branches-query'
import { useEdgeFunctionServiceStatusQuery } from 'data/service-status/edge-functions-status-query'
import {
Expand All @@ -12,14 +12,7 @@ import {
} from 'data/service-status/service-status-query'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import {
Button,
InfoIcon,
PopoverContent_Shadcn_,
PopoverTrigger_Shadcn_,
Popover_Shadcn_,
cn,
} from 'ui'
import { InfoIcon, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_, cn } from 'ui'

/**
* [Joshen] JFYI before we go live with this, we need to revisit the migrations section
Expand Down Expand Up @@ -85,7 +78,6 @@ const StatusIcon = ({
export const ServiceStatus = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const [open, setOpen] = useState(false)

const {
projectAuthAll: authEnabled,
Expand Down Expand Up @@ -262,27 +254,29 @@ export const ServiceStatus = () => {
: 'Healthy'

return (
<Popover_Shadcn_ modal={false} open={open} onOpenChange={setOpen}>
<PopoverTrigger_Shadcn_ asChild>
<Button
type="outline"
className="text-base h-auto px-2"
iconRight={<ChevronDown size={14} strokeWidth={1.5} />}
<Popover_Shadcn_>
<PopoverTrigger_Shadcn_>
<SingleStat
icon={
isLoadingChecks || anyComingUp || isMigrationLoading ? (
<Loader2 className="animate-spin ml-1" size={12} strokeWidth={1.5} />
) : (
<div
className={cn(
'w-2 h-2 rounded-full ml-1.5',
allServicesOperational ? 'bg-brand' : 'bg-warning'
)}
/>
)
<div className="grid grid-cols-3 gap-1">
{services.map((service, index) => (
<div
key={`${service.name}-${index}`}
className={cn(
'w-1.5 h-1.5 rounded-full',
service.isLoading || service.status === 'COMING_UP'
? 'bg-foreground-lighter animate-pulse'
: service.isHealthy
? 'bg-brand'
: 'bg-selection'
)}
/>
))}
</div>
}
>
{overallStatusLabel}
</Button>
label={<span>Health</span>}
value={<span>{overallStatusLabel}</span>}
/>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ portal className="p-0 w-56" side="bottom" align="start">
{services.map((service) => (
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/components/interfaces/Reports/ReportWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ const ReportWidget = (props: ReportWidgetProps) => {
query.content = props.resolvedSql
} else {
query.q = props.params?.sql
query.its = props.params!.iso_timestamp_start
query.ite = props.params!.iso_timestamp_end
query.its = props.params?.iso_timestamp_start || ''
query.ite = props.params?.iso_timestamp_end || ''
}

router.push({ pathname, query })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,15 @@ const fetchLogs = async ({

const DEFAULT_KEYS = ['shared-api-report']

export type SharedAPIReportFilterBy =
| 'auth'
| 'realtime'
| 'storage'
| 'graphql'
| 'functions'
| 'postgrest'
type SharedAPIReportParams = {
filterBy: 'auth' | 'realtime' | 'storage' | 'graphql' | 'functions' | 'postgrest'
filterBy: SharedAPIReportFilterBy
start: string
end: string
projectRef: string
Expand Down Expand Up @@ -263,7 +270,16 @@ export const useSharedAPIReport = ({

const queries = useQueries({
queries: Object.entries(SHARED_API_REPORT_SQL).map(([key, value]) => ({
queryKey: [...DEFAULT_KEYS, key, filterByMapSource[filterBy], filters, start, end, ref],
queryKey: [
...DEFAULT_KEYS,
filterBy,
key,
filterByMapSource[filterBy],
filters,
start,
end,
ref,
],
enabled: enabled && !!ref && !!filterBy,
queryFn: () =>
fetchLogs({
Expand Down Expand Up @@ -324,6 +340,22 @@ export const useSharedAPIReport = ({

const isLoadingData = Object.values(isLoading).some(Boolean)

const SQLMap: Record<SharedAPIReportKey, string> = {
totalRequests: SHARED_API_REPORT_SQL.totalRequests.sql(allFilters, filterByMapSource[filterBy]),
topRoutes: SHARED_API_REPORT_SQL.topRoutes.sql(allFilters, filterByMapSource[filterBy]),
errorCounts: SHARED_API_REPORT_SQL.errorCounts.sql(allFilters, filterByMapSource[filterBy]),
topErrorRoutes: SHARED_API_REPORT_SQL.topErrorRoutes.sql(
allFilters,
filterByMapSource[filterBy]
),
responseSpeed: SHARED_API_REPORT_SQL.responseSpeed.sql(allFilters, filterByMapSource[filterBy]),
topSlowRoutes: SHARED_API_REPORT_SQL.topSlowRoutes.sql(allFilters, filterByMapSource[filterBy]),
networkTraffic: SHARED_API_REPORT_SQL.networkTraffic.sql(
allFilters,
filterByMapSource[filterBy]
),
}

return {
data,
error,
Expand All @@ -334,5 +366,9 @@ export const useSharedAPIReport = ({
filters,
addFilter,
removeFilters,
/**
* The SQL queries used to fetch each metric
*/
sql: SQLMap,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type SharedAPIReportWidgetsProps = {
isLoading: any
isRefetching: boolean
hiddenReports?: SharedAPIReportKey[]
sql: Record<SharedAPIReportKey, string>
}

export function SharedAPIReport({
Expand All @@ -22,6 +23,7 @@ export function SharedAPIReport({
isLoading,
isRefetching,
hiddenReports = [],
sql,
}: SharedAPIReportWidgetsProps) {
return (
<div className="grid grid-cols-1 gap-4">
Expand All @@ -34,6 +36,10 @@ export function SharedAPIReport({
renderer={TotalRequestsChartRenderer}
append={TopApiRoutesRenderer}
appendProps={{ data: data.topRoutes }}
queryType="logs"
params={{
sql: sql.totalRequests,
}}
/>
)}
{!hiddenReports.includes('errorCounts') && (
Expand All @@ -48,6 +54,10 @@ export function SharedAPIReport({
data: data.topErrorRoutes || [],
}}
append={TopApiRoutesRenderer}
queryType="logs"
params={{
sql: sql.errorCounts,
}}
/>
)}
{!hiddenReports.includes('responseSpeed') && (
Expand All @@ -60,6 +70,10 @@ export function SharedAPIReport({
renderer={ResponseSpeedChartRenderer}
appendProps={{ data: data.topSlowRoutes || [] }}
append={TopApiRoutesRenderer}
queryType="logs"
params={{
sql: sql.responseSpeed,
}}
/>
)}
{!hiddenReports.includes('networkTraffic') && (
Expand All @@ -70,6 +84,10 @@ export function SharedAPIReport({
tooltip="Ingress and egress of requests and responses respectively"
data={data.networkTraffic || []}
renderer={NetworkTrafficRenderer}
queryType="logs"
params={{
sql: sql.networkTraffic,
}}
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,22 +220,6 @@ export const TopApiRoutesRenderer = (
>
{!showMore ? 'Show more' : 'Show less'}
</Button>
<Button
type="text"
className="text-foreground-lighter"
onClick={() => {
props.router.push({
pathname: `/project/${projectRef}/logs/explorer`,
query: {
q: props.params?.sql,
its: props.params!.iso_timestamp_start,
ite: props.params!.iso_timestamp_end,
},
})
}}
>
Open in Logs Explorer
</Button>
</div>
</Collapsible.Trigger>
</Collapsible>
Expand Down
Loading
Loading