@stacknext/prisma 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/configuration.md +81 -0
- package/docs/index.md +84 -0
- package/docs/troubleshooting.md +49 -0
- package/package.json +4 -3
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Configuration
|
|
3
|
+
description: Configure Prisma query events and the StackNext adapter.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configuration
|
|
7
|
+
|
|
8
|
+
## Prisma Client
|
|
9
|
+
|
|
10
|
+
Query events must be enabled when the client is created:
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { PrismaClient } from '@prisma/client'
|
|
14
|
+
|
|
15
|
+
const prisma = new PrismaClient({
|
|
16
|
+
log: [{ emit: 'event', level: 'query' }],
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Prisma's default logging does not emit these events.
|
|
21
|
+
|
|
22
|
+
## Adapter
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { instrumentPrismaClient } from '@stacknext/prisma'
|
|
26
|
+
|
|
27
|
+
const stop = instrumentPrismaClient(prisma, {
|
|
28
|
+
databaseSystem: 'postgresql',
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
| Option | Required | Default | Notes |
|
|
33
|
+
| --- | --- | --- | --- |
|
|
34
|
+
| `databaseSystem` | No | `'prisma'` | Use the engine name, for example `sqlite` or `postgresql`. |
|
|
35
|
+
| `transport` | No | Process-wide transport | Must expose `enqueueDatabaseQuery`. |
|
|
36
|
+
| `onError` | No | none | Receives telemetry failures; they never reach Prisma. |
|
|
37
|
+
|
|
38
|
+
## Lifecycle
|
|
39
|
+
|
|
40
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
41
|
+
|
|
42
|
+
<!-- coderabbit-ai-generated-section:v1:28f70536dac55a5bf479d919dd7e163c76b9148c7a914e348e3b8decef5a2e95 -->
|
|
43
|
+
|
|
44
|
+
`instrumentPrismaClient` returns a cleanup function. Calling it deactivates the
|
|
45
|
+
listener and clears the idempotency guard. Calling `instrumentPrismaClient`
|
|
46
|
+
again for the same client before cleanup returns a no-op cleanup.
|
|
47
|
+
|
|
48
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
49
|
+
|
|
50
|
+
Register the adapter once per Prisma client, after the client is created and
|
|
51
|
+
before the first request.
|
|
52
|
+
|
|
53
|
+
## `stacknext.config.json`
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"database": { "drizzle": false, "prisma": true }
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`database.prisma` is setup intent used by `stacknext init` and
|
|
62
|
+
`stacknext doctor`. It does not attach the listener; the adapter must be called
|
|
63
|
+
explicitly.
|
|
64
|
+
|
|
65
|
+
## Duration
|
|
66
|
+
|
|
67
|
+
Prisma query events include a duration in milliseconds. StackNext uses it when
|
|
68
|
+
it is a finite number, otherwise `durationMs` is `null`. Null is unmeasured, not
|
|
69
|
+
zero.
|
|
70
|
+
|
|
71
|
+
## Privacy
|
|
72
|
+
|
|
73
|
+
The adapter never reads `event.params`. SQL is redacted and capped. No
|
|
74
|
+
configuration option can enable bind-parameter capture.
|
|
75
|
+
|
|
76
|
+
## Verify
|
|
77
|
+
|
|
78
|
+
1. Start `stacknext dev` and exercise a Prisma query.
|
|
79
|
+
2. Run `stacknext coverage`; database evidence should be observed.
|
|
80
|
+
3. Check that the query duration is measured for Prisma.
|
|
81
|
+
4. Open the dashboard Database page or use `list_database_queries` through MCP.
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@stacknext/prisma"
|
|
3
|
+
description: Prisma Client query event instrumentation for StackNext.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @stacknext/prisma
|
|
7
|
+
|
|
8
|
+
`@stacknext/prisma` subscribes to Prisma `query` events and sends redacted query
|
|
9
|
+
evidence to the active StackNext transport.
|
|
10
|
+
|
|
11
|
+
## Who should read this
|
|
12
|
+
|
|
13
|
+
Applications using Prisma. This is a **public, optional integration package**.
|
|
14
|
+
It is not required unless the project uses Prisma.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @stacknext/prisma
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`@prisma/client >=5.0.0` is an optional peer dependency. The adapter accepts a
|
|
23
|
+
structural subset of the client and does not import Prisma at runtime.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { PrismaClient } from '@prisma/client'
|
|
29
|
+
import { instrumentPrismaClient } from '@stacknext/prisma'
|
|
30
|
+
|
|
31
|
+
const prisma = new PrismaClient({
|
|
32
|
+
log: [{ emit: 'event', level: 'query' }],
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const stop = instrumentPrismaClient(prisma, {
|
|
36
|
+
databaseSystem: 'postgresql',
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// Optional: call stop() during shutdown.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Prisma must be configured to emit query events. Without the `log` event
|
|
43
|
+
configuration, the adapter receives nothing.
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### `instrumentPrismaClient(client, options?)`
|
|
48
|
+
|
|
49
|
+
Subscribes to `$on('query', listener)` and returns a cleanup function. It is
|
|
50
|
+
idempotent for the same client instance: a second call returns a no-op cleanup
|
|
51
|
+
and does not attach a second listener.
|
|
52
|
+
|
|
53
|
+
`StackNextPrismaOptions`:
|
|
54
|
+
|
|
55
|
+
| Option | Type | Default | Meaning |
|
|
56
|
+
| --- | --- | --- | --- |
|
|
57
|
+
| `databaseSystem` | string | `'prisma'` | Reported as `db.system.name`. |
|
|
58
|
+
| `transport` | `Pick<StackNextTransport, 'enqueueDatabaseQuery'>` | global transport | Override for tests or custom setups. |
|
|
59
|
+
| `onError` | `(error: unknown) => void` | none | Called when the sink throws. |
|
|
60
|
+
|
|
61
|
+
## What is recorded
|
|
62
|
+
|
|
63
|
+
- redacted SQL text (capped at 20,000 characters);
|
|
64
|
+
- inferred operation;
|
|
65
|
+
- `durationMs` when Prisma supplies a finite, non-negative duration;
|
|
66
|
+
- active trace/span ids when a valid OTel context exists;
|
|
67
|
+
- `databaseSystem`, `source: 'prisma'`, `success: true`;
|
|
68
|
+
- `db.duration.measured`;
|
|
69
|
+
- `db.prisma.target` (bounded to 200 characters), when present.
|
|
70
|
+
|
|
71
|
+
## Privacy
|
|
72
|
+
|
|
73
|
+
`event.params` is typed as a JSON string but is **never read**. SQL text passes
|
|
74
|
+
through `redactSql`. Query events do not include request bodies or headers.
|
|
75
|
+
|
|
76
|
+
## Documentation map
|
|
77
|
+
|
|
78
|
+
- [Configuration](configuration.md)
|
|
79
|
+
- [Troubleshooting](troubleshooting.md)
|
|
80
|
+
|
|
81
|
+
## Related packages
|
|
82
|
+
|
|
83
|
+
- `@stacknext/core` owns the transport and redaction.
|
|
84
|
+
- `@stacknext/cli` runs the collector.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Troubleshooting
|
|
3
|
+
description: Diagnose missing Prisma query events, duplicate listeners and unmeasured durations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Troubleshooting
|
|
7
|
+
|
|
8
|
+
## No Prisma queries appear
|
|
9
|
+
|
|
10
|
+
1. Confirm `PrismaClient` is created with
|
|
11
|
+
`log: [{ emit: 'event', level: 'query' }]`.
|
|
12
|
+
2. Confirm `instrumentPrismaClient(prisma, ...)` is called on that same client.
|
|
13
|
+
3. Confirm the app runs under `stacknext dev`.
|
|
14
|
+
4. Exercise a query, then check `stacknext coverage`.
|
|
15
|
+
5. Run `stacknext doctor` for adapter and config warnings.
|
|
16
|
+
|
|
17
|
+
## The listener is not attached
|
|
18
|
+
|
|
19
|
+
The adapter requires `client.$on('query', callback)`. A mock, a wrapper or a
|
|
20
|
+
different client type may not satisfy the structural contract. Use the real
|
|
21
|
+
Prisma Client.
|
|
22
|
+
|
|
23
|
+
## I called the adapter twice
|
|
24
|
+
|
|
25
|
+
It is idempotent for the same client. The second call returns a no-op cleanup
|
|
26
|
+
and does not attach another listener.
|
|
27
|
+
|
|
28
|
+
## Duration is null
|
|
29
|
+
|
|
30
|
+
The event duration was missing or not a finite number. StackNext never
|
|
31
|
+
fabricates a duration. Check the Prisma event payload and version.
|
|
32
|
+
|
|
33
|
+
## Queries are not linked to a request
|
|
34
|
+
|
|
35
|
+
Trace/span ids are recorded only when a valid OTel context is active. Queries
|
|
36
|
+
from scripts, workers or background jobs may have no request root.
|
|
37
|
+
|
|
38
|
+
## Params are missing
|
|
39
|
+
|
|
40
|
+
By design. `event.params` is never read, logged or transmitted. The redacted SQL
|
|
41
|
+
text is the only query body StackNext stores.
|
|
42
|
+
|
|
43
|
+
## Verify
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
stacknext status --json
|
|
47
|
+
stacknext coverage --json
|
|
48
|
+
stacknext diagnose --category database
|
|
49
|
+
```
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacknext/prisma",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Prisma Client query instrumentation adapter for StackNext",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
-
"dist"
|
|
8
|
+
"dist",
|
|
9
|
+
"docs"
|
|
9
10
|
],
|
|
10
11
|
"main": "./dist/index.js",
|
|
11
12
|
"types": "./dist/index.d.ts",
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
"./package.json": "./package.json"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@stacknext/core": "0.
|
|
22
|
+
"@stacknext/core": "0.10.0",
|
|
22
23
|
"@opentelemetry/api": "1.9.0"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|