@zintrust/trace 0.4.75 → 0.4.77
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 +101 -15
- package/dist/build-manifest.json +210 -162
- package/dist/config.d.ts +1 -0
- package/dist/config.js +123 -4
- package/dist/dashboard/routes.js +4 -4
- package/dist/dashboard/ui.js +80 -23
- package/dist/index.d.ts +2 -0
- package/dist/index.js +30 -25
- package/dist/migrations/{20260331000001_create_zin_debugger_entries_table.d.ts → 20260331000001_create_zin_trace_entries_table.d.ts} +2 -2
- package/dist/migrations/{20260331000001_create_zin_debugger_entries_table.js → 20260331000001_create_zin_trace_entries_table.js} +5 -5
- package/dist/migrations/{20260331000002_create_zin_debugger_entries_tags_table.d.ts → 20260331000002_create_zin_trace_entries_tags_table.d.ts} +2 -2
- package/dist/migrations/{20260331000002_create_zin_debugger_entries_tags_table.js → 20260331000002_create_zin_trace_entries_tags_table.js} +5 -5
- package/dist/migrations/{20260331000003_create_zin_debugger_monitoring_table.d.ts → 20260331000003_create_zin_trace_monitoring_table.d.ts} +2 -2
- package/dist/migrations/{20260331000003_create_zin_debugger_monitoring_table.js → 20260331000003_create_zin_trace_monitoring_table.js} +4 -4
- package/dist/migrations/20260407193000_widen_trace_created_at_for_sql.d.ts +10 -0
- package/dist/migrations/20260407193000_widen_trace_created_at_for_sql.js +34 -0
- package/dist/migrations/index.d.ts +3 -3
- package/dist/migrations/index.js +5 -4
- package/dist/register.js +130 -32
- package/dist/storage/DebuggerStorage.js +1 -1
- package/dist/storage/TraceContentRedaction.d.ts +4 -0
- package/dist/storage/TraceContentRedaction.js +33 -0
- package/dist/storage/TraceEntryFiltering.d.ts +4 -0
- package/dist/storage/TraceEntryFiltering.js +13 -0
- package/dist/storage/TraceStorage.js +36 -6
- package/dist/storage/TraceWriteDiagnostics.d.ts +19 -0
- package/dist/storage/TraceWriteDiagnostics.js +98 -0
- package/dist/storage/index.js +1 -1
- package/dist/types.d.ts +37 -20
- package/dist/ui.js +1 -1
- package/dist/utils/authTag.js +1 -1
- package/dist/utils/entryFilter.d.ts +4 -0
- package/dist/utils/entryFilter.js +95 -0
- package/dist/utils/redact.d.ts +1 -0
- package/dist/utils/redact.js +43 -9
- package/dist/utils/requestFilter.js +1 -1
- package/dist/watchers/AuthWatcher.js +3 -3
- package/dist/watchers/BatchWatcher.js +3 -3
- package/dist/watchers/CacheWatcher.js +5 -5
- package/dist/watchers/CommandWatcher.js +5 -5
- package/dist/watchers/DumpWatcher.js +3 -3
- package/dist/watchers/EventWatcher.js +4 -4
- package/dist/watchers/ExceptionWatcher.js +6 -6
- package/dist/watchers/GateWatcher.js +3 -3
- package/dist/watchers/HttpClientWatcher.js +6 -6
- package/dist/watchers/HttpWatcher.js +108 -24
- package/dist/watchers/JobWatcher.js +4 -4
- package/dist/watchers/LogWatcher.js +5 -4
- package/dist/watchers/MailWatcher.js +3 -3
- package/dist/watchers/MiddlewareWatcher.js +3 -3
- package/dist/watchers/ModelWatcher.js +3 -3
- package/dist/watchers/NotificationWatcher.js +4 -4
- package/dist/watchers/QueryWatcher.js +5 -5
- package/dist/watchers/RedisWatcher.js +4 -4
- package/dist/watchers/ScheduleWatcher.js +3 -3
- package/dist/watchers/ViewWatcher.js +3 -3
- package/package.json +4 -4
- package/src/config.ts +152 -5
- package/src/dashboard/routes.ts +6 -2
- package/src/dashboard/ui.ts +80 -23
- package/src/index.ts +7 -0
- package/src/register.ts +137 -10
- package/src/storage/TraceContentRedaction.ts +44 -0
- package/src/storage/TraceEntryFiltering.ts +14 -0
- package/src/storage/TraceStorage.ts +52 -5
- package/src/storage/TraceWriteDiagnostics.ts +174 -0
- package/src/types.ts +40 -20
- package/src/utils/entryFilter.ts +108 -0
- package/src/utils/redact.ts +57 -9
- package/src/watchers/CommandWatcher.ts +1 -1
- package/src/watchers/HttpClientWatcher.ts +1 -1
- package/src/watchers/HttpWatcher.ts +132 -21
- package/src/watchers/LogWatcher.ts +27 -27
package/dist/config.js
CHANGED
|
@@ -1,3 +1,78 @@
|
|
|
1
|
+
const mergeStringLists = (base, override) => {
|
|
2
|
+
const merged = new Set();
|
|
3
|
+
for (const value of [...base, ...(override ?? [])]) {
|
|
4
|
+
if (typeof value !== 'string')
|
|
5
|
+
continue;
|
|
6
|
+
const normalized = value.trim();
|
|
7
|
+
if (normalized !== '')
|
|
8
|
+
merged.add(normalized);
|
|
9
|
+
}
|
|
10
|
+
return [...merged];
|
|
11
|
+
};
|
|
12
|
+
const isObjectValue = (value) => {
|
|
13
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
|
+
};
|
|
15
|
+
const mergeFilterRule = (base, override) => {
|
|
16
|
+
const include = mergeStringLists(base?.include ?? [], override?.include);
|
|
17
|
+
const exclude = mergeStringLists(base?.exclude ?? [], override?.exclude);
|
|
18
|
+
if (include.length === 0 && exclude.length === 0)
|
|
19
|
+
return undefined;
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
...(include.length > 0 ? { include } : {}),
|
|
22
|
+
...(exclude.length > 0 ? { exclude } : {}),
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
const mergeWatcherToggle = (base, override) => {
|
|
26
|
+
if (override === undefined)
|
|
27
|
+
return base;
|
|
28
|
+
if (override === false || override === true)
|
|
29
|
+
return override;
|
|
30
|
+
const baseRule = isObjectValue(base) ? base : undefined;
|
|
31
|
+
return mergeFilterRule(baseRule, override);
|
|
32
|
+
};
|
|
33
|
+
const REQUEST_METHOD_KEYS = ['all', 'get', 'post', 'put', 'patch', 'delete'];
|
|
34
|
+
const mergeRequestWatcherToggle = (base, override) => {
|
|
35
|
+
if (override === undefined)
|
|
36
|
+
return base;
|
|
37
|
+
if (override === false || override === true)
|
|
38
|
+
return override;
|
|
39
|
+
const baseConfig = isObjectValue(base) ? base : undefined;
|
|
40
|
+
const merged = mergeFilterRule(baseConfig, override) ?? {};
|
|
41
|
+
for (const key of REQUEST_METHOD_KEYS) {
|
|
42
|
+
const rule = mergeFilterRule(baseConfig?.[key], override[key]);
|
|
43
|
+
if (rule !== undefined)
|
|
44
|
+
merged[key] = rule;
|
|
45
|
+
}
|
|
46
|
+
return merged;
|
|
47
|
+
};
|
|
48
|
+
const mergeWatchers = (base, override) => {
|
|
49
|
+
if (override === undefined)
|
|
50
|
+
return { ...base };
|
|
51
|
+
return {
|
|
52
|
+
...base,
|
|
53
|
+
...override,
|
|
54
|
+
request: mergeRequestWatcherToggle(base.request, override.request),
|
|
55
|
+
query: mergeWatcherToggle(base.query, override.query),
|
|
56
|
+
exception: mergeWatcherToggle(base.exception, override.exception),
|
|
57
|
+
log: mergeWatcherToggle(base.log, override.log),
|
|
58
|
+
job: mergeWatcherToggle(base.job, override.job),
|
|
59
|
+
cache: mergeWatcherToggle(base.cache, override.cache),
|
|
60
|
+
schedule: mergeWatcherToggle(base.schedule, override.schedule),
|
|
61
|
+
mail: mergeWatcherToggle(base.mail, override.mail),
|
|
62
|
+
auth: mergeWatcherToggle(base.auth, override.auth),
|
|
63
|
+
event: mergeWatcherToggle(base.event, override.event),
|
|
64
|
+
model: mergeWatcherToggle(base.model, override.model),
|
|
65
|
+
notification: mergeWatcherToggle(base.notification, override.notification),
|
|
66
|
+
redis: mergeWatcherToggle(base.redis, override.redis),
|
|
67
|
+
gate: mergeWatcherToggle(base.gate, override.gate),
|
|
68
|
+
middleware: mergeWatcherToggle(base.middleware, override.middleware),
|
|
69
|
+
command: mergeWatcherToggle(base.command, override.command),
|
|
70
|
+
batch: mergeWatcherToggle(base.batch, override.batch),
|
|
71
|
+
dump: mergeWatcherToggle(base.dump, override.dump),
|
|
72
|
+
view: mergeWatcherToggle(base.view, override.view),
|
|
73
|
+
clientRequest: mergeWatcherToggle(base.clientRequest, override.clientRequest),
|
|
74
|
+
};
|
|
75
|
+
};
|
|
1
76
|
const DEFAULTS = Object.freeze({
|
|
2
77
|
enabled: false,
|
|
3
78
|
connection: undefined,
|
|
@@ -7,6 +82,37 @@ const DEFAULTS = Object.freeze({
|
|
|
7
82
|
logMinLevel: 'info',
|
|
8
83
|
watchers: {},
|
|
9
84
|
redaction: {
|
|
85
|
+
keys: [
|
|
86
|
+
'password',
|
|
87
|
+
'pass',
|
|
88
|
+
'passwd',
|
|
89
|
+
'token',
|
|
90
|
+
'accessToken',
|
|
91
|
+
'access_token',
|
|
92
|
+
'refreshToken',
|
|
93
|
+
'refresh_token',
|
|
94
|
+
'secret',
|
|
95
|
+
'secretKey',
|
|
96
|
+
'secret_key',
|
|
97
|
+
'apiKey',
|
|
98
|
+
'api_key',
|
|
99
|
+
'auth',
|
|
100
|
+
'authToken',
|
|
101
|
+
'auth_token',
|
|
102
|
+
'authorization',
|
|
103
|
+
'cookie',
|
|
104
|
+
'session',
|
|
105
|
+
'sessionId',
|
|
106
|
+
'session_id',
|
|
107
|
+
'card',
|
|
108
|
+
'cardNumber',
|
|
109
|
+
'card_number',
|
|
110
|
+
'cardToken',
|
|
111
|
+
'card_token',
|
|
112
|
+
'cvv',
|
|
113
|
+
'cvc',
|
|
114
|
+
'pan',
|
|
115
|
+
],
|
|
10
116
|
headers: ['authorization', 'cookie', 'x-api-key', 'x-auth-token'],
|
|
11
117
|
body: ['password', 'token', 'secret', 'apiKey', 'api_key', 'jwt', 'bearer'],
|
|
12
118
|
query: [],
|
|
@@ -14,7 +120,17 @@ const DEFAULTS = Object.freeze({
|
|
|
14
120
|
});
|
|
15
121
|
const isWatcherEnabled = (config, key) => {
|
|
16
122
|
const override = config.watchers[key];
|
|
17
|
-
|
|
123
|
+
if (override === false)
|
|
124
|
+
return false;
|
|
125
|
+
if (isObjectValue(override) && override.enabled === false)
|
|
126
|
+
return false;
|
|
127
|
+
return true; // undefined = enabled by default; explicit false = disabled
|
|
128
|
+
};
|
|
129
|
+
const getRedactionFields = (config, key) => {
|
|
130
|
+
if (key === 'keys') {
|
|
131
|
+
return mergeStringLists([], config.redaction.keys);
|
|
132
|
+
}
|
|
133
|
+
return mergeStringLists(config.redaction.keys, config.redaction[key]);
|
|
18
134
|
};
|
|
19
135
|
export const TraceConfig = Object.freeze({
|
|
20
136
|
defaults() {
|
|
@@ -26,13 +142,16 @@ export const TraceConfig = Object.freeze({
|
|
|
26
142
|
return Object.freeze({
|
|
27
143
|
...DEFAULTS,
|
|
28
144
|
...overrides,
|
|
29
|
-
watchers:
|
|
145
|
+
watchers: mergeWatchers(DEFAULTS.watchers, overrides.watchers),
|
|
30
146
|
redaction: {
|
|
31
|
-
|
|
32
|
-
|
|
147
|
+
keys: mergeStringLists(DEFAULTS.redaction.keys, overrides.redaction?.keys),
|
|
148
|
+
headers: mergeStringLists(DEFAULTS.redaction.headers, overrides.redaction?.headers),
|
|
149
|
+
body: mergeStringLists(DEFAULTS.redaction.body, overrides.redaction?.body),
|
|
150
|
+
query: mergeStringLists(DEFAULTS.redaction.query, overrides.redaction?.query),
|
|
33
151
|
},
|
|
34
152
|
ignoreRoutes: overrides.ignoreRoutes ?? DEFAULTS.ignoreRoutes,
|
|
35
153
|
});
|
|
36
154
|
},
|
|
155
|
+
getRedactionFields,
|
|
37
156
|
isWatcherEnabled,
|
|
38
157
|
});
|
package/dist/dashboard/routes.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Auth is NOT applied here — callers add middleware via routeOptions.
|
|
5
5
|
*/
|
|
6
6
|
import { appConfig, Router, useDatabase } from '@zintrust/core';
|
|
7
|
-
import { TraceConfig } from '../config';
|
|
8
|
-
import { TraceStorage } from '../storage';
|
|
9
|
-
import { addMonitoring, clearEntries, getBatch, getEntry, getMonitoring, getStats, listEntries, removeMonitoring, setHandlerStorage, } from './handlers';
|
|
10
|
-
import { buildDashboardHtml } from './ui';
|
|
7
|
+
import { TraceConfig } from '../config.js';
|
|
8
|
+
import { TraceStorage } from '../storage/index.js';
|
|
9
|
+
import { addMonitoring, clearEntries, getBatch, getEntry, getMonitoring, getStats, listEntries, removeMonitoring, setHandlerStorage, } from './handlers.js';
|
|
10
|
+
import { buildDashboardHtml } from './ui.js';
|
|
11
11
|
const resolveDashboardConnectionName = (connectionName) => {
|
|
12
12
|
const explicitConnection = connectionName?.trim();
|
|
13
13
|
if (explicitConnection !== undefined && explicitConnection !== '') {
|
package/dist/dashboard/ui.js
CHANGED
|
@@ -71,7 +71,7 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
71
71
|
.section-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;padding:22px 24px 16px}.section-head h3{margin:0;font-size:1.04rem}.section-head p{margin:6px 0 0;color:var(--muted);font-size:.92rem}.toolbar{display:flex;flex-wrap:wrap;gap:10px;padding:0 24px 18px}.control,.toolbar input,.toolbar select{height:44px;border-radius:13px;border:1px solid var(--line);background:var(--surface-strong);color:var(--text);padding:0 14px;min-width:0}.toolbar input,.toolbar select{flex:1 1 180px}.toolbar input::placeholder{color:var(--muted)}.btn{height:44px;border:none;border-radius:13px;padding:0 16px;cursor:pointer;font-weight:800}.btn-primary{background:linear-gradient(135deg,var(--accent-strong),var(--accent));color:#fff}.btn-danger{background:rgba(239,68,68,.12);color:var(--danger);border:1px solid rgba(239,68,68,.18)}.btn-ghost{background:var(--surface-soft);color:var(--text);border:1px solid var(--line)}
|
|
72
72
|
.table-wrap{overflow:auto;padding:0 12px 12px}table{width:100%;border-collapse:separate;border-spacing:0;min-width:880px}th{padding:14px;color:var(--muted);font-size:.74rem;font-weight:800;letter-spacing:.12em;text-transform:uppercase;text-align:left;border-bottom:1px solid var(--line)}td{padding:15px 14px;border-bottom:1px solid var(--line);vertical-align:top}.row-button{cursor:pointer}.row-button:hover td{background:rgba(56,189,248,.05)}.summary{font-size:.93rem;font-weight:700;line-height:1.4;color:var(--text)}.summary-sub{margin-top:6px;color:var(--muted);font-size:.82rem;line-height:1.4}.mono{font-family:var(--mono)}.empty{padding:44px 24px;color:var(--muted);line-height:1.65;text-align:center}.pagination{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 24px 24px;color:var(--muted);flex-wrap:wrap}.pagination-controls{display:flex;gap:8px}.pagination button{height:40px;min-width:92px;padding:0 14px;border-radius:12px;border:1px solid var(--line);background:var(--surface-strong);color:var(--text);cursor:pointer}.pagination button:disabled{opacity:.45;cursor:not-allowed}
|
|
73
73
|
.activity-list{list-style:none;margin:0;padding:0 24px 24px}.activity-item{padding:14px 0;border-top:1px solid var(--line)}.activity-item:first-child{border-top:none}.activity-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.activity-time{color:var(--muted);font-size:.85rem}.activity-summary{margin-top:8px;color:var(--text);line-height:1.48}.back-link{display:inline-flex;align-items:center;gap:8px;margin:0 0 14px;color:var(--accent);font-weight:800;cursor:pointer}.detail-card{padding:24px}.detail-meta{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0 20px;color:var(--muted);font-size:.9rem}.detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px}.detail-stack{display:grid;gap:16px;margin-top:18px}.detail-box{padding:16px;border-radius:16px;background:var(--surface-soft);border:1px solid var(--line)}.detail-box h4{margin:0 0 10px;font-size:.92rem}.detail-box dl{margin:0;display:grid;gap:8px}.detail-box dt{font-size:.76rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:800}.detail-box dd{margin:0;color:var(--text);line-height:1.45}.trace-tabs{display:flex;gap:10px;flex-wrap:wrap;margin:20px 0 16px}.trace-tab{border:none;border-radius:12px;padding:10px 12px;background:transparent;color:var(--muted);cursor:pointer;box-shadow:inset 0 0 0 1px var(--line);font-weight:800}.trace-tab.active{background:rgba(56,189,248,.12);color:var(--text);box-shadow:inset 0 0 0 1px rgba(56,189,248,.28)}.trace-panel{display:grid;gap:14px}.trace-item{padding:18px;border-radius:16px;background:var(--surface-soft);border:1px solid var(--line)}.trace-item-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.trace-item-summary{margin-top:10px;display:grid;gap:10px}.trace-note{color:var(--muted);line-height:1.6}
|
|
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)}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-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-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}
|
|
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
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}
|
|
@@ -140,15 +140,27 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
140
140
|
monitoring: { title: 'Monitoring tags', subtitle: 'Pinned tags for trace pivots.' }
|
|
141
141
|
};
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
143
|
+
const createInitialState = () => {
|
|
144
|
+
const search = new URLSearchParams(window.location.search);
|
|
145
|
+
const page = search.get('page');
|
|
146
|
+
const entriesPage = Number.parseInt(search.get('entriesPage') || '1', 10);
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
page: page && Object.prototype.hasOwnProperty.call(PAGE_COPY, page) ? page : 'overview',
|
|
150
|
+
entriesPage: Number.isFinite(entriesPage) && entriesPage > 0 ? entriesPage : 1,
|
|
151
|
+
entriesFilter: {
|
|
152
|
+
type: search.get('type') || '',
|
|
153
|
+
tag: search.get('tag') || '',
|
|
154
|
+
batchId: search.get('batchId') || ''
|
|
155
|
+
},
|
|
156
|
+
detail: null,
|
|
157
|
+
detailBatch: null,
|
|
158
|
+
detailTab: 'summary'
|
|
159
|
+
};
|
|
150
160
|
};
|
|
151
161
|
|
|
162
|
+
let state = createInitialState();
|
|
163
|
+
|
|
152
164
|
let copySequence = 0;
|
|
153
165
|
const copyPayloads = new Map();
|
|
154
166
|
|
|
@@ -193,7 +205,19 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
193
205
|
return response.json();
|
|
194
206
|
};
|
|
195
207
|
|
|
196
|
-
const
|
|
208
|
+
const requestMethodClass = (entry) => {
|
|
209
|
+
if (!entry || entry.type !== 'request') return '';
|
|
210
|
+
const method = String(entry.content && entry.content.method || '').toUpperCase();
|
|
211
|
+
if (method === 'GET') return ' method-get';
|
|
212
|
+
if (method === 'POST') return ' method-post';
|
|
213
|
+
return ' method-other';
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const typeClass = (entryOrType, maybeEntry) => {
|
|
217
|
+
const entry = maybeEntry || (typeof entryOrType === 'object' ? entryOrType : null);
|
|
218
|
+
const type = entry && entry.type ? entry.type : entryOrType;
|
|
219
|
+
return 'type-pill pill-' + String(type || '').replace(/_/g, '-') + requestMethodClass(entry);
|
|
220
|
+
};
|
|
197
221
|
|
|
198
222
|
const timeSince = (value) => {
|
|
199
223
|
const createdAt = Number(value);
|
|
@@ -245,11 +269,34 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
245
269
|
return '<span class="duration-chip ' + tone + '" title="' + toneLabel + '">' + escapeHtml(formatDuration(duration)) + '</span>';
|
|
246
270
|
};
|
|
247
271
|
|
|
272
|
+
const buildEntriesHref = (params) => {
|
|
273
|
+
const search = new URLSearchParams();
|
|
274
|
+
search.set('page', 'entries');
|
|
275
|
+
if (params.type) search.set('type', String(params.type));
|
|
276
|
+
if (params.tag) search.set('tag', String(params.tag));
|
|
277
|
+
if (params.batchId) search.set('batchId', String(params.batchId));
|
|
278
|
+
return BASE + '?' + search.toString();
|
|
279
|
+
};
|
|
280
|
+
|
|
248
281
|
const tagsHtml = (tags) => (tags || []).map((tag) => {
|
|
249
282
|
const css = tag === 'failed' ? 'tag failed' : tag === 'slow' ? 'tag slow' : 'tag';
|
|
250
|
-
|
|
283
|
+
const href = buildEntriesHref({ tag });
|
|
284
|
+
return '<a class="' + css + '" data-action="filter-tag" data-tag="' + escapeHtml(tag) + '" href="' + escapeHtml(href) + '">' + escapeHtml(tag) + '</a>';
|
|
251
285
|
}).join('');
|
|
252
286
|
|
|
287
|
+
const syncUrl = () => {
|
|
288
|
+
const search = new URLSearchParams();
|
|
289
|
+
if (state.page !== 'overview') search.set('page', state.page);
|
|
290
|
+
if (state.page === 'entries' || state.entriesFilter.type || state.entriesFilter.tag || state.entriesFilter.batchId) {
|
|
291
|
+
if (state.entriesFilter.type) search.set('type', state.entriesFilter.type);
|
|
292
|
+
if (state.entriesFilter.tag) search.set('tag', state.entriesFilter.tag);
|
|
293
|
+
if (state.entriesFilter.batchId) search.set('batchId', state.entriesFilter.batchId);
|
|
294
|
+
if (state.entriesPage > 1) search.set('entriesPage', String(state.entriesPage));
|
|
295
|
+
}
|
|
296
|
+
const nextUrl = search.toString() === '' ? BASE : BASE + '?' + search.toString();
|
|
297
|
+
window.history.replaceState(null, '', nextUrl);
|
|
298
|
+
};
|
|
299
|
+
|
|
253
300
|
const batchSnippet = (batchId) => {
|
|
254
301
|
const raw = String(batchId || '');
|
|
255
302
|
return raw === '' ? '-' : escapeHtml(raw.slice(0, 8));
|
|
@@ -469,7 +516,7 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
469
516
|
'<section class="trace-item">',
|
|
470
517
|
'<div class="trace-item-head">',
|
|
471
518
|
'<div>',
|
|
472
|
-
'<span class="' + typeClass(entry
|
|
519
|
+
'<span class="' + typeClass(entry) + '">' + escapeHtml(entry.type) + '</span>',
|
|
473
520
|
'</div>',
|
|
474
521
|
'<div class="activity-head">' + durationHtml(entry) + '<span class="activity-time">' + escapeHtml(timeSince(entry.createdAt)) + '</span></div>',
|
|
475
522
|
'</div>',
|
|
@@ -495,10 +542,11 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
495
542
|
{ id: 'logs', label: 'Logs', count: batchEntriesByType('log').length },
|
|
496
543
|
{ id: 'exceptions', label: 'Exceptions', count: batchEntriesByType('exception').length },
|
|
497
544
|
{ id: 'http', label: 'HTTP', count: batchEntriesByType('client_request').length },
|
|
498
|
-
{ id: '
|
|
545
|
+
{ id: 'cache', label: 'Cache', count: batchEntriesByType('cache').length },
|
|
546
|
+
{ id: 'other', label: 'Other', count: batchEntries().filter((item) => !['request','query','log','exception','client_request','cache'].includes(item.type)).length }
|
|
499
547
|
];
|
|
500
548
|
const currentTab = traceTabs.some((tab) => tab.id === state.detailTab) ? state.detailTab : 'summary';
|
|
501
|
-
const otherEntries = batchEntries().filter((item) => !['request','query','log','exception','client_request'].includes(item.type));
|
|
549
|
+
const otherEntries = batchEntries().filter((item) => !['request','query','log','exception','client_request','cache'].includes(item.type));
|
|
502
550
|
const panels = {
|
|
503
551
|
summary: [
|
|
504
552
|
'<div class="detail-grid">',
|
|
@@ -521,18 +569,19 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
521
569
|
].join(''),
|
|
522
570
|
payload: detailJson(content.payload || {}),
|
|
523
571
|
headers: '<div class="detail-stack">' + detailJson(content.headers || {}) + detailJson(content.responseHeaders || {}) + '</div>',
|
|
524
|
-
response: '<div class="detail-stack"><div class="detail-grid">' + renderMetricBox('Status', [{ label: 'Response status', value: escapeHtml(content.responseStatus || '') }, { label: 'Duration', value: escapeHtml(formatDuration(getEntryDuration(entry))) }]) + '</div
|
|
572
|
+
response: '<div class="detail-stack"><div class="detail-grid">' + renderMetricBox('Status', [{ label: 'Response status', value: escapeHtml(content.responseStatus || '') }, { label: 'Duration', value: escapeHtml(formatDuration(getEntryDuration(entry))) }]) + '</div>' + (content.responseBody === undefined ? '<p class="trace-note">No response body was captured for this request.</p>' : detailJson(content.responseBody)) + detailJson(content.responseHeaders || {}) + '</div>',
|
|
525
573
|
queries: renderTraceItems(batchEntriesByType('query')),
|
|
526
574
|
logs: renderTraceItems(batchEntriesByType('log')),
|
|
527
575
|
exceptions: renderTraceItems(batchEntriesByType('exception')),
|
|
528
576
|
http: renderTraceItems(batchEntriesByType('client_request')),
|
|
577
|
+
cache: renderTraceItems(batchEntriesByType('cache')),
|
|
529
578
|
other: renderTraceItems(otherEntries)
|
|
530
579
|
};
|
|
531
580
|
|
|
532
581
|
main.innerHTML = [
|
|
533
582
|
'<span class="back-link" data-action="close-detail"><- Back to entries</span>',
|
|
534
583
|
'<section class="panel detail-card">',
|
|
535
|
-
'<div><span class="' + typeClass(entry
|
|
584
|
+
'<div><span class="' + typeClass(entry) + '">' + escapeHtml(entry.type) + '</span> ' + tagsHtml(entry.tags) + '</div>',
|
|
536
585
|
'<div class="detail-meta"><span>UUID <span class="mono">' + escapeHtml(entry.uuid) + '</span></span><span>Batch <span class="mono">' + escapeHtml(entry.batchId || '-') + '</span></span><span>' + durationHtml(entry) + '</span><span>' + escapeHtml(new Date(Number(entry.createdAt)).toISOString()) + '</span></div>',
|
|
537
586
|
'<div class="trace-tabs">',
|
|
538
587
|
traceTabs.map((tab) => '<button type="button" class="trace-tab' + (tab.id === currentTab ? ' active' : '') + '" data-action="detail-tab" data-tab="' + escapeHtml(tab.id) + '">' + escapeHtml(tab.label) + (tab.count !== undefined ? ' (' + escapeHtml(tab.count) + ')' : '') + '</button>').join(''),
|
|
@@ -558,10 +607,10 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
558
607
|
const recentRows = recent.data || [];
|
|
559
608
|
const recentTable = recentRows.length === 0
|
|
560
609
|
? '<div class="empty">No trace entries recorded.</div>'
|
|
561
|
-
: '<div class="table-wrap"><table><thead><tr><th>Type</th><th>Summary</th><th>Tags</th><th>Duration</th><th>Happened</th></tr></thead><tbody>' + recentRows.map((entry) => '<tr class="row-button" data-action="show-detail" data-uuid="' + escapeHtml(entry.uuid) + '"><td><span class="' + typeClass(entry
|
|
610
|
+
: '<div class="table-wrap"><table><thead><tr><th>Type</th><th>Summary</th><th>Tags</th><th>Duration</th><th>Happened</th></tr></thead><tbody>' + recentRows.map((entry) => '<tr class="row-button" data-action="show-detail" data-uuid="' + escapeHtml(entry.uuid) + '"><td><span class="' + typeClass(entry) + '">' + escapeHtml(entry.type) + '</span></td><td>' + entrySummaryHtml(entry) + '</td><td>' + tagsHtml(entry.tags) + '</td><td>' + durationHtml(entry) + '</td><td class="activity-time">' + escapeHtml(timeSince(entry.createdAt)) + '</td></tr>').join('') + '</tbody></table></div>';
|
|
562
611
|
const activityList = recentRows.length === 0
|
|
563
612
|
? '<div class="empty">No recent activity.</div>'
|
|
564
|
-
: '<ul class="activity-list">' + recentRows.slice(0, 5).map((entry) => '<li class="activity-item"><div class="activity-head"><span class="' + typeClass(entry
|
|
613
|
+
: '<ul class="activity-list">' + recentRows.slice(0, 5).map((entry) => '<li class="activity-item"><div class="activity-head"><span class="' + typeClass(entry) + '">' + escapeHtml(entry.type) + '</span>' + durationHtml(entry) + '<span class="activity-time">' + escapeHtml(timeSince(entry.createdAt)) + '</span></div><div class="activity-summary">' + escapeHtml(entrySummaryText(entry)) + '</div></li>').join('') + '</ul>';
|
|
565
614
|
|
|
566
615
|
main.innerHTML = [
|
|
567
616
|
statsCardsHtml(stats),
|
|
@@ -605,7 +654,7 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
605
654
|
const total = Number(response.total || 0);
|
|
606
655
|
const perPage = Number(response.perPage || 50);
|
|
607
656
|
const totalPages = Math.max(1, Math.ceil(total / perPage));
|
|
608
|
-
const rows = data.map((entry) => '<tr class="row-button" data-action="show-detail" data-uuid="' + escapeHtml(entry.uuid) + '"><td><span class="' + typeClass(entry
|
|
657
|
+
const rows = data.map((entry) => '<tr class="row-button" data-action="show-detail" data-uuid="' + escapeHtml(entry.uuid) + '"><td><span class="' + typeClass(entry) + '">' + escapeHtml(entry.type) + '</span></td><td>' + entrySummaryHtml(entry) + '</td><td>' + tagsHtml(entry.tags) + '</td><td>' + durationHtml(entry) + '</td><td class="mono">' + batchSnippet(entry.batchId) + '</td><td class="activity-time">' + escapeHtml(timeSince(entry.createdAt)) + '</td></tr>').join('');
|
|
609
658
|
|
|
610
659
|
main.innerHTML = [
|
|
611
660
|
'<section class="panel">',
|
|
@@ -641,7 +690,7 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
641
690
|
main.innerHTML = [
|
|
642
691
|
'<span class="back-link" data-action="close-detail"><- Back to entries</span>',
|
|
643
692
|
'<section class="panel detail-card">',
|
|
644
|
-
'<div><span class="' + typeClass(entry
|
|
693
|
+
'<div><span class="' + typeClass(entry) + '">' + escapeHtml(entry.type) + '</span> ' + tagsHtml(entry.tags) + '</div>',
|
|
645
694
|
'<div class="detail-meta"><span>UUID <span class="mono">' + escapeHtml(entry.uuid) + '</span></span><span>Batch <span class="mono">' + escapeHtml(entry.batchId || '-') + '</span></span><span>' + durationHtml(entry) + '</span><span>' + escapeHtml(new Date(Number(entry.createdAt)).toISOString()) + '</span></div>',
|
|
646
695
|
'<div class="detail-stack">',
|
|
647
696
|
renderEntryBody(entry),
|
|
@@ -657,13 +706,14 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
657
706
|
const tags = result.tags || [];
|
|
658
707
|
main.innerHTML = [
|
|
659
708
|
'<section class="panel">',
|
|
660
|
-
'<div class="section-head"><div><h3>Monitoring tags</h3><p>
|
|
709
|
+
'<div class="section-head"><div><h3>Monitoring tags</h3><p>Save the tags you filter by often so they stay one click away.</p></div></div>',
|
|
661
710
|
'<div class="monitoring-wrap">',
|
|
662
711
|
'<div class="tag-list">',
|
|
663
|
-
tags.length === 0 ? '<span class="helper-text">No tags monitored.</span>' : tags.map((tag) => '<span class="tag-item"><
|
|
712
|
+
tags.length === 0 ? '<span class="helper-text">No tags monitored yet. Add tags like auth, checkout, queue:emails, or nightly-sync to pin them here.</span>' : tags.map((tag) => '<span class="tag-item"><a class="tag mono" data-action="filter-tag" data-tag="' + escapeHtml(tag) + '" href="' + escapeHtml(buildEntriesHref({ tag })) + '">' + escapeHtml(tag) + '</a><button type="button" class="tag-remove" data-action="remove-tag" data-tag="' + escapeHtml(tag) + '">x</button></span>').join(''),
|
|
664
713
|
'</div>',
|
|
714
|
+
'<p class="helper-text">Click a saved tag to filter the entries list by that exact tag. Because each tag is a real link, you can also open it in a new tab. Removing a saved tag only removes the shortcut here; it does not delete any trace entries.</p>',
|
|
665
715
|
'<div class="toolbar" style="padding:0;margin-top:8px">',
|
|
666
|
-
'<input id="new-tag" class="control" type="text" placeholder="Add tag">',
|
|
716
|
+
'<input id="new-tag" class="control" type="text" placeholder="Add tag, for example checkout">',
|
|
667
717
|
'<button type="button" class="btn btn-primary" data-action="add-tag">Add tag</button>',
|
|
668
718
|
'</div>',
|
|
669
719
|
'</div>',
|
|
@@ -688,6 +738,8 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
688
738
|
button.classList.toggle('active', button.getAttribute('data-type') === activeShortcut);
|
|
689
739
|
});
|
|
690
740
|
|
|
741
|
+
syncUrl();
|
|
742
|
+
|
|
691
743
|
if (state.page === 'overview') await renderOverview(main);
|
|
692
744
|
if (state.page === 'entries') await renderEntries(main);
|
|
693
745
|
if (state.page === 'monitoring') await renderMonitoring(main);
|
|
@@ -822,7 +874,12 @@ const DASHBOARD_DOCUMENT = `<!DOCTYPE html>
|
|
|
822
874
|
const action = target.getAttribute('data-action');
|
|
823
875
|
if (action === 'go-page') { setPage(String(target.getAttribute('data-page') || 'overview')); return; }
|
|
824
876
|
if (action === 'type-shortcut') { setTypeShortcut(String(target.getAttribute('data-type') || '')); return; }
|
|
825
|
-
if (action === 'filter-tag') {
|
|
877
|
+
if (action === 'filter-tag') {
|
|
878
|
+
if (target instanceof HTMLAnchorElement && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0)) return;
|
|
879
|
+
event.preventDefault();
|
|
880
|
+
filterByTag(String(target.getAttribute('data-tag') || ''));
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
826
883
|
if (action === 'detail-tab') { state = { ...state, detailTab: String(target.getAttribute('data-tab') || 'summary') }; render(); return; }
|
|
827
884
|
if (action === 'clear-all') { clearAll(); return; }
|
|
828
885
|
if (action === 'show-detail') { showDetail(String(target.getAttribute('data-uuid') || '')); return; }
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
export { TraceConfig } from './config';
|
|
9
9
|
export { TraceStorage } from './storage';
|
|
10
10
|
export type { ITraceStorage } from './storage';
|
|
11
|
+
export { TraceContentRedaction } from './storage/TraceContentRedaction';
|
|
11
12
|
export { TraceContext } from './context';
|
|
12
13
|
export { registerTraceDashboard, registerTraceRoutes } from './dashboard/routes';
|
|
13
14
|
export type { TraceDashboardOptions, TraceDashboardRegistrationOptions } from './dashboard/routes';
|
|
@@ -31,5 +32,6 @@ export { QueryWatcher } from './watchers/QueryWatcher';
|
|
|
31
32
|
export { RedisWatcher } from './watchers/RedisWatcher';
|
|
32
33
|
export { ScheduleWatcher } from './watchers/ScheduleWatcher';
|
|
33
34
|
export { ViewWatcher } from './watchers/ViewWatcher';
|
|
35
|
+
export declare const captureTraceException: (error: unknown) => void;
|
|
34
36
|
export { EntryType } from './types';
|
|
35
37
|
export type { AuthContent, BatchContent, CacheContent, ClientRequestContent, CommandContent, DumpContent, EntryTypeValue, EventContent, ExceptionContent, GateContent, ITraceConfig, ITraceEntry, ITraceWatcher, ITraceWatcherConfig, JobContent, LogContent, MailContent, MiddlewareContent, ModelContent, NotificationContent, QueryContent, RedactionConfig, RedisContent, RequestContent, ScheduleContent, TraceConfigOverrides, ViewContent, WatcherToggles, } from './types';
|
package/dist/index.js
CHANGED
|
@@ -5,46 +5,51 @@
|
|
|
5
5
|
* individually. For full auto-initialisation, use:
|
|
6
6
|
* import '@zintrust/trace/register';
|
|
7
7
|
*/
|
|
8
|
+
import { ExceptionWatcher as ExceptionWatcherApi } from './watchers/ExceptionWatcher.js';
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
9
10
|
// Config
|
|
10
11
|
// ---------------------------------------------------------------------------
|
|
11
|
-
export { TraceConfig } from './config';
|
|
12
|
+
export { TraceConfig } from './config.js';
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Storage
|
|
14
15
|
// ---------------------------------------------------------------------------
|
|
15
|
-
export { TraceStorage } from './storage';
|
|
16
|
+
export { TraceStorage } from './storage/index.js';
|
|
17
|
+
export { TraceContentRedaction } from './storage/TraceContentRedaction.js';
|
|
16
18
|
// ---------------------------------------------------------------------------
|
|
17
19
|
// Context
|
|
18
20
|
// ---------------------------------------------------------------------------
|
|
19
|
-
export { TraceContext } from './context';
|
|
21
|
+
export { TraceContext } from './context.js';
|
|
20
22
|
// ---------------------------------------------------------------------------
|
|
21
23
|
// Dashboard
|
|
22
24
|
// ---------------------------------------------------------------------------
|
|
23
|
-
export { registerTraceDashboard, registerTraceRoutes } from './dashboard/routes';
|
|
25
|
+
export { registerTraceDashboard, registerTraceRoutes } from './dashboard/routes.js';
|
|
24
26
|
// ---------------------------------------------------------------------------
|
|
25
27
|
// Watchers (named re-exports for use with custom wiring)
|
|
26
28
|
// ---------------------------------------------------------------------------
|
|
27
|
-
export { AuthWatcher } from './watchers/AuthWatcher';
|
|
28
|
-
export { BatchWatcher } from './watchers/BatchWatcher';
|
|
29
|
-
export { CacheWatcher } from './watchers/CacheWatcher';
|
|
30
|
-
export { CommandWatcher } from './watchers/CommandWatcher';
|
|
31
|
-
export { DumpWatcher } from './watchers/DumpWatcher';
|
|
32
|
-
export { EventWatcher } from './watchers/EventWatcher';
|
|
33
|
-
export { ExceptionWatcher } from './watchers/ExceptionWatcher';
|
|
34
|
-
export { GateWatcher } from './watchers/GateWatcher';
|
|
35
|
-
export { HttpClientWatcher } from './watchers/HttpClientWatcher';
|
|
36
|
-
export { HttpWatcher } from './watchers/HttpWatcher';
|
|
37
|
-
export { JobWatcher } from './watchers/JobWatcher';
|
|
38
|
-
export { LogWatcher } from './watchers/LogWatcher';
|
|
39
|
-
export { MailWatcher } from './watchers/MailWatcher';
|
|
40
|
-
export { MiddlewareWatcher } from './watchers/MiddlewareWatcher';
|
|
41
|
-
export { ModelWatcher } from './watchers/ModelWatcher';
|
|
42
|
-
export { NotificationWatcher } from './watchers/NotificationWatcher';
|
|
43
|
-
export { QueryWatcher } from './watchers/QueryWatcher';
|
|
44
|
-
export { RedisWatcher } from './watchers/RedisWatcher';
|
|
45
|
-
export { ScheduleWatcher } from './watchers/ScheduleWatcher';
|
|
46
|
-
export { ViewWatcher } from './watchers/ViewWatcher';
|
|
29
|
+
export { AuthWatcher } from './watchers/AuthWatcher.js';
|
|
30
|
+
export { BatchWatcher } from './watchers/BatchWatcher.js';
|
|
31
|
+
export { CacheWatcher } from './watchers/CacheWatcher.js';
|
|
32
|
+
export { CommandWatcher } from './watchers/CommandWatcher.js';
|
|
33
|
+
export { DumpWatcher } from './watchers/DumpWatcher.js';
|
|
34
|
+
export { EventWatcher } from './watchers/EventWatcher.js';
|
|
35
|
+
export { ExceptionWatcher } from './watchers/ExceptionWatcher.js';
|
|
36
|
+
export { GateWatcher } from './watchers/GateWatcher.js';
|
|
37
|
+
export { HttpClientWatcher } from './watchers/HttpClientWatcher.js';
|
|
38
|
+
export { HttpWatcher } from './watchers/HttpWatcher.js';
|
|
39
|
+
export { JobWatcher } from './watchers/JobWatcher.js';
|
|
40
|
+
export { LogWatcher } from './watchers/LogWatcher.js';
|
|
41
|
+
export { MailWatcher } from './watchers/MailWatcher.js';
|
|
42
|
+
export { MiddlewareWatcher } from './watchers/MiddlewareWatcher.js';
|
|
43
|
+
export { ModelWatcher } from './watchers/ModelWatcher.js';
|
|
44
|
+
export { NotificationWatcher } from './watchers/NotificationWatcher.js';
|
|
45
|
+
export { QueryWatcher } from './watchers/QueryWatcher.js';
|
|
46
|
+
export { RedisWatcher } from './watchers/RedisWatcher.js';
|
|
47
|
+
export { ScheduleWatcher } from './watchers/ScheduleWatcher.js';
|
|
48
|
+
export { ViewWatcher } from './watchers/ViewWatcher.js';
|
|
49
|
+
export const captureTraceException = (error) => {
|
|
50
|
+
ExceptionWatcherApi.capture(error);
|
|
51
|
+
};
|
|
47
52
|
// ---------------------------------------------------------------------------
|
|
48
53
|
// Types
|
|
49
54
|
// ---------------------------------------------------------------------------
|
|
50
|
-
export { EntryType } from './types';
|
|
55
|
+
export { EntryType } from './types.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Migration:
|
|
3
|
-
* Creates the main entries table for @zintrust/
|
|
2
|
+
* Migration: CreateZinTraceEntriesTable
|
|
3
|
+
* Creates the main entries table for @zintrust/trace
|
|
4
4
|
*/
|
|
5
5
|
import { type IDatabase } from '@zintrust/core';
|
|
6
6
|
export interface Migration {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Migration:
|
|
3
|
-
* Creates the main entries table for @zintrust/
|
|
2
|
+
* Migration: CreateZinTraceEntriesTable
|
|
3
|
+
* Creates the main entries table for @zintrust/trace
|
|
4
4
|
*/
|
|
5
5
|
import { MigrationSchema } from '@zintrust/core';
|
|
6
6
|
export const migration = {
|
|
7
7
|
async up(db) {
|
|
8
8
|
const schema = MigrationSchema.create(db);
|
|
9
|
-
await schema.create('
|
|
9
|
+
await schema.create('zin_trace_entries', (table) => {
|
|
10
10
|
table.id();
|
|
11
11
|
table.uuid('uuid').unique();
|
|
12
12
|
table.string('batch_id');
|
|
@@ -14,7 +14,7 @@ export const migration = {
|
|
|
14
14
|
table.string('type');
|
|
15
15
|
table.text('content');
|
|
16
16
|
table.boolean('is_latest').default(true);
|
|
17
|
-
table.
|
|
17
|
+
table.bigInteger('created_at');
|
|
18
18
|
table.index('batch_id');
|
|
19
19
|
table.index('family_hash');
|
|
20
20
|
table.index('created_at');
|
|
@@ -23,6 +23,6 @@ export const migration = {
|
|
|
23
23
|
},
|
|
24
24
|
async down(db) {
|
|
25
25
|
const schema = MigrationSchema.create(db);
|
|
26
|
-
await schema.dropIfExists('
|
|
26
|
+
await schema.dropIfExists('zin_trace_entries');
|
|
27
27
|
},
|
|
28
28
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Migration:
|
|
3
|
-
* Creates the tag join table for @zintrust/
|
|
2
|
+
* Migration: CreateZinTraceEntriesTagsTable
|
|
3
|
+
* Creates the tag join table for @zintrust/trace
|
|
4
4
|
*/
|
|
5
5
|
import { type IDatabase } from '@zintrust/core';
|
|
6
6
|
export interface Migration {
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Migration:
|
|
3
|
-
* Creates the tag join table for @zintrust/
|
|
2
|
+
* Migration: CreateZinTraceEntriesTagsTable
|
|
3
|
+
* Creates the tag join table for @zintrust/trace
|
|
4
4
|
*/
|
|
5
5
|
import { MigrationSchema } from '@zintrust/core';
|
|
6
6
|
export const migration = {
|
|
7
7
|
async up(db) {
|
|
8
8
|
const schema = MigrationSchema.create(db);
|
|
9
|
-
await schema.create('
|
|
9
|
+
await schema.create('zin_trace_entries_tags', (table) => {
|
|
10
10
|
table.string('entry_uuid');
|
|
11
11
|
table.string('tag');
|
|
12
12
|
table.unique(['entry_uuid', 'tag']);
|
|
13
13
|
table.index('tag');
|
|
14
|
-
table.foreign('entry_uuid').references('uuid').on('
|
|
14
|
+
table.foreign('entry_uuid').references('uuid').on('zin_trace_entries').onDelete('CASCADE');
|
|
15
15
|
});
|
|
16
16
|
},
|
|
17
17
|
async down(db) {
|
|
18
18
|
const schema = MigrationSchema.create(db);
|
|
19
|
-
await schema.dropIfExists('
|
|
19
|
+
await schema.dropIfExists('zin_trace_entries_tags');
|
|
20
20
|
},
|
|
21
21
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Migration:
|
|
3
|
-
* Creates the tag watchlist table for @zintrust/
|
|
2
|
+
* Migration: CreateZinTraceMonitoringTable
|
|
3
|
+
* Creates the tag watchlist table for @zintrust/trace
|
|
4
4
|
*/
|
|
5
5
|
import { type IDatabase } from '@zintrust/core';
|
|
6
6
|
export interface Migration {
|