@zintrust/trace 0.4.81 → 0.4.83
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/README.md +6 -0
- package/dist/build-manifest.json +45 -45
- package/dist/config.js +3 -0
- package/dist/dashboard/ui.js +103 -8
- package/dist/register.js +36 -4
- package/dist/types.d.ts +30 -1
- package/dist/watchers/CacheWatcher.d.ts +1 -1
- package/dist/watchers/CacheWatcher.js +10 -2
- package/dist/watchers/HttpClientWatcher.d.ts +2 -2
- package/dist/watchers/HttpClientWatcher.js +17 -4
- package/dist/watchers/MailWatcher.d.ts +1 -1
- package/dist/watchers/MailWatcher.js +12 -3
- package/dist/watchers/NotificationWatcher.d.ts +1 -1
- package/dist/watchers/NotificationWatcher.js +9 -1
- package/dist/watchers/QueryWatcher.d.ts +5 -1
- package/dist/watchers/QueryWatcher.js +49 -33
- package/package.json +3 -3
- package/src/config.ts +3 -0
- package/src/dashboard/ui.ts +103 -8
- package/src/register.ts +51 -5
- package/src/types.ts +31 -1
- package/src/watchers/CacheWatcher.ts +13 -2
- package/src/watchers/HttpClientWatcher.ts +33 -11
- package/src/watchers/MailWatcher.ts +18 -3
- package/src/watchers/NotificationWatcher.ts +15 -1
- package/src/watchers/QueryWatcher.ts +53 -35
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ You can still import the package migrations manually if you prefer to keep them
|
|
|
29
29
|
```env
|
|
30
30
|
TRACE_ENABLED=true
|
|
31
31
|
TRACE_DB_CONNECTION=d1 # optional — omit to inherit DB_CONNECTION
|
|
32
|
+
TRACE_QUERY_CONNECTION=main # optional — app DB to observe for SQL traces
|
|
32
33
|
TRACE_PRUNE_HOURS=24 # how long entries are kept (default: 24)
|
|
33
34
|
TRACE_SLOW_QUERY_MS=100 # slow-query threshold in ms (default: 100)
|
|
34
35
|
TRACE_LOG_LEVEL=info # minimum log level captured (default: info)
|
|
@@ -77,6 +78,7 @@ import type { TraceConfigOverrides } from '@zintrust/trace';
|
|
|
77
78
|
export default {
|
|
78
79
|
enabled: Env.getBool('TRACE_ENABLED', false),
|
|
79
80
|
connection: Env.get('TRACE_DB_CONNECTION', '') || undefined,
|
|
81
|
+
observeConnection: Env.get('TRACE_QUERY_CONNECTION', '') || undefined,
|
|
80
82
|
pruneAfterHours: Env.getInt('TRACE_PRUNE_HOURS', 24),
|
|
81
83
|
slowQueryThreshold: Env.getInt('TRACE_SLOW_QUERY_MS', 100),
|
|
82
84
|
logMinLevel: Env.get('TRACE_LOG_LEVEL', 'info') as TraceConfigOverrides['logMinLevel'],
|
|
@@ -102,6 +104,10 @@ export default {
|
|
|
102
104
|
|
|
103
105
|
All include/exclude matching is contains-based, so a term like `report` matches `/reports/daily`, `monthly-report`, or any other trace content containing that fragment.
|
|
104
106
|
|
|
107
|
+
When trace storage lives on a different connection than your application data, keep `TRACE_DB_CONNECTION` pointed at the trace tables and set `TRACE_QUERY_CONNECTION` to the app connection you want SQL traces to observe. If you omit `TRACE_QUERY_CONNECTION`, trace automatically falls back to the main `DB_CONNECTION` whenever the storage connection is different.
|
|
108
|
+
|
|
109
|
+
When ZinTrust proxy runtimes also have trace enabled, proxy-executed SQL and SMTP operations are traced at the proxy boundary too. That means MySQL, PostgreSQL, SQL Server, and D1 proxy requests can still record the final SQL plus bound values, and the SMTP proxy can persist rendered mail text and HTML, even when the consumer application is talking to the proxy rather than executing the transport locally.
|
|
110
|
+
|
|
105
111
|
### 3. Mount the dashboard
|
|
106
112
|
|
|
107
113
|
Register the dashboard explicitly in your route file when you want the UI. Restrict access with middleware — the trace does **not** apply auth automatically.
|
package/dist/build-manifest.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/trace",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"buildDate": "2026-04-
|
|
3
|
+
"version": "0.4.83",
|
|
4
|
+
"buildDate": "2026-04-08T17:13:19.081Z",
|
|
5
5
|
"buildEnvironment": {
|
|
6
6
|
"node": "v22.22.1",
|
|
7
7
|
"platform": "darwin",
|
|
8
8
|
"arch": "arm64"
|
|
9
9
|
},
|
|
10
10
|
"git": {
|
|
11
|
-
"commit": "
|
|
11
|
+
"commit": "3c792064",
|
|
12
12
|
"branch": "release"
|
|
13
13
|
},
|
|
14
14
|
"package": {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"files": {
|
|
24
24
|
"build-manifest.json": {
|
|
25
|
-
"size":
|
|
26
|
-
"sha256": "
|
|
25
|
+
"size": 14439,
|
|
26
|
+
"sha256": "dab00c1ade5c0b5fe2b10b5eeeae31dfd9a017f198794e18e7c2b69cfb5560d8"
|
|
27
27
|
},
|
|
28
28
|
"cli-register.d.ts": {
|
|
29
29
|
"size": 255,
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"sha256": "b034cbef0c71fb868071363624ef7a9f8d7acc20f8be8c895dd5db5a75e81f37"
|
|
39
39
|
},
|
|
40
40
|
"config.js": {
|
|
41
|
-
"size":
|
|
42
|
-
"sha256": "
|
|
41
|
+
"size": 5961,
|
|
42
|
+
"sha256": "1402cf8ad7c850da99e429c8c937385b7b5cf401fa3714d972d4e6bd94f1663e"
|
|
43
43
|
},
|
|
44
44
|
"context.d.ts": {
|
|
45
45
|
"size": 596,
|
|
@@ -70,16 +70,16 @@
|
|
|
70
70
|
"sha256": "4862b41e0477f01afa0dbb446d4553b65c22ed774cd1e2db3489059ced392f94"
|
|
71
71
|
},
|
|
72
72
|
"dashboard/ui.js": {
|
|
73
|
-
"size":
|
|
74
|
-
"sha256": "
|
|
73
|
+
"size": 70368,
|
|
74
|
+
"sha256": "b9f67e7977a36b459ac8d37312547b2638fcab7fc9b6c3d0c072d02510fca62f"
|
|
75
75
|
},
|
|
76
76
|
"index.d.ts": {
|
|
77
|
-
"size":
|
|
78
|
-
"sha256": "
|
|
77
|
+
"size": 2470,
|
|
78
|
+
"sha256": "99c28d43f79dbb2b372bf6a8b611841c131f59f5066702b499915b874e9fa2b8"
|
|
79
79
|
},
|
|
80
80
|
"index.js": {
|
|
81
|
-
"size":
|
|
82
|
-
"sha256": "
|
|
81
|
+
"size": 3255,
|
|
82
|
+
"sha256": "a293d38a9e56a2ab802f99143eb1eaebb18f854e610f29bc95878746ffe26326"
|
|
83
83
|
},
|
|
84
84
|
"migrations/20260331000001_create_zin_trace_entries_table.d.ts": {
|
|
85
85
|
"size": 304,
|
|
@@ -134,8 +134,8 @@
|
|
|
134
134
|
"sha256": "71d366165dd36f1675aa253a76262b226fb6c62e5ab632746b8aea61c0c625fc"
|
|
135
135
|
},
|
|
136
136
|
"register.js": {
|
|
137
|
-
"size":
|
|
138
|
-
"sha256": "
|
|
137
|
+
"size": 12522,
|
|
138
|
+
"sha256": "66bccec7fac4d669702fa18e439788325d36ce17f228639005ffcde2cd968d70"
|
|
139
139
|
},
|
|
140
140
|
"storage/DebuggerStorage.d.ts": {
|
|
141
141
|
"size": 517,
|
|
@@ -186,8 +186,8 @@
|
|
|
186
186
|
"sha256": "d916e8e3abb1b1087f6b184851b0e6265e53380d7857b008e745d566aad15d44"
|
|
187
187
|
},
|
|
188
188
|
"types.d.ts": {
|
|
189
|
-
"size":
|
|
190
|
-
"sha256": "
|
|
189
|
+
"size": 8448,
|
|
190
|
+
"sha256": "de994120c04696e08afb428cff27a99fb2918f5c4277b8190b8fb3d36d139f0d"
|
|
191
191
|
},
|
|
192
192
|
"types.js": {
|
|
193
193
|
"size": 696,
|
|
@@ -266,12 +266,12 @@
|
|
|
266
266
|
"sha256": "879a739de9ce2c3c5b57bdad73eae2ce3de94ccdc7e666ca52a50b45b0bc9bfd"
|
|
267
267
|
},
|
|
268
268
|
"watchers/CacheWatcher.d.ts": {
|
|
269
|
-
"size":
|
|
270
|
-
"sha256": "
|
|
269
|
+
"size": 314,
|
|
270
|
+
"sha256": "19b5f6fe4f0fc8f3df6762f4f46d36f198c7c7d7da8d3d23e5c8f124462e8cf7"
|
|
271
271
|
},
|
|
272
272
|
"watchers/CacheWatcher.js": {
|
|
273
|
-
"size":
|
|
274
|
-
"sha256": "
|
|
273
|
+
"size": 1956,
|
|
274
|
+
"sha256": "e1e1b79e85e7553d856ff0209d912e27d7b4fe665579de856c60e04bb7519aa1"
|
|
275
275
|
},
|
|
276
276
|
"watchers/CommandWatcher.d.ts": {
|
|
277
277
|
"size": 267,
|
|
@@ -298,12 +298,12 @@
|
|
|
298
298
|
"sha256": "ff32b44b48b6e313d15ba4370a845faf74ff8b03504a6336c19f183ff91a90dc"
|
|
299
299
|
},
|
|
300
300
|
"watchers/ExceptionWatcher.d.ts": {
|
|
301
|
-
"size":
|
|
302
|
-
"sha256": "
|
|
301
|
+
"size": 311,
|
|
302
|
+
"sha256": "0f58c50fd77704151399ca6cb6ec7890a9aef86afe28235951971f8cc9c1d600"
|
|
303
303
|
},
|
|
304
304
|
"watchers/ExceptionWatcher.js": {
|
|
305
|
-
"size":
|
|
306
|
-
"sha256": "
|
|
305
|
+
"size": 3691,
|
|
306
|
+
"sha256": "d2ddd55f14730b0404cea53c17a6cfd4bd65ff3c17c8b068cc284de109da36d1"
|
|
307
307
|
},
|
|
308
308
|
"watchers/GateWatcher.d.ts": {
|
|
309
309
|
"size": 262,
|
|
@@ -314,20 +314,20 @@
|
|
|
314
314
|
"sha256": "f318cdeec954ce0bba97be1dc11a6dff935b081e6b6a417c614be1934fa47f04"
|
|
315
315
|
},
|
|
316
316
|
"watchers/HttpClientWatcher.d.ts": {
|
|
317
|
-
"size":
|
|
318
|
-
"sha256": "
|
|
317
|
+
"size": 333,
|
|
318
|
+
"sha256": "08ab7e213c489ecc4fdd3166d7a121b9a5220ff9cbae9841d4787d9a804e11ce"
|
|
319
319
|
},
|
|
320
320
|
"watchers/HttpClientWatcher.js": {
|
|
321
|
-
"size":
|
|
322
|
-
"sha256": "
|
|
321
|
+
"size": 2414,
|
|
322
|
+
"sha256": "817c74e7a89bcd0c53c0344d713b422e0c9e51ec65e7b6c97f0c486116dda7a5"
|
|
323
323
|
},
|
|
324
324
|
"watchers/HttpWatcher.d.ts": {
|
|
325
325
|
"size": 96,
|
|
326
326
|
"sha256": "ce9a95a670f755193fd74ce721dbfa4b30f20c879a6566ebb35229b3b2435429"
|
|
327
327
|
},
|
|
328
328
|
"watchers/HttpWatcher.js": {
|
|
329
|
-
"size":
|
|
330
|
-
"sha256": "
|
|
329
|
+
"size": 5916,
|
|
330
|
+
"sha256": "9b3fed08fd11f8a2bfe1f667293af437b00f11dcc66bfb545b2f77925394e611"
|
|
331
331
|
},
|
|
332
332
|
"watchers/JobWatcher.d.ts": {
|
|
333
333
|
"size": 441,
|
|
@@ -342,16 +342,16 @@
|
|
|
342
342
|
"sha256": "f3ddc5f8b58c6c86ac6b464dd48e5a55e79ab2bf2e735feacffc7480e4ccc0c4"
|
|
343
343
|
},
|
|
344
344
|
"watchers/LogWatcher.js": {
|
|
345
|
-
"size":
|
|
346
|
-
"sha256": "
|
|
345
|
+
"size": 2026,
|
|
346
|
+
"sha256": "c5d2227cd76ce10162993ac31f474b2460cd41264c36f01b5130152f14a0ad21"
|
|
347
347
|
},
|
|
348
348
|
"watchers/MailWatcher.d.ts": {
|
|
349
|
-
"size":
|
|
350
|
-
"sha256": "
|
|
349
|
+
"size": 244,
|
|
350
|
+
"sha256": "5031b96ef8e64a6d376576e8cddf1c2560f22432a78f1d2be55f7cea6bff4547"
|
|
351
351
|
},
|
|
352
352
|
"watchers/MailWatcher.js": {
|
|
353
|
-
"size":
|
|
354
|
-
"sha256": "
|
|
353
|
+
"size": 1655,
|
|
354
|
+
"sha256": "0eb4f43c27a0c76cf290bb6507e71dc595bff3f8ab66c25249d9ac6027b351c5"
|
|
355
355
|
},
|
|
356
356
|
"watchers/MiddlewareWatcher.d.ts": {
|
|
357
357
|
"size": 259,
|
|
@@ -370,20 +370,20 @@
|
|
|
370
370
|
"sha256": "de3d1e379c7b1289167fe0b1dbf2aa5a54137b841df17c8d397ee656d9ce37fd"
|
|
371
371
|
},
|
|
372
372
|
"watchers/NotificationWatcher.d.ts": {
|
|
373
|
-
"size":
|
|
374
|
-
"sha256": "
|
|
373
|
+
"size": 274,
|
|
374
|
+
"sha256": "a1d918122c5db9a7f27fdf78c0c14a61f6e1213748ee6f9b06f976f33589dc33"
|
|
375
375
|
},
|
|
376
376
|
"watchers/NotificationWatcher.js": {
|
|
377
|
-
"size":
|
|
378
|
-
"sha256": "
|
|
377
|
+
"size": 1697,
|
|
378
|
+
"sha256": "b0ecc1df6a49dc8c5ffeb8dff0f1e3594ba016c4de3424dc8b5d7832e2f4cd11"
|
|
379
379
|
},
|
|
380
380
|
"watchers/QueryWatcher.d.ts": {
|
|
381
|
-
"size":
|
|
382
|
-
"sha256": "
|
|
381
|
+
"size": 240,
|
|
382
|
+
"sha256": "5d5046c65e5b683369c7709f1acd09b60aec3e7f44748fd1baeb35498836465b"
|
|
383
383
|
},
|
|
384
384
|
"watchers/QueryWatcher.js": {
|
|
385
|
-
"size":
|
|
386
|
-
"sha256": "
|
|
385
|
+
"size": 2935,
|
|
386
|
+
"sha256": "577c6fec0282d2290db5c4b6c606b9b6ecdd64209af2b09f3205a15bf656bbef"
|
|
387
387
|
},
|
|
388
388
|
"watchers/RedisWatcher.d.ts": {
|
|
389
389
|
"size": 294,
|
package/dist/config.js
CHANGED
|
@@ -76,9 +76,12 @@ const mergeWatchers = (base, override) => {
|
|
|
76
76
|
const DEFAULTS = Object.freeze({
|
|
77
77
|
enabled: false,
|
|
78
78
|
connection: undefined,
|
|
79
|
+
observeConnection: undefined,
|
|
79
80
|
pruneAfterHours: 24,
|
|
80
81
|
ignoreRoutes: ['/trace', '/health', '/ping'],
|
|
81
82
|
slowQueryThreshold: 100,
|
|
83
|
+
captureCachePayloads: false,
|
|
84
|
+
captureQueryBindings: true,
|
|
82
85
|
logMinLevel: 'info',
|
|
83
86
|
watchers: {},
|
|
84
87
|
redaction: {
|
package/dist/dashboard/ui.js
CHANGED
|
@@ -41,7 +41,7 @@ const encodeSvgDataUri = (svg) => {
|
|
|
41
41
|
const compactSvg = svg.replaceAll(/>\s+</g, '><').trim();
|
|
42
42
|
return `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(compactSvg)}`;
|
|
43
43
|
};
|
|
44
|
-
const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
44
|
+
const DASHBOARD_DOCUMENT = String.raw `<!DOCTYPE html>
|
|
45
45
|
<html lang="en">
|
|
46
46
|
<head>
|
|
47
47
|
<meta charset="UTF-8">
|
|
@@ -74,7 +74,7 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
74
74
|
.tag{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;background:rgba(56,189,248,.12);color:#bae6fd;font-size:.78rem;font-weight:800;margin:0 6px 6px 0;border:1px solid rgba(56,189,248,.18);text-decoration:none}button.tag{cursor:pointer}html[data-theme='light'] .tag{color:#075985}.tag.failed{background:rgba(239,68,68,.14);color:#fecaca;border-color:rgba(239,68,68,.2)}html[data-theme='light'] .tag.failed{color:#b91c1c}.tag.slow{background:rgba(245,158,11,.12);color:#fde68a;border-color:rgba(245,158,11,.18)}html[data-theme='light'] .tag.slow{color:#92400e}.type-pill{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:999px;font-size:.74rem;font-weight:900;text-transform:uppercase;letter-spacing:.08em;border:1px solid transparent}.pill-request{background:rgba(56,189,248,.14);color:#93c5fd}.pill-request.method-get{background:rgba(34,197,94,.16);color:#bbf7d0}.pill-request.method-post{background:rgba(59,130,246,.16);color:#bfdbfe}.pill-request.method-other{background:rgba(245,158,11,.16);color:#fde68a}.pill-query{background:rgba(34,197,94,.12);color:#86efac}.pill-exception{background:rgba(239,68,68,.14);color:#fecaca}.pill-log{background:rgba(168,85,247,.14);color:#ddd6fe}.pill-job,.pill-batch{background:rgba(245,158,11,.14);color:#fde68a}.pill-cache{background:rgba(20,184,166,.12);color:#99f6e4}.pill-schedule,.pill-command{background:rgba(14,165,233,.14);color:#bae6fd}.pill-mail,.pill-notification{background:rgba(236,72,153,.14);color:#fbcfe8}.pill-auth{background:rgba(148,163,184,.16);color:#e2e8f0}.pill-event,.pill-model{background:rgba(74,222,128,.14);color:#bbf7d0}.pill-redis{background:rgba(239,68,68,.12);color:#fecaca}.pill-gate{background:rgba(99,102,241,.14);color:#c7d2fe}.pill-middleware{background:rgba(45,212,191,.12);color:#ccfbf1}.pill-dump,.pill-view{background:rgba(148,163,184,.14);color:#e2e8f0}.pill-client-request{background:rgba(59,130,246,.14);color:#bfdbfe}html[data-theme='light'] .pill-request{color:#1d4ed8}html[data-theme='light'] .pill-request.method-get{color:#166534}html[data-theme='light'] .pill-request.method-post{color:#1d4ed8}html[data-theme='light'] .pill-request.method-other{color:#92400e}html[data-theme='light'] .pill-query{color:#166534}html[data-theme='light'] .pill-exception{color:#b91c1c}html[data-theme='light'] .pill-log{color:#6d28d9}html[data-theme='light'] .pill-job,html[data-theme='light'] .pill-batch{color:#92400e}html[data-theme='light'] .pill-cache{color:#115e59}html[data-theme='light'] .pill-schedule,html[data-theme='light'] .pill-command{color:#0c4a6e}html[data-theme='light'] .pill-mail,html[data-theme='light'] .pill-notification{color:#9d174d}html[data-theme='light'] .pill-auth,html[data-theme='light'] .pill-dump,html[data-theme='light'] .pill-view{color:#334155}html[data-theme='light'] .pill-event,html[data-theme='light'] .pill-model{color:#166534}html[data-theme='light'] .pill-redis{color:#991b1b}html[data-theme='light'] .pill-gate{color:#3730a3}html[data-theme='light'] .pill-middleware{color:#155e75}html[data-theme='light'] .pill-client-request{color:#1d4ed8}
|
|
75
75
|
.monitoring-wrap{padding:0 24px 24px}.tag-list{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:18px}.tag-item{display:inline-flex;align-items:center;gap:10px;padding:10px 14px;border-radius:999px;border:1px solid var(--line);background:var(--surface-strong)}.tag-remove{border:none;background:rgba(239,68,68,.14);color:var(--danger);border-radius:999px;width:24px;height:24px;cursor:pointer;font-size:1rem;line-height:1}.helper-text{color:var(--muted);line-height:1.6}
|
|
76
76
|
.duration-chip{display:inline-flex;align-items:center;padding:5px 9px;border-radius:999px;border:1px solid transparent;font-size:.8rem;font-weight:700;color:var(--text);white-space:nowrap}.duration-chip.vfast{background:rgba(34,197,94,.14);border-color:rgba(34,197,94,.28);color:#bbf7d0}.duration-chip.fast{background:rgba(56,189,248,.12);border-color:rgba(56,189,248,.24);color:#bae6fd}.duration-chip.slow{background:rgba(245,158,11,.12);border-color:rgba(245,158,11,.22);color:#fde68a}.duration-chip.vslow{background:rgba(239,68,68,.14);border-color:rgba(239,68,68,.24);color:#fecaca}html[data-theme='light'] .duration-chip.vfast{color:#166534}html[data-theme='light'] .duration-chip.fast{color:#1d4ed8}html[data-theme='light'] .duration-chip.slow{color:#92400e}html[data-theme='light'] .duration-chip.vslow{color:#b91c1c}
|
|
77
|
-
.code-card{border-radius:16px;border:1px solid var(--code-border);background:var(--surface-soft);overflow:hidden}.code-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 14px;border-bottom:1px solid var(--line)}.code-label{font-size:.76rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:800}.copy-button{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:38px;height:38px;border-radius:12px;border:1px solid var(--line);background:var(--surface-strong);color:var(--text);cursor:pointer;transition:border-color .16s ease,color .16s ease}.copy-button:hover{border-color:rgba(56,189,248,.35);color:var(--accent)}.copy-button[data-copied='true']{color:var(--success);border-color:rgba(34,197,94,.28)}.copy-button svg{width:16px;height:16px;display:block}.code-block{margin:0;padding:18px 20px;background:var(--code-bg);color:#dbeafe;border:0;overflow:auto;white-space:pre;line-height:1.72;font-family:var(--mono);font-size:.92rem}.code-block code{font-family:inherit}.tok-key{color:#93c5fd}.tok-string{color:#86efac}.tok-number{color:#f9a8d4}.tok-boolean{color:#facc15}.tok-null{color:#fb7185}.tok-punctuation{color:#94a3b8}.tok-sql-keyword{color:#f472b6;font-weight:700}.tok-sql-identifier{color:#93c5fd}.tok-sql-string{color:#86efac}.tok-sql-number{color:#facc15}.tok-sql-comment{color:#64748b;font-style:italic}html[data-theme='light'] .code-block{color:#0f172a}html[data-theme='light'] .tok-key{color:#1d4ed8}html[data-theme='light'] .tok-string{color:#15803d}html[data-theme='light'] .tok-number{color:#c026d3}html[data-theme='light'] .tok-boolean{color:#b45309}html[data-theme='light'] .tok-null{color:#dc2626}html[data-theme='light'] .tok-punctuation{color:#64748b}html[data-theme='light'] .tok-sql-keyword{color:#db2777}html[data-theme='light'] .tok-sql-identifier{color:#2563eb}html[data-theme='light'] .tok-sql-string{color:#15803d}html[data-theme='light'] .tok-sql-number{color:#b45309}html[data-theme='light'] .tok-sql-comment{color:#6b7280}
|
|
77
|
+
.code-card{border-radius:16px;border:1px solid var(--code-border);background:var(--surface-soft);overflow:hidden}.code-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 14px;border-bottom:1px solid var(--line)}.code-label{font-size:.76rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:800}.copy-button{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:38px;height:38px;border-radius:12px;border:1px solid var(--line);background:var(--surface-strong);color:var(--text);cursor:pointer;transition:border-color .16s ease,color .16s ease}.copy-button:hover{border-color:rgba(56,189,248,.35);color:var(--accent)}.copy-button[data-copied='true']{color:var(--success);border-color:rgba(34,197,94,.28)}.copy-button svg{width:16px;height:16px;display:block}.code-block{margin:0;padding:18px 20px;background:var(--code-bg);color:#dbeafe;border:0;overflow:auto;white-space:pre;line-height:1.72;font-family:var(--mono);font-size:.92rem}.code-block code{font-family:inherit}.html-preview-wrap{padding:14px;background:var(--surface-strong);border-top:1px solid var(--line)}.html-preview{display:block;width:100%;min-height:320px;border:1px solid var(--line);border-radius:14px;background:#fff}.tok-key{color:#93c5fd}.tok-string{color:#86efac}.tok-number{color:#f9a8d4}.tok-boolean{color:#facc15}.tok-null{color:#fb7185}.tok-punctuation{color:#94a3b8}.tok-sql-keyword{color:#f472b6;font-weight:700}.tok-sql-identifier{color:#93c5fd}.tok-sql-string{color:#86efac}.tok-sql-number{color:#facc15}.tok-sql-comment{color:#64748b;font-style:italic}html[data-theme='light'] .code-block{color:#0f172a}html[data-theme='light'] .tok-key{color:#1d4ed8}html[data-theme='light'] .tok-string{color:#15803d}html[data-theme='light'] .tok-number{color:#c026d3}html[data-theme='light'] .tok-boolean{color:#b45309}html[data-theme='light'] .tok-null{color:#dc2626}html[data-theme='light'] .tok-punctuation{color:#64748b}html[data-theme='light'] .tok-sql-keyword{color:#db2777}html[data-theme='light'] .tok-sql-identifier{color:#2563eb}html[data-theme='light'] .tok-sql-string{color:#15803d}html[data-theme='light'] .tok-sql-number{color:#b45309}html[data-theme='light'] .tok-sql-comment{color:#6b7280}
|
|
78
78
|
@media (max-width:1120px){.content-grid{grid-template-columns:1fr}}@media (max-width:920px){.layout{grid-template-columns:1fr}.sidebar{position:static;height:auto;border-right:none;border-bottom:1px solid var(--line);padding:20px 16px 18px}.brand-row{padding:0 0 16px}.sidebar-status{margin:0 0 16px}.sidebar-group{padding:0}.main{padding:20px}}@media (max-width:640px){.stats-grid{grid-template-columns:1fr}.detail-card{padding:18px}.toolbar,.section-head,.pagination,.activity-list,.monitoring-wrap{padding-left:18px;padding-right:18px}.table-wrap{padding:0 8px 10px}.brand-row{align-items:stretch;gap:14px;padding:0 0 14px}.brand{width:100%;align-items:flex-start}.brand-copy{min-width:0}.brand-copy h1{font-size:1.18rem;line-height:1.12}.brand-copy p{font-size:.82rem;overflow-wrap:anywhere}.icon-button{align-self:flex-end}.sidebar-status{padding:12px}.nav-button{padding:11px 12px}.nav-title{font-size:.95rem}.nav-meta{font-size:.72rem}}@media (max-width:480px){.brand-row{flex-direction:column}.icon-button{align-self:flex-start}.nav-button{align-items:flex-start;flex-direction:column}.nav-meta{font-size:.7rem}}
|
|
79
79
|
</style>
|
|
80
80
|
</head>
|
|
@@ -196,6 +196,8 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
196
196
|
.replace(/"/g, '"')
|
|
197
197
|
.replace(/'/g, ''');
|
|
198
198
|
|
|
199
|
+
const looksLikeHtml = (value) => new RegExp('</?(?:html|body|div|table)\\b|<!doctype\\b', 'i').test(String(value || ''));
|
|
200
|
+
|
|
199
201
|
const api = async (path, opts) => {
|
|
200
202
|
const response = await fetch(API + path, opts);
|
|
201
203
|
if (!response.ok) {
|
|
@@ -335,6 +337,28 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
335
337
|
].join('');
|
|
336
338
|
};
|
|
337
339
|
|
|
340
|
+
const renderTextCard = (label, value) => {
|
|
341
|
+
const source = String(value ?? '');
|
|
342
|
+
return renderCodeCard(label, source, escapeHtml(source), 'language-text');
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const renderHtmlPreview = (label, html) => {
|
|
346
|
+
const source = String(html ?? '');
|
|
347
|
+
const copyId = registerCopyPayload(source);
|
|
348
|
+
return [
|
|
349
|
+
'<section class="code-card">',
|
|
350
|
+
'<div class="code-toolbar">',
|
|
351
|
+
'<span class="code-label">' + escapeHtml(label) + '</span>',
|
|
352
|
+
'<button type="button" class="copy-button" data-action="copy-code" data-copy-id="' + escapeHtml(copyId) + '" title="Copy ' + escapeHtml(label) + '">',
|
|
353
|
+
COPY_ICON,
|
|
354
|
+
'</button>',
|
|
355
|
+
'</div>',
|
|
356
|
+
'<pre class="code-block language-html"><code>' + escapeHtml(source) + '</code></pre>',
|
|
357
|
+
'<div class="html-preview-wrap"><iframe class="html-preview" sandbox="allow-same-origin" srcdoc="' + escapeHtml(source) + '"></iframe></div>',
|
|
358
|
+
'</section>'
|
|
359
|
+
].join('');
|
|
360
|
+
};
|
|
361
|
+
|
|
338
362
|
const highlightJson = (value, label = 'JSON') => {
|
|
339
363
|
const source = prettyJson(value);
|
|
340
364
|
let output = '';
|
|
@@ -386,6 +410,14 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
386
410
|
|
|
387
411
|
const detailJson = (value, label = 'JSON') => highlightJson(value ?? {}, label);
|
|
388
412
|
|
|
413
|
+
const renderPayload = (label, value) => {
|
|
414
|
+
if (value === undefined) return '<p class="trace-note">No ' + escapeHtml(label.toLowerCase()) + ' was captured.</p>';
|
|
415
|
+
if (typeof value === 'string') {
|
|
416
|
+
return looksLikeHtml(value) ? renderHtmlPreview(label, value) : renderTextCard(label, value);
|
|
417
|
+
}
|
|
418
|
+
return detailJson(value, label);
|
|
419
|
+
};
|
|
420
|
+
|
|
389
421
|
const entrySummaryText = (entry) => {
|
|
390
422
|
const content = entry && entry.content ? entry.content : {};
|
|
391
423
|
if (entry.type === 'request') return [content.responseStatus || '', content.method || '', content.uri || ''].filter(Boolean).join(' ');
|
|
@@ -393,20 +425,20 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
393
425
|
if (entry.type === 'exception') return [content.class || '', content.message || ''].filter(Boolean).join(': ');
|
|
394
426
|
if (entry.type === 'log') return '[' + String(content.level || 'log') + '] ' + String(content.message || '').slice(0, 160);
|
|
395
427
|
if (entry.type === 'job') return [content.name || '', content.status || 'queued'].filter(Boolean).join(' · ');
|
|
396
|
-
if (entry.type === 'cache') return [content.operation || '', content.key || ''].filter(Boolean).join(' ');
|
|
428
|
+
if (entry.type === 'cache') return [content.operation || '', content.key || '', content.payloadLogged ? '' : '(payload off)'].filter(Boolean).join(' ');
|
|
397
429
|
if (entry.type === 'schedule') return [content.name || '', content.status || 'ran'].filter(Boolean).join(' · ');
|
|
398
430
|
if (entry.type === 'mail') return ['To ' + (content.to || 'unknown'), content.subject || 'No subject'].join(' · ');
|
|
399
431
|
if (entry.type === 'auth') return [content.event || 'auth', content.userId ? '#' + content.userId : ''].filter(Boolean).join(' ');
|
|
400
432
|
if (entry.type === 'event') return String(content.name || 'event');
|
|
401
433
|
if (entry.type === 'model') return [content.action || '', content.model || ''].filter(Boolean).join(' ');
|
|
402
|
-
if (entry.type === 'notification') return [content.notification || '', (content.channels || []).join(', ')].filter(Boolean).join(' -> ');
|
|
434
|
+
if (entry.type === 'notification') return [content.notification || '', content.message || (content.channels || []).join(', ')].filter(Boolean).join(' -> ');
|
|
403
435
|
if (entry.type === 'redis') return String(content.command || 'redis');
|
|
404
436
|
if (entry.type === 'gate') return [content.ability || '', content.result || ''].filter(Boolean).join(' · ');
|
|
405
437
|
if (entry.type === 'middleware') return [content.name || '', content.event || ''].filter(Boolean).join(' · ');
|
|
406
438
|
if (entry.type === 'command') return [content.name || '', content.exitCode !== undefined ? 'exit=' + content.exitCode : ''].filter(Boolean).join(' ');
|
|
407
439
|
if (entry.type === 'batch') return [content.name || '', 'processed ' + (content.processed || 0) + '/' + (content.total || 0)].join(' · ');
|
|
408
440
|
if (entry.type === 'view') return String(content.template || 'view');
|
|
409
|
-
if (entry.type === 'client_request') return [content.method || '', content.url || ''].filter(Boolean).join(' ');
|
|
441
|
+
if (entry.type === 'client_request') return [content.method || '', content.url || '', content.responseStatus ? '[' + content.responseStatus + ']' : content.error ? '[failed]' : ''].filter(Boolean).join(' ');
|
|
410
442
|
return JSON.stringify(content).slice(0, 160);
|
|
411
443
|
};
|
|
412
444
|
|
|
@@ -442,6 +474,7 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
442
474
|
{ label: 'Connection', value: escapeHtml(content.connection || 'default') },
|
|
443
475
|
{ label: 'Duration', value: escapeHtml(formatDuration(getEntryDuration(entry))) },
|
|
444
476
|
{ label: 'Slow', value: escapeHtml(content.slow ? 'Yes' : 'No') },
|
|
477
|
+
{ label: 'Bindings', value: escapeHtml(content.bindingsIncluded === false ? 'Hidden' : 'Included') },
|
|
445
478
|
{ label: 'Hash', value: '<span class="mono">' + escapeHtml(content.hash || '') + '</span>' }
|
|
446
479
|
]),
|
|
447
480
|
renderMetricBox('Runtime', [
|
|
@@ -449,7 +482,8 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
449
482
|
{ label: 'Batch', value: '<span class="mono">' + escapeHtml(entry.batchId || '-') + '</span>' }
|
|
450
483
|
]),
|
|
451
484
|
'</div>',
|
|
452
|
-
highlightSql(content.sql || '')
|
|
485
|
+
highlightSql(content.sql || ''),
|
|
486
|
+
content.bindingsIncluded === false ? '<p class="trace-note">SQL bindings were hidden for this entry.</p>' : (Array.isArray(content.bindings) ? detailJson(content.bindings, 'Bindings Json') : '')
|
|
453
487
|
].join('');
|
|
454
488
|
}
|
|
455
489
|
|
|
@@ -493,7 +527,34 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
493
527
|
renderMetricBox('Request', [
|
|
494
528
|
{ label: 'Method', value: escapeHtml(content.method || '') },
|
|
495
529
|
{ label: 'URL', value: '<span class="mono">' + escapeHtml(content.url || '') + '</span>' },
|
|
496
|
-
{ label: 'Status', value: escapeHtml(content.responseStatus || '') },
|
|
530
|
+
{ label: 'Status', value: escapeHtml(content.responseStatus || (content.error ? 'Failed' : 'Pending')) },
|
|
531
|
+
{ label: 'Duration', value: escapeHtml(formatDuration(getEntryDuration(entry))) }
|
|
532
|
+
]),
|
|
533
|
+
renderMetricBox('Runtime', [
|
|
534
|
+
{ label: 'Hostname', value: escapeHtml(content.hostname || '') },
|
|
535
|
+
{ label: 'Batch', value: '<span class="mono">' + escapeHtml(entry.batchId || '-') + '</span>' },
|
|
536
|
+
{ label: 'Error', value: escapeHtml(content.error || '-') }
|
|
537
|
+
]),
|
|
538
|
+
'</div>',
|
|
539
|
+
'<div class="detail-stack">',
|
|
540
|
+
detailJson(content.requestHeaders || {}, 'Request Header Json'),
|
|
541
|
+
renderPayload('Request Body', content.requestBody),
|
|
542
|
+
detailJson(content.responseHeaders || {}, 'Response Header Json'),
|
|
543
|
+
renderPayload('Response Body', content.responseBody),
|
|
544
|
+
'</div>'
|
|
545
|
+
].join('');
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (entry.type === 'cache') {
|
|
549
|
+
return [
|
|
550
|
+
'<div class="detail-grid">',
|
|
551
|
+
renderMetricBox('Cache', [
|
|
552
|
+
{ label: 'Operation', value: escapeHtml(content.operation || '') },
|
|
553
|
+
{ label: 'Key', value: '<span class="mono">' + escapeHtml(content.key || '') + '</span>' },
|
|
554
|
+
{ label: 'Store', value: escapeHtml(content.store || 'default') },
|
|
555
|
+
{ label: 'Hit', value: escapeHtml(content.hit === undefined ? '-' : (content.hit ? 'Yes' : 'No')) },
|
|
556
|
+
{ label: 'Payload', value: escapeHtml(content.payloadLogged ? 'Captured' : 'Disabled') },
|
|
557
|
+
{ label: 'TTL', value: escapeHtml(content.ttl === undefined ? '-' : String(content.ttl)) },
|
|
497
558
|
{ label: 'Duration', value: escapeHtml(formatDuration(getEntryDuration(entry))) }
|
|
498
559
|
]),
|
|
499
560
|
renderMetricBox('Runtime', [
|
|
@@ -501,7 +562,41 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
501
562
|
{ label: 'Batch', value: '<span class="mono">' + escapeHtml(entry.batchId || '-') + '</span>' }
|
|
502
563
|
]),
|
|
503
564
|
'</div>',
|
|
504
|
-
|
|
565
|
+
content.payloadLogged ? renderPayload('Cache Payload', content.payload) : '<p class="trace-note">Cache payload logging is disabled. Set TRACE_CACHE_PAYLOADS=true to include values.</p>'
|
|
566
|
+
].join('');
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
if (entry.type === 'mail') {
|
|
570
|
+
return [
|
|
571
|
+
'<div class="detail-grid">',
|
|
572
|
+
renderMetricBox('Mail', [
|
|
573
|
+
{ label: 'To', value: escapeHtml(content.to || '') },
|
|
574
|
+
{ label: 'Subject', value: escapeHtml(content.subject || '') },
|
|
575
|
+
{ label: 'Template', value: escapeHtml(content.template || '-') },
|
|
576
|
+
{ label: 'Hostname', value: escapeHtml(content.hostname || '') }
|
|
577
|
+
]),
|
|
578
|
+
'</div>',
|
|
579
|
+
'<div class="detail-stack">',
|
|
580
|
+
renderPayload('Mail Text', content.text),
|
|
581
|
+
renderPayload('Mail Html', content.html),
|
|
582
|
+
'</div>'
|
|
583
|
+
].join('');
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (entry.type === 'notification') {
|
|
587
|
+
return [
|
|
588
|
+
'<div class="detail-grid">',
|
|
589
|
+
renderMetricBox('Notification', [
|
|
590
|
+
{ label: 'Notification', value: escapeHtml(content.notification || '') },
|
|
591
|
+
{ label: 'Channels', value: escapeHtml((content.channels || []).join(', ') || '-') },
|
|
592
|
+
{ label: 'Recipient', value: escapeHtml(content.notifiable || '-') },
|
|
593
|
+
{ label: 'Hostname', value: escapeHtml(content.hostname || '') }
|
|
594
|
+
]),
|
|
595
|
+
'</div>',
|
|
596
|
+
'<div class="detail-stack">',
|
|
597
|
+
renderPayload('Message', content.message),
|
|
598
|
+
content.payload === undefined ? '<p class="trace-note">No additional notification payload was captured.</p>' : detailJson(content.payload, 'Notification Payload Json'),
|
|
599
|
+
'</div>'
|
|
505
600
|
].join('');
|
|
506
601
|
}
|
|
507
602
|
|
package/dist/register.js
CHANGED
|
@@ -64,6 +64,17 @@ const resolveTraceConnectionName = (env, configuredConnection) => {
|
|
|
64
64
|
}
|
|
65
65
|
return resolveDefaultConnection();
|
|
66
66
|
};
|
|
67
|
+
const resolveObservedConnectionName = (env, configuredObservedConnection, storageConnectionName) => {
|
|
68
|
+
if (typeof configuredObservedConnection === 'string' &&
|
|
69
|
+
configuredObservedConnection.trim() !== '') {
|
|
70
|
+
return resolveTraceConnectionName(env, configuredObservedConnection);
|
|
71
|
+
}
|
|
72
|
+
const defaultConnectionName = resolveTraceConnectionName(env, undefined);
|
|
73
|
+
if (storageConnectionName !== defaultConnectionName) {
|
|
74
|
+
return defaultConnectionName;
|
|
75
|
+
}
|
|
76
|
+
return storageConnectionName;
|
|
77
|
+
};
|
|
67
78
|
const isObjectValue = (value) => {
|
|
68
79
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
69
80
|
};
|
|
@@ -90,6 +101,16 @@ const parseEnvList = (rawValue) => {
|
|
|
90
101
|
.map((entry) => entry.trim())
|
|
91
102
|
.filter((entry) => entry !== '');
|
|
92
103
|
};
|
|
104
|
+
const parseEnvBool = (rawValue) => {
|
|
105
|
+
const value = rawValue.trim().toLowerCase();
|
|
106
|
+
if (value === '')
|
|
107
|
+
return undefined;
|
|
108
|
+
if (['1', 'true', 'yes', 'on'].includes(value))
|
|
109
|
+
return true;
|
|
110
|
+
if (['0', 'false', 'no', 'off'].includes(value))
|
|
111
|
+
return false;
|
|
112
|
+
return undefined;
|
|
113
|
+
};
|
|
93
114
|
const resolveTraceStartupOverrides = (core) => {
|
|
94
115
|
const traceConfigFile = core.StartupConfigFile?.Trace;
|
|
95
116
|
if (typeof traceConfigFile !== 'string' || traceConfigFile.trim() === '')
|
|
@@ -136,14 +157,18 @@ if (!traceAlreadyInitialized && Env) {
|
|
|
136
157
|
const enabled = startupOverrides?.enabled === true || Env.getBool('TRACE_ENABLED', false);
|
|
137
158
|
if (enabled) {
|
|
138
159
|
const connectionRaw = Env.get('TRACE_DB_CONNECTION', '').trim();
|
|
160
|
+
const observeConnectionRaw = Env.get('TRACE_QUERY_CONNECTION', '').trim();
|
|
139
161
|
const pruneAfterHoursRaw = Env.get('TRACE_PRUNE_HOURS', '').trim();
|
|
140
162
|
const slowQueryThresholdRaw = Env.get('TRACE_SLOW_QUERY_MS', '').trim();
|
|
141
163
|
const logMinLevelRaw = Env.get('TRACE_LOG_LEVEL', '').trim();
|
|
164
|
+
const captureCachePayloadsRaw = Env.get('TRACE_CACHE_PAYLOADS', '').trim();
|
|
165
|
+
const captureQueryBindingsRaw = Env.get('TRACE_QUERY_BINDINGS', '').trim();
|
|
142
166
|
const redactionKeys = parseEnvList(Env.get('TRACE_REDACT_KEYS', ''));
|
|
143
167
|
const redactionHeaders = parseEnvList(Env.get('TRACE_REDACT_HEADERS', ''));
|
|
144
168
|
const redactionBody = parseEnvList(Env.get('TRACE_REDACT_BODY', ''));
|
|
145
169
|
const redactionQuery = parseEnvList(Env.get('TRACE_REDACT_QUERY', ''));
|
|
146
170
|
const connection = connectionRaw === '' ? startupOverrides?.connection : connectionRaw;
|
|
171
|
+
const observeConnection = observeConnectionRaw === '' ? startupOverrides?.observeConnection : observeConnectionRaw;
|
|
147
172
|
const pruneAfterHours = pruneAfterHoursRaw === ''
|
|
148
173
|
? startupOverrides?.pruneAfterHours
|
|
149
174
|
: Number.parseInt(pruneAfterHoursRaw, 10);
|
|
@@ -151,6 +176,8 @@ if (!traceAlreadyInitialized && Env) {
|
|
|
151
176
|
? startupOverrides?.slowQueryThreshold
|
|
152
177
|
: Number.parseInt(slowQueryThresholdRaw, 10);
|
|
153
178
|
const logMinLevel = (logMinLevelRaw === '' ? startupOverrides?.logMinLevel : logMinLevelRaw);
|
|
179
|
+
const captureCachePayloads = parseEnvBool(captureCachePayloadsRaw) ?? startupOverrides?.captureCachePayloads;
|
|
180
|
+
const captureQueryBindings = parseEnvBool(captureQueryBindingsRaw) ?? startupOverrides?.captureQueryBindings;
|
|
154
181
|
const redaction = buildTraceRedactionOverrides({
|
|
155
182
|
startupOverrides,
|
|
156
183
|
redactionBody,
|
|
@@ -162,19 +189,24 @@ if (!traceAlreadyInitialized && Env) {
|
|
|
162
189
|
...startupOverrides,
|
|
163
190
|
enabled,
|
|
164
191
|
connection,
|
|
192
|
+
observeConnection,
|
|
165
193
|
...(typeof pruneAfterHours === 'number' && Number.isFinite(pruneAfterHours)
|
|
166
194
|
? { pruneAfterHours }
|
|
167
195
|
: {}),
|
|
168
196
|
...(typeof slowQueryThreshold === 'number' && Number.isFinite(slowQueryThreshold)
|
|
169
197
|
? { slowQueryThreshold }
|
|
170
198
|
: {}),
|
|
199
|
+
...(typeof captureCachePayloads === 'boolean' ? { captureCachePayloads } : {}),
|
|
200
|
+
...(typeof captureQueryBindings === 'boolean' ? { captureQueryBindings } : {}),
|
|
171
201
|
logMinLevel,
|
|
172
202
|
...(redaction === undefined ? {} : { redaction }),
|
|
173
203
|
});
|
|
174
204
|
const resolvedConnectionName = resolveTraceConnectionName(Env, config.connection);
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
205
|
+
const resolvedObservedConnectionName = resolveObservedConnectionName(Env, config.observeConnection, resolvedConnectionName);
|
|
206
|
+
const storageDb = core.useDatabase?.(undefined, resolvedConnectionName);
|
|
207
|
+
const observedDb = core.useDatabase?.(undefined, resolvedObservedConnectionName);
|
|
208
|
+
if (storageDb && observedDb) {
|
|
209
|
+
const storage = TraceWriteDiagnostics.wrapStorage(TraceContentRedaction.wrapStorage(TraceEntryFiltering.wrapStorage(TraceStorage.resolveStorage(storageDb), config), config.redaction), {
|
|
178
210
|
connectionName: resolvedConnectionName,
|
|
179
211
|
logger: core.Logger,
|
|
180
212
|
});
|
|
@@ -203,7 +235,7 @@ if (!traceAlreadyInitialized && Env) {
|
|
|
203
235
|
import('./watchers/ViewWatcher.js'),
|
|
204
236
|
import('./watchers/HttpClientWatcher.js'),
|
|
205
237
|
]);
|
|
206
|
-
const watcherArgs = { storage, config, db };
|
|
238
|
+
const watcherArgs = { storage, config, db: observedDb };
|
|
207
239
|
HttpWatcher.register({ ...watcherArgs, registerMiddleware: resolveRegisterMiddleware() });
|
|
208
240
|
QueryWatcher.register(watcherArgs);
|
|
209
241
|
LogWatcher.register(watcherArgs);
|
package/dist/types.d.ts
CHANGED
|
@@ -43,6 +43,9 @@ export interface RequestContent {
|
|
|
43
43
|
export interface QueryContent {
|
|
44
44
|
connection: string;
|
|
45
45
|
sql: string;
|
|
46
|
+
statement?: string;
|
|
47
|
+
bindings?: unknown[];
|
|
48
|
+
bindingsIncluded?: boolean;
|
|
46
49
|
time: number;
|
|
47
50
|
duration: number;
|
|
48
51
|
slow: boolean;
|
|
@@ -91,6 +94,10 @@ export interface CacheContent {
|
|
|
91
94
|
operation: 'get' | 'set' | 'delete' | 'clear' | 'has';
|
|
92
95
|
key: string;
|
|
93
96
|
hit?: boolean;
|
|
97
|
+
store?: string;
|
|
98
|
+
payload?: unknown;
|
|
99
|
+
payloadLogged?: boolean;
|
|
100
|
+
ttl?: number;
|
|
94
101
|
duration: number;
|
|
95
102
|
hostname: string;
|
|
96
103
|
}
|
|
@@ -106,6 +113,8 @@ export interface MailContent {
|
|
|
106
113
|
to: string;
|
|
107
114
|
subject: string;
|
|
108
115
|
template?: string;
|
|
116
|
+
text?: string;
|
|
117
|
+
html?: string;
|
|
109
118
|
hostname: string;
|
|
110
119
|
}
|
|
111
120
|
export interface AuthContent {
|
|
@@ -130,6 +139,8 @@ export interface NotificationContent {
|
|
|
130
139
|
channels: string[];
|
|
131
140
|
notifiable?: string;
|
|
132
141
|
notification: string;
|
|
142
|
+
message?: string;
|
|
143
|
+
payload?: unknown;
|
|
133
144
|
hostname: string;
|
|
134
145
|
}
|
|
135
146
|
export interface RedisContent {
|
|
@@ -181,10 +192,25 @@ export interface ClientRequestContent {
|
|
|
181
192
|
method: string;
|
|
182
193
|
url: string;
|
|
183
194
|
requestHeaders: Record<string, string>;
|
|
184
|
-
|
|
195
|
+
requestBody?: unknown;
|
|
196
|
+
responseStatus?: number;
|
|
197
|
+
responseHeaders?: Record<string, string>;
|
|
198
|
+
responseBody?: unknown;
|
|
199
|
+
error?: string;
|
|
185
200
|
duration: number;
|
|
186
201
|
hostname: string;
|
|
187
202
|
}
|
|
203
|
+
export interface ClientRequestTraceInput {
|
|
204
|
+
method: string;
|
|
205
|
+
url: string;
|
|
206
|
+
requestHeaders: Record<string, string>;
|
|
207
|
+
responseStatus?: number;
|
|
208
|
+
duration: number;
|
|
209
|
+
requestBody?: unknown;
|
|
210
|
+
responseHeaders?: Record<string, string>;
|
|
211
|
+
responseBody?: unknown;
|
|
212
|
+
error?: string;
|
|
213
|
+
}
|
|
188
214
|
export interface ITraceEntry<T = unknown> {
|
|
189
215
|
uuid: string;
|
|
190
216
|
batchId: string;
|
|
@@ -277,9 +303,12 @@ export type WatcherToggles = {
|
|
|
277
303
|
export interface ITraceConfig {
|
|
278
304
|
enabled: boolean;
|
|
279
305
|
connection?: string;
|
|
306
|
+
observeConnection?: string;
|
|
280
307
|
pruneAfterHours: number;
|
|
281
308
|
ignoreRoutes: string[];
|
|
282
309
|
slowQueryThreshold: number;
|
|
310
|
+
captureCachePayloads: boolean;
|
|
311
|
+
captureQueryBindings: boolean;
|
|
283
312
|
logMinLevel: 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
284
313
|
watchers: WatcherToggles;
|
|
285
314
|
redaction: RedactionConfig;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CacheContent, ITraceWatcher } from '../types';
|
|
2
|
-
declare const emit: (operation: CacheContent["operation"], key: string, duration: number, hit?: boolean) => void;
|
|
2
|
+
declare const emit: (operation: CacheContent["operation"], key: string, duration: number, hit?: boolean, payload?: unknown, store?: string, ttl?: number) => void;
|
|
3
3
|
export declare const CacheWatcher: ITraceWatcher & {
|
|
4
4
|
emit: typeof emit;
|
|
5
5
|
};
|