uisnap 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +26 -0
- package/.claude/skills/uisnap/README.md +48 -0
- package/.claude/skills/uisnap/REFERENCE.md +1261 -0
- package/.claude/skills/uisnap/SETUP.md +75 -0
- package/.claude/skills/uisnap/SKILL.md +130 -0
- package/.claude/skills/uisnap/snapshot-capture-and-analysis.md +452 -0
- package/.claude/skills/uisnap/trace-capture-and-analysis.md +472 -0
- package/CHANGELOG.md +96 -0
- package/LICENSE +21 -0
- package/README.md +394 -0
- package/SKILL-INSTALLATION.md +103 -0
- package/dist/analyze-console.d.ts +3 -0
- package/dist/analyze-console.d.ts.map +1 -0
- package/dist/analyze-console.js +153 -0
- package/dist/analyze-console.js.map +1 -0
- package/dist/analyze-network.d.ts +3 -0
- package/dist/analyze-network.d.ts.map +1 -0
- package/dist/analyze-network.js +156 -0
- package/dist/analyze-network.js.map +1 -0
- package/dist/chrome-trace-analyze.d.ts +3 -0
- package/dist/chrome-trace-analyze.d.ts.map +1 -0
- package/dist/chrome-trace-analyze.js +119 -0
- package/dist/chrome-trace-analyze.js.map +1 -0
- package/dist/chrome-trace-import.d.ts +3 -0
- package/dist/chrome-trace-import.d.ts.map +1 -0
- package/dist/chrome-trace-import.js +90 -0
- package/dist/chrome-trace-import.js.map +1 -0
- package/dist/commands/snapshot.d.ts +4 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +154 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/diagnose.d.ts +3 -0
- package/dist/diagnose.d.ts.map +1 -0
- package/dist/diagnose.js +244 -0
- package/dist/diagnose.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/pw.d.ts +3 -0
- package/dist/pw.d.ts.map +1 -0
- package/dist/pw.js +289 -0
- package/dist/pw.js.map +1 -0
- package/dist/query-a11y.d.ts +3 -0
- package/dist/query-a11y.d.ts.map +1 -0
- package/dist/query-a11y.js +208 -0
- package/dist/query-a11y.js.map +1 -0
- package/dist/trace-import.d.ts +3 -0
- package/dist/trace-import.d.ts.map +1 -0
- package/dist/trace-import.js +93 -0
- package/dist/trace-import.js.map +1 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/chromeTraceAnalyze.d.ts +40 -0
- package/dist/utils/chromeTraceAnalyze.d.ts.map +1 -0
- package/dist/utils/chromeTraceAnalyze.js +113 -0
- package/dist/utils/chromeTraceAnalyze.js.map +1 -0
- package/dist/utils/chromeTraceHelpers.d.ts +4 -0
- package/dist/utils/chromeTraceHelpers.d.ts.map +1 -0
- package/dist/utils/chromeTraceHelpers.js +68 -0
- package/dist/utils/chromeTraceHelpers.js.map +1 -0
- package/dist/utils/chromeTraceImport.d.ts +14 -0
- package/dist/utils/chromeTraceImport.d.ts.map +1 -0
- package/dist/utils/chromeTraceImport.js +77 -0
- package/dist/utils/chromeTraceImport.js.map +1 -0
- package/dist/utils/helpers.d.ts +3 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +88 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/projectRoot.d.ts +2 -0
- package/dist/utils/projectRoot.d.ts.map +1 -0
- package/dist/utils/projectRoot.js +56 -0
- package/dist/utils/projectRoot.js.map +1 -0
- package/dist/utils/traceHelpers.d.ts +4 -0
- package/dist/utils/traceHelpers.d.ts.map +1 -0
- package/dist/utils/traceHelpers.js +67 -0
- package/dist/utils/traceHelpers.js.map +1 -0
- package/dist/utils/traceImport.d.ts +20 -0
- package/dist/utils/traceImport.d.ts.map +1 -0
- package/dist/utils/traceImport.js +124 -0
- package/dist/utils/traceImport.js.map +1 -0
- package/dist/utils/webVitals.d.ts +9 -0
- package/dist/utils/webVitals.d.ts.map +1 -0
- package/dist/utils/webVitals.js +54 -0
- package/dist/utils/webVitals.js.map +1 -0
- package/examples/login-flow.js +37 -0
- package/examples/scroll-perf-trace.js +43 -0
- package/examples/simple-capture.js +28 -0
- package/package.json +74 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# Trace Capture and Analysis
|
|
2
|
+
|
|
3
|
+
Complete reference for performance debugging with Chrome DevTools traces.
|
|
4
|
+
|
|
5
|
+
## When to Use Trace Capture
|
|
6
|
+
|
|
7
|
+
Use trace capture for performance profiling:
|
|
8
|
+
- Slow page loads or interactions
|
|
9
|
+
- Janky scrolling or animations
|
|
10
|
+
- UI freezes during user actions
|
|
11
|
+
- Long blocking tasks (>50ms)
|
|
12
|
+
- JavaScript execution analysis
|
|
13
|
+
- Layout thrashing or excessive repaints
|
|
14
|
+
- Identifying performance bottlenecks
|
|
15
|
+
|
|
16
|
+
## Chrome Trace vs Playwright Trace
|
|
17
|
+
|
|
18
|
+
**Chrome Performance Trace** (this guide):
|
|
19
|
+
- Captures browser internals: paint, layout, JS execution, style recalc
|
|
20
|
+
- Uses Chrome DevTools Protocol (CDP)
|
|
21
|
+
- Stores in DuckDB for efficient querying
|
|
22
|
+
- 36MB JSON → 1.5MB database → 100-500 token queries
|
|
23
|
+
- Use for: Performance profiling, blocking tasks, rendering analysis
|
|
24
|
+
|
|
25
|
+
**Playwright Trace** (different tool):
|
|
26
|
+
- Captures Playwright actions: clicks, navigations, assertions
|
|
27
|
+
- Stores in .trace.zip format
|
|
28
|
+
- Opens in Playwright Trace Viewer UI
|
|
29
|
+
- Use for: Action replay, test debugging, visual timeline
|
|
30
|
+
|
|
31
|
+
This guide covers Chrome Performance Traces only.
|
|
32
|
+
|
|
33
|
+
## Capture Workflow
|
|
34
|
+
|
|
35
|
+
### Basic Trace Capture
|
|
36
|
+
|
|
37
|
+
Use the provided example script for scroll performance:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uisnap exec examples/scroll-perf-trace.js https://myapp.com
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Output**:
|
|
44
|
+
```
|
|
45
|
+
snapshots/myapp.com/scroll-perf-trace-2025-12-30-143052/
|
|
46
|
+
├── chrome-trace.json # Raw trace (potentially large, not for direct reading)
|
|
47
|
+
└── chrome-trace.db # DuckDB database (queryable)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Custom Trace Script
|
|
51
|
+
|
|
52
|
+
For custom interactions, create a script with trace boundaries:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
// examples/interaction-trace.js
|
|
56
|
+
// Get CDP session
|
|
57
|
+
const cdp = await context.newCDPSession(page);
|
|
58
|
+
|
|
59
|
+
// Start Chrome tracing
|
|
60
|
+
console.log('Starting Chrome performance trace...');
|
|
61
|
+
await utils.startChromeTrace(cdp);
|
|
62
|
+
|
|
63
|
+
// Navigate
|
|
64
|
+
await page.goto(args[0]);
|
|
65
|
+
await page.waitForLoadState('networkidle');
|
|
66
|
+
|
|
67
|
+
// Perform interactions (all will be traced)
|
|
68
|
+
await page.getByRole('button', { name: 'Open Modal' }).click();
|
|
69
|
+
await page.waitForTimeout(100);
|
|
70
|
+
|
|
71
|
+
await page.getByRole('textbox', { name: 'Search' }).fill('test query');
|
|
72
|
+
await page.waitForTimeout(100);
|
|
73
|
+
|
|
74
|
+
await page.evaluate(() => {
|
|
75
|
+
for (let i = 0; i < 10; i++) {
|
|
76
|
+
document.querySelector('.item').scrollIntoView({ behavior: 'smooth' });
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
console.log('Stopping trace and importing to database...');
|
|
81
|
+
|
|
82
|
+
// Stop tracing and auto-import to DuckDB
|
|
83
|
+
const tracePath = path.join(utils.baseOutputDir, 'chrome-trace.json');
|
|
84
|
+
const dbPath = await utils.stopChromeTraceAndImport(cdp, tracePath);
|
|
85
|
+
|
|
86
|
+
console.log('\nAnalyze with:');
|
|
87
|
+
console.log(` uisnap-chrome-trace-analyze ${dbPath} --full`);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Key points**:
|
|
91
|
+
- Start trace BEFORE interactions you want to profile
|
|
92
|
+
- All browser activity between start/stop is captured
|
|
93
|
+
- Auto-import creates queryable database
|
|
94
|
+
- Don't try to read chrome-trace.json directly (too large)
|
|
95
|
+
|
|
96
|
+
### Combining Snapshot and Trace
|
|
97
|
+
|
|
98
|
+
Capture both functional state and performance data:
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
// examples/comprehensive-debug.js
|
|
102
|
+
// Capture initial state
|
|
103
|
+
await utils.captureStep(page, 'initial-load', async () => {
|
|
104
|
+
await page.goto(args[0]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Start performance tracing
|
|
108
|
+
const cdp = await context.newCDPSession(page);
|
|
109
|
+
await utils.startChromeTrace(cdp);
|
|
110
|
+
|
|
111
|
+
// Perform interactions (traced)
|
|
112
|
+
await page.evaluate(() => window.scrollTo({ top: 1000, behavior: 'smooth' }));
|
|
113
|
+
await page.waitForTimeout(500);
|
|
114
|
+
|
|
115
|
+
await page.evaluate(() => window.scrollTo({ top: 2000, behavior: 'smooth' }));
|
|
116
|
+
await page.waitForTimeout(500);
|
|
117
|
+
|
|
118
|
+
// Capture final state
|
|
119
|
+
await utils.captureStep(page, 'after-scroll', async () => {});
|
|
120
|
+
|
|
121
|
+
// Stop trace
|
|
122
|
+
const tracePath = path.join(utils.baseOutputDir, 'chrome-trace.json');
|
|
123
|
+
const dbPath = await utils.stopChromeTraceAndImport(cdp, tracePath);
|
|
124
|
+
|
|
125
|
+
console.log('Functional analysis:');
|
|
126
|
+
console.log(` uisnap-analyze-console step-1-initial-load/console.jsonl`);
|
|
127
|
+
console.log(` uisnap-analyze-console step-2-after-scroll/console.jsonl`);
|
|
128
|
+
console.log('\nPerformance analysis:');
|
|
129
|
+
console.log(` uisnap-chrome-trace-analyze ${dbPath} --full`);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Analysis Workflow
|
|
133
|
+
|
|
134
|
+
### Progressive Disclosure Pattern
|
|
135
|
+
|
|
136
|
+
Start with summary, drill into details as needed:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# 1. Summary (shows what's available)
|
|
140
|
+
uisnap-chrome-trace-analyze snapshots/myapp.com/latest/chrome-trace.db
|
|
141
|
+
|
|
142
|
+
# Output:
|
|
143
|
+
# === Chrome Trace Summary ===
|
|
144
|
+
# Total tasks: 48,234
|
|
145
|
+
# Total duration: 3,847.52ms
|
|
146
|
+
#
|
|
147
|
+
# For details, use:
|
|
148
|
+
# --long-tasks Show 8 task(s) over 50ms
|
|
149
|
+
# --js-time Show JavaScript execution breakdown
|
|
150
|
+
# --layout-paint Show layout and paint analysis
|
|
151
|
+
|
|
152
|
+
# 2. Identify long blocking tasks
|
|
153
|
+
uisnap-chrome-trace-analyze snapshots/myapp.com/latest/chrome-trace.db --long-tasks
|
|
154
|
+
|
|
155
|
+
# 3. Analyze JS execution
|
|
156
|
+
uisnap-chrome-trace-analyze snapshots/myapp.com/latest/chrome-trace.db --js-time
|
|
157
|
+
|
|
158
|
+
# 4. Check layout/paint
|
|
159
|
+
uisnap-chrome-trace-analyze snapshots/myapp.com/latest/chrome-trace.db --layout-paint
|
|
160
|
+
|
|
161
|
+
# 5. See everything
|
|
162
|
+
uisnap-chrome-trace-analyze snapshots/myapp.com/latest/chrome-trace.db --full
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Canned Queries
|
|
166
|
+
|
|
167
|
+
#### --long-tasks
|
|
168
|
+
|
|
169
|
+
Shows tasks exceeding threshold (default 50ms):
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
uisnap-chrome-trace-analyze trace.db --long-tasks
|
|
173
|
+
uisnap-chrome-trace-analyze trace.db --long-tasks --threshold=100 # Custom threshold
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Output**:
|
|
177
|
+
```
|
|
178
|
+
=== Long Tasks (>50ms) ===
|
|
179
|
+
1. RunTask: 115.27ms (at 1234.56ms)
|
|
180
|
+
2. EvaluateScript: 87.45ms (at 2456.78ms)
|
|
181
|
+
3. FunctionCall: 62.33ms (at 3678.90ms)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### --js-time
|
|
185
|
+
|
|
186
|
+
Analyzes JavaScript execution breakdown:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
uisnap-chrome-trace-analyze trace.db --js-time
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Output**:
|
|
193
|
+
```
|
|
194
|
+
=== JavaScript Execution ===
|
|
195
|
+
FunctionCall:
|
|
196
|
+
Count: 1624, Total: 1445.67ms, Avg: 0.89ms, Max: 62.33ms
|
|
197
|
+
EvaluateScript:
|
|
198
|
+
Count: 47, Total: 339.06ms, Avg: 7.21ms, Max: 87.45ms
|
|
199
|
+
Total JS time: 1784.73ms
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### --layout-paint
|
|
203
|
+
|
|
204
|
+
Shows layout and paint operations:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
uisnap-chrome-trace-analyze trace.db --layout-paint
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Output**:
|
|
211
|
+
```
|
|
212
|
+
=== Layout & Paint ===
|
|
213
|
+
Paint: 516x, Total: 73.82ms, Avg: 0.14ms
|
|
214
|
+
Layout: 411x, Total: 53.67ms, Avg: 0.13ms
|
|
215
|
+
UpdateLayoutTree: 387x, Total: 41.23ms, Avg: 0.11ms
|
|
216
|
+
RecalculateStyles: 215x, Total: 28.45ms, Avg: 0.13ms
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
#### --full
|
|
220
|
+
|
|
221
|
+
Shows all analyses:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
uisnap-chrome-trace-analyze trace.db --full
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Equivalent to: `--long-tasks --js-time --layout-paint`
|
|
228
|
+
|
|
229
|
+
### Custom SQL Queries
|
|
230
|
+
|
|
231
|
+
For advanced analysis, query DuckDB directly:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Open database
|
|
235
|
+
duckdb snapshots/myapp.com/latest/chrome-trace.db
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### Database Schema
|
|
239
|
+
|
|
240
|
+
```sql
|
|
241
|
+
CREATE TABLE tasks (
|
|
242
|
+
name VARCHAR, -- Event name (e.g., 'FunctionCall', 'Paint', 'Layout')
|
|
243
|
+
cat VARCHAR, -- Category (e.g., 'devtools.timeline', 'v8.execute')
|
|
244
|
+
ts_ms DOUBLE, -- Timestamp in milliseconds
|
|
245
|
+
dur_ms DOUBLE, -- Duration in milliseconds
|
|
246
|
+
pid INTEGER, -- Process ID
|
|
247
|
+
tid INTEGER, -- Thread ID
|
|
248
|
+
args JSON -- Additional event arguments
|
|
249
|
+
);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### Example Queries
|
|
253
|
+
|
|
254
|
+
**Find slowest paint operations**:
|
|
255
|
+
```sql
|
|
256
|
+
SELECT name, dur_ms, ts_ms
|
|
257
|
+
FROM tasks
|
|
258
|
+
WHERE name LIKE '%Paint%'
|
|
259
|
+
ORDER BY dur_ms DESC
|
|
260
|
+
LIMIT 10;
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Calculate total time by category**:
|
|
264
|
+
```sql
|
|
265
|
+
SELECT cat,
|
|
266
|
+
COUNT(*) as count,
|
|
267
|
+
ROUND(SUM(dur_ms), 2) as total_ms,
|
|
268
|
+
ROUND(AVG(dur_ms), 2) as avg_ms
|
|
269
|
+
FROM tasks
|
|
270
|
+
GROUP BY cat
|
|
271
|
+
ORDER BY total_ms DESC;
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Find tasks during specific time range**:
|
|
275
|
+
```sql
|
|
276
|
+
SELECT name, dur_ms, ts_ms
|
|
277
|
+
FROM tasks
|
|
278
|
+
WHERE ts_ms BETWEEN 1000 AND 2000 -- Between 1-2 seconds
|
|
279
|
+
AND dur_ms > 10
|
|
280
|
+
ORDER BY ts_ms;
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Identify layout thrashing** (many rapid layouts):
|
|
284
|
+
```sql
|
|
285
|
+
SELECT
|
|
286
|
+
COUNT(*) as layout_count,
|
|
287
|
+
MIN(ts_ms) as first_layout,
|
|
288
|
+
MAX(ts_ms) as last_layout,
|
|
289
|
+
ROUND(MAX(ts_ms) - MIN(ts_ms), 2) as timespan_ms
|
|
290
|
+
FROM tasks
|
|
291
|
+
WHERE name = 'Layout'
|
|
292
|
+
AND ts_ms BETWEEN 1000 AND 1100 -- 100ms window
|
|
293
|
+
HAVING COUNT(*) > 10;
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Find functions called most often**:
|
|
297
|
+
```sql
|
|
298
|
+
SELECT name,
|
|
299
|
+
COUNT(*) as count,
|
|
300
|
+
ROUND(SUM(dur_ms), 2) as total_ms,
|
|
301
|
+
ROUND(AVG(dur_ms), 2) as avg_ms
|
|
302
|
+
FROM tasks
|
|
303
|
+
WHERE name LIKE '%Function%'
|
|
304
|
+
GROUP BY name
|
|
305
|
+
ORDER BY count DESC
|
|
306
|
+
LIMIT 20;
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Export results to JSON**:
|
|
310
|
+
```sql
|
|
311
|
+
COPY (
|
|
312
|
+
SELECT name, dur_ms, ts_ms
|
|
313
|
+
FROM tasks
|
|
314
|
+
WHERE dur_ms > 50
|
|
315
|
+
ORDER BY dur_ms DESC
|
|
316
|
+
) TO 'long-tasks.json';
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Common Performance Patterns
|
|
320
|
+
|
|
321
|
+
### Pattern 1: Identifying Blocking Tasks
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
# Find long tasks
|
|
325
|
+
uisnap-chrome-trace-analyze trace.db --long-tasks
|
|
326
|
+
|
|
327
|
+
# If found: "EvaluateScript: 340ms"
|
|
328
|
+
# Indicates: Heavy synchronous script execution blocking the main thread
|
|
329
|
+
# Solution: Break into smaller chunks, use requestIdleCallback, or web workers
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Pattern 2: Layout Thrashing
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Check layout operations
|
|
336
|
+
uisnap-chrome-trace-analyze trace.db --layout-paint
|
|
337
|
+
|
|
338
|
+
# If found: "Layout: 2,340x, Total: 850ms, Avg: 0.36ms"
|
|
339
|
+
# High count + individual operations fast = layout thrashing
|
|
340
|
+
# Cause: Reading layout properties (offsetTop, etc.) in a loop
|
|
341
|
+
# Solution: Batch reads before writes (read all → write all)
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Pattern 3: JavaScript Execution Bottleneck
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
# Analyze JS execution
|
|
348
|
+
uisnap-chrome-trace-analyze trace.db --js-time
|
|
349
|
+
|
|
350
|
+
# If found: "FunctionCall: 1624x, Total: 1445ms"
|
|
351
|
+
# Indicates: JS execution is main bottleneck
|
|
352
|
+
# Custom query to find hot functions:
|
|
353
|
+
duckdb trace.db "SELECT name, COUNT(*) FROM tasks WHERE name LIKE '%Function%' GROUP BY name ORDER BY COUNT(*) DESC LIMIT 10"
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Pattern 4: Paint Performance
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# Check paint operations
|
|
360
|
+
uisnap-chrome-trace-analyze trace.db --layout-paint
|
|
361
|
+
|
|
362
|
+
# If found: "Paint: 516x, each taking 5-10ms"
|
|
363
|
+
# Indicates: Expensive paint operations
|
|
364
|
+
# Causes: Large paint areas, complex CSS (shadows, blurs, gradients)
|
|
365
|
+
# Solution: Use will-change, reduce paint area, simplify styles
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Troubleshooting
|
|
369
|
+
|
|
370
|
+
### Trace file is huge (>100MB)
|
|
371
|
+
|
|
372
|
+
**Cause**: Traced too long (>30 seconds) or high-frequency events
|
|
373
|
+
|
|
374
|
+
**Solution**:
|
|
375
|
+
```javascript
|
|
376
|
+
// Keep traces short (5-10 seconds)
|
|
377
|
+
await utils.startChromeTrace(cdp);
|
|
378
|
+
// ... interactions ...
|
|
379
|
+
await utils.stopChromeTraceAndImport(cdp, tracePath); // Stop after 5-10s
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Database import fails
|
|
383
|
+
|
|
384
|
+
**Error**: `Error parsing Chrome trace JSON`
|
|
385
|
+
|
|
386
|
+
**Cause**: Incomplete or corrupted trace file
|
|
387
|
+
|
|
388
|
+
**Solution**:
|
|
389
|
+
```bash
|
|
390
|
+
# Check trace file validity
|
|
391
|
+
node -e "const trace = require('./chrome-trace.json'); console.log('Valid JSON, events:', trace.length)"
|
|
392
|
+
|
|
393
|
+
# If invalid, recapture
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### No long tasks found
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
uisnap-chrome-trace-analyze trace.db --long-tasks
|
|
400
|
+
# For details, use:
|
|
401
|
+
# --long-tasks Show 0 task(s) over 50ms
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**Cause**: Page is actually fast, or threshold is too high
|
|
405
|
+
|
|
406
|
+
**Solution**:
|
|
407
|
+
```bash
|
|
408
|
+
# Lower threshold
|
|
409
|
+
uisnap-chrome-trace-analyze trace.db --long-tasks --threshold=10
|
|
410
|
+
|
|
411
|
+
# Or check total JS time
|
|
412
|
+
uisnap-chrome-trace-analyze trace.db --js-time
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Query returns empty results
|
|
416
|
+
|
|
417
|
+
**Check database has data**:
|
|
418
|
+
```bash
|
|
419
|
+
duckdb trace.db "SELECT COUNT(*) FROM tasks"
|
|
420
|
+
# Should return thousands of events
|
|
421
|
+
|
|
422
|
+
# If 0, re-import:
|
|
423
|
+
uisnap-chrome-trace-import chrome-trace.json new-trace.db
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### "Tasks" table doesn't exist
|
|
427
|
+
|
|
428
|
+
**Error**: `Error: Catalog Error: Table with name tasks does not exist!`
|
|
429
|
+
|
|
430
|
+
**Cause**: Opened wrong database or import failed
|
|
431
|
+
|
|
432
|
+
**Solution**:
|
|
433
|
+
```bash
|
|
434
|
+
# Verify database path
|
|
435
|
+
ls -lh chrome-trace.db
|
|
436
|
+
|
|
437
|
+
# Re-import if needed
|
|
438
|
+
uisnap-chrome-trace-import chrome-trace.json chrome-trace.db
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Manual Import (Advanced)
|
|
442
|
+
|
|
443
|
+
If auto-import fails or you have existing trace JSON:
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
uisnap-chrome-trace-import <trace.json> <output.db>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Example**:
|
|
450
|
+
```bash
|
|
451
|
+
# Import from downloaded Chrome trace
|
|
452
|
+
uisnap-chrome-trace-import ~/Downloads/trace.json analysis.db
|
|
453
|
+
|
|
454
|
+
# Analyze
|
|
455
|
+
uisnap-chrome-trace-analyze analysis.db --full
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
The database stays on disk. Query it repeatedly without re-importing.
|
|
459
|
+
|
|
460
|
+
### Reading the timeline
|
|
461
|
+
|
|
462
|
+
Events are ordered by `ts_ms` (timestamp in milliseconds):
|
|
463
|
+
|
|
464
|
+
```
|
|
465
|
+
0ms - Page load starts
|
|
466
|
+
500ms - EvaluateScript: 87ms (script execution)
|
|
467
|
+
1200ms - FunctionCall: 62ms (user code)
|
|
468
|
+
1850ms - Layout: 15ms (layout calculation)
|
|
469
|
+
2000ms - Paint: 8ms (rendering)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Use timestamps to correlate with user actions or identify patterns.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-01-02
|
|
9
|
+
|
|
10
|
+
**Initial release of uisnap** (formerly playwright-debug-toolkit)
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
#### Core Capture Commands
|
|
15
|
+
- `uisnap snapshot` - Capture full page state (ARIA tree, console, network, web vitals, Chrome trace)
|
|
16
|
+
- `uisnap exec` - Execute custom Playwright scripts for multi-step flows
|
|
17
|
+
- Auto-generated timestamped output directories: `snapshots/{hostname}/{timestamp}/`
|
|
18
|
+
- "latest" symlink for convenience when querying most recent snapshot
|
|
19
|
+
|
|
20
|
+
#### Analysis Commands
|
|
21
|
+
- `uisnap-analyze-console` - Analyze console logs with summary and grouping by type
|
|
22
|
+
- `uisnap-analyze-network` - Analyze network requests by status, type, domain, and performance
|
|
23
|
+
- `uisnap-query-a11y` - Query accessibility tree by role (buttons, links, headings) or text content
|
|
24
|
+
- `uisnap-chrome-trace-analyze` - Analyze Chrome performance traces with progressive disclosure
|
|
25
|
+
- `uisnap-chrome-trace-import` - Import Chrome trace JSON to DuckDB for custom queries
|
|
26
|
+
|
|
27
|
+
#### Developer Experience
|
|
28
|
+
- Comprehensive error messages with troubleshooting steps
|
|
29
|
+
- Project root detection (walks up from CWD to find `.git` or `package.json`)
|
|
30
|
+
- Clear output directory logging
|
|
31
|
+
- Support for both auto-generated and explicit output paths
|
|
32
|
+
|
|
33
|
+
#### Claude Code Integration
|
|
34
|
+
- Skill definition for teaching Claude Code when to use this toolkit
|
|
35
|
+
- Detailed reference documentation for snapshot and trace analysis
|
|
36
|
+
- Installation guide for team sharing vs personal use
|
|
37
|
+
|
|
38
|
+
#### Performance
|
|
39
|
+
- Token efficiency: ~17x reduction vs traditional DOM debugging
|
|
40
|
+
- Chrome trace: ~18,000x reduction vs raw JSON
|
|
41
|
+
- DuckDB-backed trace storage enables sub-second queries on 36MB+ traces
|
|
42
|
+
|
|
43
|
+
#### Data Formats
|
|
44
|
+
- YAML accessibility snapshots (Playwright ARIA format)
|
|
45
|
+
- JSONL console and network logs (one JSON object per line)
|
|
46
|
+
- JSON metadata (page title, URL, viewport, timestamp, web vitals)
|
|
47
|
+
- DuckDB trace databases for efficient querying
|
|
48
|
+
|
|
49
|
+
#### Testing
|
|
50
|
+
- 61 test cases across core runtime, snapshot analysis, and trace analysis
|
|
51
|
+
- Test parallelization for fast CI/CD (10x speedup on unit tests)
|
|
52
|
+
- Comprehensive error handling coverage
|
|
53
|
+
|
|
54
|
+
### Technical Details
|
|
55
|
+
|
|
56
|
+
**Supported Node Versions**: >=18.0.0
|
|
57
|
+
|
|
58
|
+
**Dependencies**:
|
|
59
|
+
- Playwright 1.49.0
|
|
60
|
+
- DuckDB (async)
|
|
61
|
+
- YAML parser
|
|
62
|
+
- adm-zip (for trace handling)
|
|
63
|
+
|
|
64
|
+
**Output Formats**:
|
|
65
|
+
- `a11y.yaml` - Accessibility tree snapshot
|
|
66
|
+
- `console.jsonl` - Console messages (errors, warnings, logs)
|
|
67
|
+
- `network.jsonl` - Network requests (status, timing, type)
|
|
68
|
+
- `metadata.json` - Page metadata and web vitals
|
|
69
|
+
- `chrome-trace.json` - Chrome DevTools performance trace
|
|
70
|
+
- `chrome-trace.db` - DuckDB database for trace queries
|
|
71
|
+
|
|
72
|
+
**CLI Commands**:
|
|
73
|
+
- `uisnap` - Main entry point
|
|
74
|
+
- `uisnap-diagnose` - Diagnostic utilities
|
|
75
|
+
- `uisnap-analyze-console` - Console log analysis
|
|
76
|
+
- `uisnap-analyze-network` - Network request analysis
|
|
77
|
+
- `uisnap-query-a11y` - Accessibility tree queries
|
|
78
|
+
- `uisnap-chrome-trace-import` - Import Chrome trace to DuckDB
|
|
79
|
+
- `uisnap-chrome-trace-analyze` - Analyze Chrome trace database
|
|
80
|
+
- `uisnap-trace-import` - Legacy trace import utility
|
|
81
|
+
|
|
82
|
+
### Known Limitations
|
|
83
|
+
|
|
84
|
+
- Chromium only (Firefox/WebKit support planned for future releases)
|
|
85
|
+
- Chrome trace import requires DuckDB (automatically installed)
|
|
86
|
+
- Symlinks may not work on Windows (uses `fs.symlinkSync` with `'dir'` type)
|
|
87
|
+
- Sequential execution required for DuckDB operations (file-level WAL locking)
|
|
88
|
+
|
|
89
|
+
### Documentation
|
|
90
|
+
|
|
91
|
+
- README.md - User-facing installation and usage guide
|
|
92
|
+
- SKILL-INSTALLATION.md - Guide for installing Claude Code skill
|
|
93
|
+
- `.claude/skills/uisnap/` - Skill definition and reference docs
|
|
94
|
+
- `examples/` - Sample scripts for common debugging workflows
|
|
95
|
+
|
|
96
|
+
[0.1.0]: https://github.com/tonyhschu/uisnap/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tony Chu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|