@stacknext/drizzle 0.8.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 +70 -0
- package/docs/index.md +94 -0
- package/docs/troubleshooting.md +48 -0
- package/package.json +4 -3
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Configuration
|
|
3
|
+
description: Configure the Drizzle adapter, transport and database settings.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configuration
|
|
7
|
+
|
|
8
|
+
## Adapter options
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { createStackNextDrizzleLogger } from '@stacknext/drizzle'
|
|
12
|
+
|
|
13
|
+
const logger = createStackNextDrizzleLogger({
|
|
14
|
+
databaseSystem: 'postgresql',
|
|
15
|
+
})
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Option | Required | Default | Notes |
|
|
19
|
+
| --- | --- | --- | --- |
|
|
20
|
+
| `databaseSystem` | No | `'sql'` | Use the engine name, for example `sqlite`, `postgresql` or `mysql`. |
|
|
21
|
+
| `transport` | No | Process-wide transport | Must expose `enqueueDatabaseQuery`. |
|
|
22
|
+
| `onError` | No | none | Receives telemetry failures; they never reach Drizzle. |
|
|
23
|
+
|
|
24
|
+
## Connect the logger
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3'
|
|
28
|
+
import { createStackNextDrizzleLogger } from '@stacknext/drizzle'
|
|
29
|
+
|
|
30
|
+
export const db = drizzle(client, {
|
|
31
|
+
logger: createStackNextDrizzleLogger({ databaseSystem: 'sqlite' }),
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The logger is registered when the Drizzle client is created. There is no
|
|
36
|
+
automatic global registration and no monkey-patching.
|
|
37
|
+
|
|
38
|
+
## `stacknext.config.json`
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"database": { "drizzle": true, "prisma": false }
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`database.drizzle` is setup intent used by `stacknext init` and
|
|
47
|
+
`stacknext doctor`. Setting it does **not** attach the logger. The adapter must
|
|
48
|
+
be passed to `drizzle(...)` explicitly.
|
|
49
|
+
|
|
50
|
+
## Environment
|
|
51
|
+
|
|
52
|
+
The adapter uses the active transport. `stacknext dev` exports
|
|
53
|
+
`STACKNEXT_COLLECTOR_URL` and `STACKNEXT_TOKEN`; outside that environment the
|
|
54
|
+
global transport is absent and the logger is inert.
|
|
55
|
+
|
|
56
|
+
Optional adapter overrides for tests are passed through `options.transport`, not
|
|
57
|
+
environment variables.
|
|
58
|
+
|
|
59
|
+
## Captured fields
|
|
60
|
+
|
|
61
|
+
See [the package overview](index.md#what-is-recorded). There is no option to
|
|
62
|
+
enable bind-parameter capture, SQL parameter logging or query bodies.
|
|
63
|
+
|
|
64
|
+
## Verify
|
|
65
|
+
|
|
66
|
+
1. Start `stacknext dev` and make a request that queries the database.
|
|
67
|
+
2. Run `stacknext coverage`; the database category should show observed
|
|
68
|
+
evidence.
|
|
69
|
+
3. Open the dashboard Database page or call `list_database_queries` through MCP.
|
|
70
|
+
4. Confirm durations are `null` and marked unmeasured. That is expected.
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@stacknext/drizzle"
|
|
3
|
+
description: Drizzle ORM query logging adapter for StackNext, without bind-parameter capture.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @stacknext/drizzle
|
|
7
|
+
|
|
8
|
+
`@stacknext/drizzle` is a Drizzle `Logger` adapter. It sends redacted SQL events
|
|
9
|
+
to the active StackNext transport so queries appear in request timelines and
|
|
10
|
+
diagnostics.
|
|
11
|
+
|
|
12
|
+
## Who should read this
|
|
13
|
+
|
|
14
|
+
Applications using Drizzle. This is a **public, optional integration package**.
|
|
15
|
+
It is not required unless the project uses Drizzle.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @stacknext/drizzle
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`drizzle-orm >=0.30.0` is an optional peer dependency. The adapter does not
|
|
24
|
+
import Drizzle at runtime; it accepts any object matching
|
|
25
|
+
`{ logQuery(query, params) }`.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3'
|
|
31
|
+
import { createStackNextDrizzleLogger } from '@stacknext/drizzle'
|
|
32
|
+
|
|
33
|
+
export const db = drizzle(client, {
|
|
34
|
+
logger: createStackNextDrizzleLogger({ databaseSystem: 'sqlite' }),
|
|
35
|
+
})
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
|
|
40
|
+
### `createStackNextDrizzleLogger(options?)`
|
|
41
|
+
|
|
42
|
+
Returns a `DrizzleLoggerLike` with `logQuery(query, params)`.
|
|
43
|
+
|
|
44
|
+
`StackNextDrizzleLoggerOptions`:
|
|
45
|
+
|
|
46
|
+
| Option | Type | Default | Meaning |
|
|
47
|
+
| --- | --- | --- | --- |
|
|
48
|
+
| `databaseSystem` | string | `'sql'` | Value reported as `db.system.name`. |
|
|
49
|
+
| `transport` | `Pick<StackNextTransport, 'enqueueDatabaseQuery'>` | global transport | Override for tests or custom setups. |
|
|
50
|
+
| `onError` | `(error: unknown) => void` | none | Called when the telemetry sink throws. |
|
|
51
|
+
|
|
52
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
53
|
+
|
|
54
|
+
<!-- coderabbit-ai-generated-section:v1:92e6ad51fd00b5bd40b76d93991b902366deea6ad1bb299cee86b066438eac33 -->
|
|
55
|
+
|
|
56
|
+
Telemetry failures are caught, but a throwing `onError` callback can propagate
|
|
57
|
+
its error to Drizzle. Callers must ensure `onError` does not throw. If no transport is active, the
|
|
58
|
+
logger is a no-op.
|
|
59
|
+
|
|
60
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
61
|
+
|
|
62
|
+
## What is recorded
|
|
63
|
+
|
|
64
|
+
- redacted SQL text (capped at 20,000 characters);
|
|
65
|
+
- inferred operation (`select`, `insert`, `update`, `delete`, `with`, and so
|
|
66
|
+
on);
|
|
67
|
+
- active trace/span ids when a valid OTel context exists;
|
|
68
|
+
- `databaseSystem`, `success: true`, `source: 'drizzle'`;
|
|
69
|
+
- `db.query.parameter_count` (the count only);
|
|
70
|
+
- `db.duration.measured: false`.
|
|
71
|
+
|
|
72
|
+
## Duration is null
|
|
73
|
+
|
|
74
|
+
Drizzle's `Logger` interface does not expose query duration. StackNext stores
|
|
75
|
+
`durationMs: null` and marks it unmeasured. It is never converted to zero.
|
|
76
|
+
|
|
77
|
+
Do not compare Drizzle durations with Prisma durations or rank them as if they
|
|
78
|
+
were fast.
|
|
79
|
+
|
|
80
|
+
## Privacy
|
|
81
|
+
|
|
82
|
+
`params` is used only for `Array.isArray(params) ? params.length : 0`. The
|
|
83
|
+
values are never read, logged or transmitted. SQL text passes through
|
|
84
|
+
`redactSql`.
|
|
85
|
+
|
|
86
|
+
## Documentation map
|
|
87
|
+
|
|
88
|
+
- [Configuration](configuration.md)
|
|
89
|
+
- [Troubleshooting](troubleshooting.md)
|
|
90
|
+
|
|
91
|
+
## Related packages
|
|
92
|
+
|
|
93
|
+
- `@stacknext/core` owns the transport and redaction.
|
|
94
|
+
- `@stacknext/cli` runs the collector.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Troubleshooting
|
|
3
|
+
description: Diagnose missing Drizzle queries, null durations and adapter registration problems.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Troubleshooting
|
|
7
|
+
|
|
8
|
+
## No Drizzle queries appear
|
|
9
|
+
|
|
10
|
+
1. Confirm `createStackNextDrizzleLogger()` is passed to the same Drizzle client
|
|
11
|
+
that serves requests.
|
|
12
|
+
2. Confirm the app is running under `stacknext dev`, which supplies the
|
|
13
|
+
transport environment.
|
|
14
|
+
3. Make a request that actually executes a query.
|
|
15
|
+
4. Run `stacknext coverage`; `database` evidence should become observed.
|
|
16
|
+
5. Check `stacknext doctor` for adapter/config warnings.
|
|
17
|
+
|
|
18
|
+
## Queries appear without a trace
|
|
19
|
+
|
|
20
|
+
The adapter records trace/span ids only when a valid OpenTelemetry context is
|
|
21
|
+
active. Queries from scripts, workers or background jobs may have no request
|
|
22
|
+
root. They are still stored, but they are not attributed to a request.
|
|
23
|
+
|
|
24
|
+
## Duration is null
|
|
25
|
+
|
|
26
|
+
Expected. Drizzle's logger does not expose duration. StackNext stores `null` and
|
|
27
|
+
sets `db.duration.measured: false`.
|
|
28
|
+
|
|
29
|
+
Do not treat `null` as zero, and do not compare Drizzle and Prisma durations.
|
|
30
|
+
|
|
31
|
+
## SQL is redacted or truncated
|
|
32
|
+
|
|
33
|
+
SQL passes through `redactSql` and is capped at 20,000 characters. Bind
|
|
34
|
+
parameters are not included, so a value passed as `?` or `$1` cannot leak.
|
|
35
|
+
|
|
36
|
+
## The adapter throws?
|
|
37
|
+
|
|
38
|
+
It should not. `logQuery` catches sink errors and forwards them to `onError` if
|
|
39
|
+
provided. If an error escapes, check the Drizzle logger contract and the
|
|
40
|
+
`enqueueDatabaseQuery` implementation supplied through `options.transport`.
|
|
41
|
+
|
|
42
|
+
## Verify
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
stacknext status --json
|
|
46
|
+
stacknext coverage --json
|
|
47
|
+
stacknext diagnose --category database
|
|
48
|
+
```
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacknext/drizzle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Drizzle ORM query logging 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": {
|