nuxt-devtools-observatory 0.1.28 → 0.1.31
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 +93 -11
- package/client/.env +2 -1
- package/client/.env.example +2 -1
- package/client/dist/assets/index-BuMXDBO9.js +17 -0
- package/client/dist/assets/index-CwcspZ6w.css +1 -0
- package/client/dist/index.html +2 -2
- package/client/src/App.vue +4 -0
- package/client/src/components/Flamegraph.vue +443 -0
- package/client/src/components/SpanInspector.vue +446 -0
- package/client/src/components/TraceFilter.vue +344 -0
- package/client/src/components/WaterfallView.vue +443 -0
- package/client/src/composables/useResizablePane.ts +65 -0
- package/client/src/composables/useTraceFilter.ts +164 -0
- package/client/src/stores/observatory.ts +16 -2
- package/client/src/style.css +203 -28
- package/client/src/views/ComposableTracker.vue +324 -259
- package/client/src/views/FetchDashboard.vue +104 -133
- package/client/src/views/ProvideInjectGraph.vue +99 -109
- package/client/src/views/RenderHeatmap.vue +191 -147
- package/client/src/views/TraceViewer.vue +599 -0
- package/client/src/views/TransitionTimeline.vue +167 -137
- package/client/tsconfig.json +3 -1
- package/client/vite.config.ts +8 -0
- package/dist/module.d.mts +5 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +186 -200
- package/dist/runtime/composables/render-registry.js +66 -110
- package/dist/runtime/composables/transition-registry.js +103 -28
- package/dist/runtime/instrumentation/asyncData.d.ts +9 -0
- package/dist/runtime/instrumentation/asyncData.js +49 -0
- package/dist/runtime/instrumentation/component.d.ts +2 -0
- package/dist/runtime/instrumentation/component.js +126 -0
- package/dist/runtime/instrumentation/fetch.d.ts +2 -0
- package/dist/runtime/instrumentation/fetch.js +89 -0
- package/dist/runtime/instrumentation/route.d.ts +6 -0
- package/dist/runtime/instrumentation/route.js +41 -0
- package/dist/runtime/plugin.js +39 -3
- package/dist/runtime/tracing/context.d.ts +9 -0
- package/dist/runtime/tracing/context.js +15 -0
- package/dist/runtime/tracing/trace.d.ts +25 -0
- package/dist/runtime/tracing/trace.js +0 -0
- package/dist/runtime/tracing/traceStore.d.ts +39 -0
- package/dist/runtime/tracing/traceStore.js +101 -0
- package/dist/runtime/tracing/tracing.d.ts +27 -0
- package/dist/runtime/tracing/tracing.js +48 -0
- package/package.json +9 -6
- package/client/dist/assets/index-DXCGQOSF.js +0 -17
- package/client/dist/assets/index-htI4WwBU.css +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ref } from 'vue'
|
|
2
2
|
import { useDevtoolsClient, onDevtoolsClientConnected } from '@nuxt/devtools-kit/iframe-client'
|
|
3
|
-
import type { ObservatorySnapshot, ObservatoryServerFunctions, ObservatoryClientFunctions } from '
|
|
4
|
-
import type { FetchEntry, ProvideEntry, InjectEntry, ComposableEntry, RenderEntry, TransitionEntry } from '
|
|
3
|
+
import type { ObservatorySnapshot, ObservatoryServerFunctions, ObservatoryClientFunctions } from '@observatory/types/rpc'
|
|
4
|
+
import type { FetchEntry, ProvideEntry, InjectEntry, ComposableEntry, RenderEntry, TransitionEntry, TraceEntry } from '@observatory/types/snapshot'
|
|
5
5
|
|
|
6
6
|
type ProvideInjectSnapshot = { provides: ProvideEntry[]; injects: InjectEntry[] }
|
|
7
7
|
|
|
@@ -10,6 +10,7 @@ const provideInject = ref<ProvideInjectSnapshot>({ provides: [], injects: [] })
|
|
|
10
10
|
const composables = ref<ComposableEntry[]>([])
|
|
11
11
|
const renders = ref<RenderEntry[]>([])
|
|
12
12
|
const transitions = ref<TransitionEntry[]>([])
|
|
13
|
+
const traces = ref<TraceEntry[]>([])
|
|
13
14
|
const connected = ref(false)
|
|
14
15
|
const features = ref<ObservatorySnapshot['features']>({})
|
|
15
16
|
const debugRpc = typeof window !== 'undefined' && new URLSearchParams(window.location.search).has('debugRpc')
|
|
@@ -50,6 +51,7 @@ function applySnapshot(data: ObservatorySnapshot) {
|
|
|
50
51
|
composables.value = cloneArray(data.composables as ComposableEntry[] | undefined)
|
|
51
52
|
renders.value = normalizeRenderEntries(data.renders as RenderEntry[] | undefined)
|
|
52
53
|
transitions.value = cloneArray(data.transitions as TransitionEntry[] | undefined)
|
|
54
|
+
traces.value = cloneArray(data.traces as TraceEntry[] | undefined)
|
|
53
55
|
features.value = data.features || {}
|
|
54
56
|
|
|
55
57
|
// If the server snapshot disagrees with the user's requested mode,
|
|
@@ -79,6 +81,7 @@ function applySnapshot(data: ObservatorySnapshot) {
|
|
|
79
81
|
composables: composables.value.length,
|
|
80
82
|
renders: renders.value.length,
|
|
81
83
|
transitions: transitions.value.length,
|
|
84
|
+
traces: traces.value.length,
|
|
82
85
|
})
|
|
83
86
|
}
|
|
84
87
|
}
|
|
@@ -89,6 +92,16 @@ function ensureStarted() {
|
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
started = true
|
|
95
|
+
|
|
96
|
+
// Support mock data injection via postMessage (used by the screenshot capture script).
|
|
97
|
+
if (typeof window !== 'undefined') {
|
|
98
|
+
window.addEventListener('message', (event) => {
|
|
99
|
+
if (event.data && event.data.type === 'observatory:snapshot') {
|
|
100
|
+
applySnapshot(event.data.data)
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
92
105
|
const client = useDevtoolsClient()
|
|
93
106
|
|
|
94
107
|
const setupRpc = () => {
|
|
@@ -214,6 +227,7 @@ export function useObservatoryData() {
|
|
|
214
227
|
composables,
|
|
215
228
|
renders,
|
|
216
229
|
transitions,
|
|
230
|
+
traces,
|
|
217
231
|
features,
|
|
218
232
|
connected,
|
|
219
233
|
refresh,
|
package/client/src/style.css
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--tracker-space-1: 4px;
|
|
3
|
+
--tracker-space-2: 8px;
|
|
4
|
+
--tracker-space-3: 12px;
|
|
5
|
+
--tracker-space-4: 16px;
|
|
6
|
+
--tracker-space-5: 24px;
|
|
7
|
+
--tracker-gap-view: 10px;
|
|
8
|
+
--tracker-gap-toolbar: 6px;
|
|
9
|
+
--tracker-gap-grid: 8px;
|
|
10
|
+
--tracker-font-size-xs: 10px;
|
|
11
|
+
--tracker-font-size-sm: 11px;
|
|
12
|
+
--tracker-font-size-md: 12px;
|
|
13
|
+
--tracker-font-size-stat: 20px;
|
|
14
|
+
--tracker-border-width: 0.5px;
|
|
15
|
+
--tracker-resize-handle-width: 8px;
|
|
16
|
+
--tracker-resize-handle-gutter: 2px;
|
|
17
|
+
--tracker-panel-width: 280px;
|
|
18
|
+
--tracker-transition-fast: 0.12s;
|
|
19
|
+
--tracker-transition-ui: 0.15s;
|
|
20
|
+
--tracker-tint-purple: rgb(127 119 221 / 15%);
|
|
21
|
+
--tracker-tint-purple-strong: rgb(127 119 221 / 20%);
|
|
22
|
+
--tracker-tint-purple-soft: rgb(127 119 221 / 8%);
|
|
23
|
+
--tracker-tint-red: rgb(226 75 74 / 12%);
|
|
24
|
+
--tracker-tint-teal: rgb(29 158 117 / 12%);
|
|
25
|
+
--tracker-tint-teal-badge: rgb(29 158 117 / 15%);
|
|
26
|
+
--tracker-tint-amber: rgb(239 159 39 / 15%);
|
|
27
|
+
--tracker-tint-blue: rgb(55 138 221 / 12%);
|
|
28
|
+
}
|
|
29
|
+
|
|
1
30
|
* {
|
|
2
31
|
box-sizing: border-box;
|
|
3
32
|
margin: 0;
|
|
@@ -30,14 +59,14 @@ body {
|
|
|
30
59
|
/* ── Base elements ──────────────────────────────────────────────────────── */
|
|
31
60
|
button {
|
|
32
61
|
font-family: var(--font);
|
|
33
|
-
font-size:
|
|
62
|
+
font-size: var(--tracker-font-size-md);
|
|
34
63
|
cursor: pointer;
|
|
35
|
-
border:
|
|
64
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
36
65
|
background: transparent;
|
|
37
66
|
color: var(--text2);
|
|
38
|
-
padding:
|
|
67
|
+
padding: var(--tracker-space-1) 10px;
|
|
39
68
|
border-radius: var(--radius);
|
|
40
|
-
transition: background
|
|
69
|
+
transition: background var(--tracker-transition-fast);
|
|
41
70
|
}
|
|
42
71
|
|
|
43
72
|
button:hover {
|
|
@@ -49,19 +78,19 @@ button:active {
|
|
|
49
78
|
}
|
|
50
79
|
|
|
51
80
|
button.active {
|
|
52
|
-
background:
|
|
81
|
+
background: var(--tracker-tint-purple);
|
|
53
82
|
color: var(--purple);
|
|
54
83
|
border-color: var(--purple);
|
|
55
84
|
}
|
|
56
85
|
|
|
57
86
|
button.danger-active {
|
|
58
|
-
background:
|
|
87
|
+
background: var(--tracker-tint-red);
|
|
59
88
|
color: var(--red);
|
|
60
89
|
border-color: var(--red);
|
|
61
90
|
}
|
|
62
91
|
|
|
63
92
|
button.success-active {
|
|
64
|
-
background:
|
|
93
|
+
background: var(--tracker-tint-teal);
|
|
65
94
|
color: var(--teal);
|
|
66
95
|
border-color: var(--teal);
|
|
67
96
|
}
|
|
@@ -69,8 +98,8 @@ button.success-active {
|
|
|
69
98
|
input[type='text'],
|
|
70
99
|
input[type='search'] {
|
|
71
100
|
font-family: var(--font);
|
|
72
|
-
font-size:
|
|
73
|
-
border:
|
|
101
|
+
font-size: var(--tracker-font-size-md);
|
|
102
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
74
103
|
background: var(--bg2);
|
|
75
104
|
color: var(--text);
|
|
76
105
|
padding: 5px 10px;
|
|
@@ -82,7 +111,7 @@ input[type='search'] {
|
|
|
82
111
|
input[type='text']:focus,
|
|
83
112
|
input[type='search']:focus {
|
|
84
113
|
border-color: var(--purple);
|
|
85
|
-
box-shadow: 0 0 0 2px
|
|
114
|
+
box-shadow: 0 0 0 2px var(--tracker-tint-purple-strong);
|
|
86
115
|
}
|
|
87
116
|
|
|
88
117
|
input[type='range'] {
|
|
@@ -100,11 +129,11 @@ input[type='range'] {
|
|
|
100
129
|
}
|
|
101
130
|
|
|
102
131
|
.text-sm {
|
|
103
|
-
font-size:
|
|
132
|
+
font-size: var(--tracker-font-size-sm);
|
|
104
133
|
}
|
|
105
134
|
|
|
106
135
|
.text-xs {
|
|
107
|
-
font-size:
|
|
136
|
+
font-size: var(--tracker-font-size-xs);
|
|
108
137
|
}
|
|
109
138
|
|
|
110
139
|
.bold {
|
|
@@ -114,7 +143,7 @@ input[type='range'] {
|
|
|
114
143
|
/* ── Badge ──────────────────────────────────────────────────────────────── */
|
|
115
144
|
.badge {
|
|
116
145
|
display: inline-block;
|
|
117
|
-
font-size:
|
|
146
|
+
font-size: var(--tracker-font-size-xs);
|
|
118
147
|
font-weight: 500;
|
|
119
148
|
padding: 2px 7px;
|
|
120
149
|
border-radius: 99px;
|
|
@@ -122,42 +151,42 @@ input[type='range'] {
|
|
|
122
151
|
}
|
|
123
152
|
|
|
124
153
|
.badge-ok {
|
|
125
|
-
background:
|
|
154
|
+
background: var(--tracker-tint-teal-badge);
|
|
126
155
|
color: var(--teal);
|
|
127
156
|
}
|
|
128
157
|
|
|
129
158
|
.badge-err {
|
|
130
|
-
background:
|
|
159
|
+
background: var(--tracker-tint-red);
|
|
131
160
|
color: var(--red);
|
|
132
161
|
}
|
|
133
162
|
|
|
134
163
|
.badge-warn {
|
|
135
|
-
background:
|
|
164
|
+
background: var(--tracker-tint-amber);
|
|
136
165
|
color: var(--amber);
|
|
137
166
|
}
|
|
138
167
|
|
|
139
168
|
.badge-info {
|
|
140
|
-
background:
|
|
169
|
+
background: var(--tracker-tint-blue);
|
|
141
170
|
color: var(--blue);
|
|
142
171
|
}
|
|
143
172
|
|
|
144
173
|
.badge-gray {
|
|
145
174
|
background: var(--bg2);
|
|
146
175
|
color: var(--text3);
|
|
147
|
-
border:
|
|
176
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
148
177
|
}
|
|
149
178
|
|
|
150
179
|
.badge-purple {
|
|
151
|
-
background:
|
|
180
|
+
background: var(--tracker-tint-purple);
|
|
152
181
|
color: var(--purple);
|
|
153
182
|
}
|
|
154
183
|
|
|
155
184
|
/* ── Card ───────────────────────────────────────────────────────────────── */
|
|
156
185
|
.card {
|
|
157
186
|
background: var(--bg3);
|
|
158
|
-
border:
|
|
187
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
159
188
|
border-radius: var(--radius-lg);
|
|
160
|
-
padding:
|
|
189
|
+
padding: var(--tracker-space-3) 14px;
|
|
161
190
|
}
|
|
162
191
|
|
|
163
192
|
/* ── Table ──────────────────────────────────────────────────────────────── */
|
|
@@ -169,11 +198,11 @@ input[type='range'] {
|
|
|
169
198
|
|
|
170
199
|
.data-table th {
|
|
171
200
|
text-align: left;
|
|
172
|
-
font-size:
|
|
201
|
+
font-size: var(--tracker-font-size-xs);
|
|
173
202
|
font-weight: 500;
|
|
174
203
|
color: var(--text3);
|
|
175
204
|
padding: 6px 8px;
|
|
176
|
-
border-bottom:
|
|
205
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
177
206
|
text-transform: uppercase;
|
|
178
207
|
letter-spacing: 0.4px;
|
|
179
208
|
white-space: nowrap;
|
|
@@ -181,7 +210,7 @@ input[type='range'] {
|
|
|
181
210
|
|
|
182
211
|
.data-table td {
|
|
183
212
|
padding: 8px;
|
|
184
|
-
border-bottom:
|
|
213
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
185
214
|
color: var(--text);
|
|
186
215
|
vertical-align: middle;
|
|
187
216
|
}
|
|
@@ -192,18 +221,18 @@ input[type='range'] {
|
|
|
192
221
|
}
|
|
193
222
|
|
|
194
223
|
.data-table tr.selected td {
|
|
195
|
-
background:
|
|
224
|
+
background: var(--tracker-tint-purple-soft);
|
|
196
225
|
}
|
|
197
226
|
|
|
198
227
|
/* ── Stat card ──────────────────────────────────────────────────────────── */
|
|
199
228
|
.stat-card {
|
|
200
229
|
background: var(--bg2);
|
|
201
230
|
border-radius: var(--radius);
|
|
202
|
-
padding:
|
|
231
|
+
padding: var(--tracker-space-2) var(--tracker-space-3);
|
|
203
232
|
}
|
|
204
233
|
|
|
205
234
|
.stat-label {
|
|
206
|
-
font-size:
|
|
235
|
+
font-size: var(--tracker-font-size-xs);
|
|
207
236
|
color: var(--text3);
|
|
208
237
|
text-transform: uppercase;
|
|
209
238
|
letter-spacing: 0.4px;
|
|
@@ -211,10 +240,156 @@ input[type='range'] {
|
|
|
211
240
|
}
|
|
212
241
|
|
|
213
242
|
.stat-val {
|
|
214
|
-
font-size:
|
|
243
|
+
font-size: var(--tracker-font-size-stat);
|
|
215
244
|
font-weight: 500;
|
|
216
245
|
}
|
|
217
246
|
|
|
247
|
+
.stat-val--ok {
|
|
248
|
+
color: var(--teal);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.stat-val--pending {
|
|
252
|
+
color: var(--amber);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.stat-val--error {
|
|
256
|
+
color: var(--red);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.stat-val--active {
|
|
260
|
+
color: var(--purple);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* ── Tracker primitives ─────────────────────────────────────────────────── */
|
|
264
|
+
.tracker-view {
|
|
265
|
+
display: flex;
|
|
266
|
+
flex-direction: column;
|
|
267
|
+
height: 100%;
|
|
268
|
+
overflow: hidden;
|
|
269
|
+
padding: var(--tracker-space-3);
|
|
270
|
+
gap: var(--tracker-gap-view);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.tracker-stats-row {
|
|
274
|
+
display: grid;
|
|
275
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
276
|
+
gap: var(--tracker-gap-grid);
|
|
277
|
+
flex-shrink: 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.tracker-toolbar {
|
|
281
|
+
display: flex;
|
|
282
|
+
align-items: center;
|
|
283
|
+
gap: var(--tracker-gap-toolbar);
|
|
284
|
+
flex-shrink: 0;
|
|
285
|
+
flex-wrap: wrap;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.tracker-toolbar__spacer {
|
|
289
|
+
margin-left: auto;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.tracker-split {
|
|
293
|
+
display: flex;
|
|
294
|
+
gap: 0;
|
|
295
|
+
flex: 1;
|
|
296
|
+
overflow: hidden;
|
|
297
|
+
min-height: 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.tracker-table-wrap {
|
|
301
|
+
flex: 1;
|
|
302
|
+
overflow: auto;
|
|
303
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
304
|
+
border-radius: var(--radius-lg);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.tracker-resize-handle {
|
|
308
|
+
width: var(--tracker-resize-handle-width);
|
|
309
|
+
flex-shrink: 0;
|
|
310
|
+
cursor: col-resize;
|
|
311
|
+
background: transparent;
|
|
312
|
+
position: relative;
|
|
313
|
+
z-index: 1;
|
|
314
|
+
margin: 0 var(--tracker-resize-handle-gutter);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.tracker-resize-handle::after {
|
|
318
|
+
content: '';
|
|
319
|
+
position: absolute;
|
|
320
|
+
inset: 0 3px;
|
|
321
|
+
border-radius: 2px;
|
|
322
|
+
background: var(--border);
|
|
323
|
+
opacity: 0;
|
|
324
|
+
transition: opacity var(--tracker-transition-ui);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.tracker-resize-handle:hover::after {
|
|
328
|
+
opacity: 1;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.tracker-detail-panel {
|
|
332
|
+
flex-shrink: 0;
|
|
333
|
+
display: flex;
|
|
334
|
+
flex-direction: column;
|
|
335
|
+
gap: var(--tracker-space-2);
|
|
336
|
+
overflow: auto;
|
|
337
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
338
|
+
border-radius: var(--radius-lg);
|
|
339
|
+
padding: var(--tracker-space-3);
|
|
340
|
+
background: var(--bg3);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.tracker-detail-empty {
|
|
344
|
+
width: var(--tracker-panel-width);
|
|
345
|
+
flex-shrink: 0;
|
|
346
|
+
display: flex;
|
|
347
|
+
align-items: center;
|
|
348
|
+
justify-content: center;
|
|
349
|
+
color: var(--text3);
|
|
350
|
+
font-size: var(--tracker-font-size-md);
|
|
351
|
+
border: var(--tracker-border-width) dashed var(--border);
|
|
352
|
+
border-radius: var(--radius-lg);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.tracker-section-label {
|
|
356
|
+
font-size: var(--tracker-font-size-xs);
|
|
357
|
+
font-weight: 500;
|
|
358
|
+
text-transform: uppercase;
|
|
359
|
+
letter-spacing: 0.4px;
|
|
360
|
+
color: var(--text3);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.tracker-empty-cell {
|
|
364
|
+
text-align: center;
|
|
365
|
+
color: var(--text3);
|
|
366
|
+
padding: var(--tracker-space-5);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.tracker-mono-secondary {
|
|
370
|
+
font-size: var(--tracker-font-size-sm);
|
|
371
|
+
color: var(--text2);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.tracker-truncate {
|
|
375
|
+
display: block;
|
|
376
|
+
overflow: hidden;
|
|
377
|
+
text-overflow: ellipsis;
|
|
378
|
+
white-space: nowrap;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.tracker-progress-bar {
|
|
382
|
+
height: 4px;
|
|
383
|
+
background: var(--bg2);
|
|
384
|
+
border-radius: 2px;
|
|
385
|
+
overflow: hidden;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.tracker-progress-bar__fill {
|
|
389
|
+
height: 100%;
|
|
390
|
+
border-radius: 2px;
|
|
391
|
+
}
|
|
392
|
+
|
|
218
393
|
/* ── Layout helpers ─────────────────────────────────────────────────────── */
|
|
219
394
|
.flex {
|
|
220
395
|
display: flex;
|