Skip to content

Commit d9f7983

Browse files
committed
perf: add timing logs to api routes, tiles, search, embeddings
1 parent 9d57ca3 commit d9f7983

File tree

4 files changed

+32
-6
lines changed

4 files changed

+32
-6
lines changed

server/middleware/timing.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { consola } from 'consola'
2+
3+
export default defineEventHandler((event) => {
4+
const start = performance.now()
5+
event.node.res.on('finish', () => {
6+
const ms = (performance.now() - start).toFixed(0)
7+
consola.info(`[perf] ${event.node.req.method} ${event.path} ${ms}ms`)
8+
})
9+
})

server/utils/db-functions.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Buffer } from 'node:buffer'
22

3+
import { consola } from 'consola'
34
import { sql } from 'drizzle-orm'
45

56
/**
@@ -8,9 +9,9 @@ import { sql } from 'drizzle-orm'
89
export async function getTileMvt(z: number, x: number, y: number): Promise<Buffer> {
910
const db = useDrizzle()
1011

11-
const result = await db.execute(
12-
sql`SELECT get_tile_mvt(${z}, ${x}, ${y})`,
13-
)
12+
const start = performance.now()
13+
const result = await db.execute(sql`SELECT get_tile_mvt(${z}, ${x}, ${y})`)
14+
consola.info(`[perf] getTileMvt z=${z} x=${x} y=${y} ${(performance.now() - start).toFixed(0)}ms`)
1415

1516
const row = Array.isArray(result) ? result[0] : (result as { rows?: unknown[] })?.rows?.[0]
1617
const mvtData: unknown = (row as { get_tile_mvt?: unknown })?.get_tile_mvt

server/utils/embeddings.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
import { createOpenAI } from '@ai-sdk/openai'
22
import { embed } from 'ai'
3+
import { consola } from 'consola'
34

45
export async function generateEmbeddingCached(value: string): Promise<number[]> {
56
const normalizedValue = value.trim().toLowerCase()
67
const cacheKey = `embedding:${normalizedValue}`
78

89
const cached = await kv.get(cacheKey) as number[] | null
9-
if (cached)
10+
if (cached) {
11+
consola.info('[perf] embedding: cache hit')
1012
return cached
13+
}
1114

15+
consola.info('[perf] embedding: cache miss, calling OpenAI')
16+
const start = performance.now()
1217
const model = createOpenAI({ apiKey: useRuntimeConfig().openaiApiKey }).embedding('text-embedding-3-small')
1318
const { embedding } = await embed({ model, value })
19+
consola.info(`[perf] embedding: OpenAI ${(performance.now() - start).toFixed(0)}ms`)
1420

1521
await kv.set(cacheKey, embedding as unknown as string)
1622

server/utils/search.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,12 @@ export async function searchLocationsBySimilarCategories(
106106
): Promise<SearchLocationResponse[]> {
107107
try {
108108
const db = useDrizzle()
109+
const embStart = performance.now()
109110
const queryEmbedding = await generateEmbeddingCached(query)
111+
logger.info(`[perf] generateEmbedding ${(performance.now() - embStart).toFixed(0)}ms`)
110112
const { origin, maxDistanceMeters, categories: requiredCategories, fetchLimit, page, limit: pageLimit } = options
111113

114+
const vecStart = performance.now()
112115
const vectorMatches = await db.execute(sql`
113116
SELECT ${tables.categories.id} as id
114117
FROM ${tables.categories}
@@ -119,6 +122,7 @@ export async function searchLocationsBySimilarCategories(
119122
`)
120123

121124
let categoryIds = ((vectorMatches as any).rows || []).map((row: any) => row.id as string)
125+
logger.info(`[perf] vectorSearch found=${categoryIds.length} ${(performance.now() - vecStart).toFixed(0)}ms`)
122126

123127
if (categoryIds.length === 0)
124128
categoryIds = pickFallbackCategories(query)
@@ -198,7 +202,10 @@ export async function searchLocationsByCategories(
198202
? baseQuery.orderBy(selectFields.distanceMeters)
199203
: baseQuery.orderBy(sql`${tables.locations.rating} DESC NULLS LAST`)
200204

201-
return await queryBuilder.limit(limit).offset(offset) as SearchLocationResponse[]
205+
const catStart = performance.now()
206+
const rows = await queryBuilder.limit(limit).offset(offset) as SearchLocationResponse[]
207+
logger.info(`[perf] searchLocationsByCategories count=${rows.length} ${(performance.now() - catStart).toFixed(0)}ms`)
208+
return rows
202209
}
203210

204211
// PostgreSQL's built-in FTS is faster than vector search for exact/prefix matches
@@ -273,5 +280,8 @@ export async function searchLocationsByText(
273280
? baseQuery.orderBy(selectFields.distanceMeters)
274281
: baseQuery
275282

276-
return await queryBuilder.limit(limit).offset(offset) as SearchLocationResponse[]
283+
const txtStart = performance.now()
284+
const rows = await queryBuilder.limit(limit).offset(offset) as SearchLocationResponse[]
285+
logger.info(`[perf] searchLocationsByText count=${rows.length} ${(performance.now() - txtStart).toFixed(0)}ms`)
286+
return rows
277287
}

0 commit comments

Comments
 (0)