diff --git a/packages/web/src/app/[domain]/search/page.tsx b/packages/web/src/app/[domain]/search/page.tsx index 3c9ed729..7ea5dfd5 100644 --- a/packages/web/src/app/[domain]/search/page.tsx +++ b/packages/web/src/app/[domain]/search/page.tsx @@ -10,7 +10,7 @@ import useCaptureEvent from "@/hooks/useCaptureEvent"; import { useNonEmptyQueryParam } from "@/hooks/useNonEmptyQueryParam"; import { useSearchHistory } from "@/hooks/useSearchHistory"; import { Repository, SearchQueryParams, SearchResultFile } from "@/lib/types"; -import { createPathWithQueryParams } from "@/lib/utils"; +import { createPathWithQueryParams, measureSync } from "@/lib/utils"; import { SymbolIcon } from "@radix-ui/react-icons"; import { useQuery } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; @@ -139,16 +139,19 @@ const SearchPageInternal = () => { // We only want to show matches for the default branch when // the user isn't explicitly filtering by branch. - if (!isBranchFilteringEnabled) { - fileMatches = fileMatches.filter(match => { - // @note : this case handles local repos that don't have any branches. - if (!match.Branches) { - return true; - } - return match.Branches.includes("HEAD"); - }); - } + measureSync(() => { + if (!isBranchFilteringEnabled) { + fileMatches = fileMatches.filter(match => { + // @note : this case handles local repos that don't have any branches. + if (!match.Branches) { + return true; + } + + return match.Branches.includes("HEAD"); + }); + } + }, "search.branchFiltering"); return { fileMatches, diff --git a/packages/web/src/app/api/(client)/client.ts b/packages/web/src/app/api/(client)/client.ts index ac83d370..0a98a0b6 100644 --- a/packages/web/src/app/api/(client)/client.ts +++ b/packages/web/src/app/api/(client)/client.ts @@ -3,18 +3,19 @@ import { NEXT_PUBLIC_DOMAIN_SUB_PATH } from "@/lib/environment.client"; import { fileSourceResponseSchema, listRepositoriesResponseSchema, searchResponseSchema } from "@/lib/schemas"; import { FileSourceRequest, FileSourceResponse, ListRepositoriesResponse, SearchRequest, SearchResponse } from "@/lib/types"; +import { measure } from "@/lib/utils"; import assert from "assert"; export const search = async (body: SearchRequest, domain: string): Promise => { const path = resolveServerPath("/api/search"); - const result = await fetch(path, { + const { data: result } = await measure(() => fetch(path, { method: "POST", headers: { "Content-Type": "application/json", "X-Org-Domain": domain, }, body: JSON.stringify(body), - }).then(response => response.json()); + }).then(response => response.json()), "client.search"); return searchResponseSchema.parse(result); } diff --git a/packages/web/src/lib/utils.ts b/packages/web/src/lib/utils.ts index 34834bfe..58322d3a 100644 --- a/packages/web/src/lib/utils.ts +++ b/packages/web/src/lib/utils.ts @@ -208,3 +208,39 @@ export const getDisplayTime = (date: Date) => { return formatTime(months, 'month'); } } + +export const measureSync = (cb: () => T, measureName: string) => { + const startMark = `${measureName}.start`; + const endMark = `${measureName}.end`; + + performance.mark(startMark); + const data = cb(); + performance.mark(endMark); + + const measure = performance.measure(measureName, startMark, endMark); + const durationMs = measure.duration; + console.debug(`[${measureName}] took ${durationMs}ms`); + + return { + data, + durationMs + } +} + +export const measure = async (cb: () => Promise, measureName: string) => { + const startMark = `${measureName}.start`; + const endMark = `${measureName}.end`; + + performance.mark(startMark); + const data = await cb(); + performance.mark(endMark); + + const measure = performance.measure(measureName, startMark, endMark); + const durationMs = measure.duration; + console.debug(`[${measureName}] took ${durationMs}ms`); + + return { + data, + durationMs + } +}