You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 1953632
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
8
8
## [Unreleased]
9
9
10
+
### Added
11
+
-**Prisma without code changes:**`traceperf/auto` and `traceperf run` track every Prisma Client call (`prisma.User.findMany`, raw queries as `prisma.raw.$queryRaw SELECT users`), including clients made with `$extends`. `instrumentPrisma(tp, require('@prisma/client'))` does it by hand. `prismaExtension` steps aside when this is active, so calls are not counted twice.
12
+
-**better-sqlite3, and so Drizzle on SQLite:**`instrumentBetterSqlite3`; auto-detected. Drizzle on pg or mysql2 was already covered through those drivers.
13
+
- N+1 fixes name the Prisma (`include`, `where: { id: { in } }`) and Drizzle (`inArray`) way.
Copy file name to clipboardExpand all lines: README.md
+6-4Lines changed: 6 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@
13
13
-**Honest numbers.** You get total, self and synchronous time for each call. Detailed mode flags calls that blocked the event loop.
14
14
-**Production-ready.** Stats are bounded per label (p50/p95/p99), sampling is built in, and `enabled: false` makes tracking a pass-through costing ~40 ns.
15
15
-**Gets data out.** Chrome/Perfetto traces, OpenTelemetry spans, JSON lines, or your own `onComplete` hook.
16
-
-**Zero-effort coverage.** One line tracks every `fetch`, HTTP request or query, for pg, mysql2, MongoDB/Mongoose, ioredis, Prisma and the AWS SDK.
16
+
-**Zero-effort coverage.** One line tracks every `fetch`, HTTP request or query, for pg, mysql2, MongoDB/Mongoose, ioredis, Prisma, better-sqlite3 (and Drizzle on any of these drivers) and the AWS SDK.
17
17
-**Built for teams.** It feeds Prometheus, catches regressions in CI (`traceperf compare --fail`), shows up in Chrome DevTools, and produces HTML flame-chart reports.
18
18
-**Fits your stack.** Express, Fastify, Hono, Koa, NestJS, Next.js route handlers, decorators, CommonJS, ESM, TypeScript, browsers, Node.js 14+, Bun, Deno, Cloudflare Workers and Vercel Edge. There are no runtime dependencies.
19
19
@@ -99,7 +99,7 @@ The same naming works without `run`: `TRACEPERF_PROFILE_BLOCKING=1 node --requir
99
99
100
100
## No code changes: `traceperf/auto`
101
101
102
-
Start your app with traceperf preloaded. Every incoming HTTP request becomes a tree, with the outgoing `http`/`fetch` calls and the `pg`, `mysql2`, MongoDB/Mongooseand `ioredis` queries it made nested under it:
102
+
Start your app with traceperf preloaded. Every incoming HTTP request becomes a tree, with the outgoing `http`/`fetch` calls and the `pg`, `mysql2`, MongoDB/Mongoose, `ioredis`, Prisma and `better-sqlite3` queries it made nested under it (Drizzle runs on these drivers, so its queries show up too):
103
103
104
104
<!-- docs:skip -->
105
105
```bash
@@ -125,7 +125,7 @@ Database clients are only instrumented when your `package.json` lists them. Conf
125
125
|`TRACEPERF_THRESHOLD=50`| Only report calls taking at least 50 ms |
126
126
|`TRACEPERF_SAMPLE_RATE=0.1`| Track 10% of requests |
127
127
|`TRACEPERF_IGNORE=^/health`| Regular expression of request paths not to track |
Copy file name to clipboardExpand all lines: src/core/explain.ts
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -385,6 +385,8 @@ function suggestFix(f: Finding, hotspots?: Record<string, BlockingHotspot[]>): s
385
385
}
386
386
case'repeated': {
387
387
constlabel=labels[0]||'';
388
+
if(/^prisma\./.test(label))return`load them in one call: include the relation in the parent query (include: { ... }), or findMany({ where: { id: { in: ids } } }) and match results in memory`;
389
+
if(/^sqlite/.test(label))return`load them in one query: WHERE id IN (...) (in Drizzle: inArray(column, ids), or db.query with: { ... }); then match results in memory`;
388
390
returnSQL.test(label)
389
391
? `load them in one query: WHERE id IN (...) (or = ANY($1) in Postgres), or your ORM's include/join; then match results in memory`
390
392
: `make one batched call instead of one per item (a bulk API, or DataLoader to collect the calls of one tick)`;
0 commit comments