nuxt-devtools-observatory 0.1.30 → 0.1.32

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.
Files changed (51) hide show
  1. package/README.md +117 -30
  2. package/client/.env.example +2 -1
  3. package/client/dist/assets/index-5Wl1XYRH.js +17 -0
  4. package/client/dist/assets/index-DT_QUiIh.css +1 -0
  5. package/client/dist/index.html +2 -2
  6. package/client/src/App.vue +4 -0
  7. package/client/src/components/Flamegraph.vue +442 -0
  8. package/client/src/components/SpanInspector.vue +446 -0
  9. package/client/src/components/TraceFilter.vue +342 -0
  10. package/client/src/components/WaterfallView.vue +443 -0
  11. package/client/src/composables/composable-search.ts +124 -0
  12. package/client/src/composables/trace-render-aggregation.ts +254 -0
  13. package/client/src/composables/useExportImport.ts +63 -0
  14. package/client/src/composables/useTraceFilter.ts +160 -0
  15. package/client/src/stores/observatory.ts +13 -1
  16. package/client/src/views/ComposableTracker.vue +65 -30
  17. package/client/src/views/RenderHeatmap.vue +63 -1
  18. package/client/src/views/TraceViewer.vue +1212 -0
  19. package/client/src/views/TransitionTimeline.vue +1 -6
  20. package/dist/module.d.mts +5 -0
  21. package/dist/module.json +1 -1
  22. package/dist/module.mjs +31 -45
  23. package/dist/runtime/composables/composable-registry.d.ts +19 -0
  24. package/dist/runtime/composables/composable-registry.js +63 -5
  25. package/dist/runtime/composables/render-registry.js +74 -110
  26. package/dist/runtime/composables/transition-registry.js +103 -28
  27. package/dist/runtime/instrumentation/asyncData.d.ts +9 -0
  28. package/dist/runtime/instrumentation/asyncData.js +49 -0
  29. package/dist/runtime/instrumentation/component.d.ts +2 -0
  30. package/dist/runtime/instrumentation/component.js +126 -0
  31. package/dist/runtime/instrumentation/fetch.d.ts +2 -0
  32. package/dist/runtime/instrumentation/fetch.js +89 -0
  33. package/dist/runtime/instrumentation/route.d.ts +6 -0
  34. package/dist/runtime/instrumentation/route.js +41 -0
  35. package/dist/runtime/nitro/fetch-capture.d.ts +1 -2
  36. package/dist/runtime/nitro/fetch-capture.js +85 -7
  37. package/dist/runtime/nitro/ssr-trace-store.d.ts +85 -0
  38. package/dist/runtime/nitro/ssr-trace-store.js +84 -0
  39. package/dist/runtime/plugin.js +82 -2
  40. package/dist/runtime/tracing/context.d.ts +9 -0
  41. package/dist/runtime/tracing/context.js +15 -0
  42. package/dist/runtime/tracing/trace.d.ts +25 -0
  43. package/dist/runtime/tracing/trace.js +0 -0
  44. package/dist/runtime/tracing/traceStore.d.ts +39 -0
  45. package/dist/runtime/tracing/traceStore.js +101 -0
  46. package/dist/runtime/tracing/tracing.d.ts +27 -0
  47. package/dist/runtime/tracing/tracing.js +48 -0
  48. package/package.json +5 -1
  49. package/client/.env +0 -16
  50. package/client/dist/assets/index-BCaKoHBH.js +0 -17
  51. package/client/dist/assets/index-BmGW_M3W.css +0 -1
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Per-request SSR trace collector.
3
+ *
4
+ * Each incoming SSR page request gets its own record keyed by a unique
5
+ * requestId (stored on H3 `event.context`). Spans are accumulated during the
6
+ * request lifecycle and drained once the HTML is rendered (via the
7
+ * `render:html` Nitro hook), so they can be injected into the page as inline
8
+ * JSON for the client plugin to pick up.
9
+ */
10
+ export interface SsrSpan {
11
+ id: string;
12
+ name: string;
13
+ type: string;
14
+ /** Milliseconds relative to request start (0 = request began). */
15
+ startTime: number;
16
+ endTime?: number;
17
+ durationMs?: number;
18
+ status: 'ok' | 'error' | 'active';
19
+ metadata?: Record<string, unknown>;
20
+ }
21
+ export interface SsrTraceRecord {
22
+ traceId: string;
23
+ name: string;
24
+ spans: SsrSpan[];
25
+ }
26
+ /**
27
+ * Open a new per-request SSR record. A `navigation` span covering the full
28
+ * request is pre-populated; its end time is filled in when `drainSsrRecord`
29
+ * is called.
30
+ * @param {string} requestId - Unique identifier for the HTTP request, stored in `event.context`.
31
+ * @param {string} route - Request pathname (e.g. `/dashboard`).
32
+ * @param {string} method - HTTP method in upper-case (e.g. `GET`).
33
+ * @returns {SsrTraceRecord} The newly created `SsrTraceRecord` keyed by `requestId`.
34
+ */
35
+ export declare function createSsrRecord(requestId: string, route: string, method: string): SsrTraceRecord;
36
+ /**
37
+ * Append an SSR-side fetch span. `startMs` / `endMs` are milliseconds
38
+ * relative to request start (same origin as `createSsrRecord`).
39
+ * @param {string} requestId - The request identifier returned by `createSsrRecord`.
40
+ * @param {object} opts - Span options.
41
+ * @param {string} opts.url - The request URL or path that was fetched.
42
+ * @param {string} opts.method - HTTP method in upper-case (e.g. `GET`).
43
+ * @param {number} opts.startMs - Span start, in ms relative to the request start time.
44
+ * @param {number} opts.endMs - Span end, in ms relative to the request start time.
45
+ * @param {number} [opts.statusCode] - Optional HTTP response status code.
46
+ * @param {boolean} [opts.error] - Set to `true` to mark the span status as `error`.
47
+ */
48
+ export declare function addSsrFetchSpan(requestId: string, opts: {
49
+ url: string;
50
+ method: string;
51
+ startMs: number;
52
+ endMs: number;
53
+ statusCode?: number;
54
+ error?: boolean;
55
+ }): void;
56
+ /**
57
+ * Append a generic SSR phase span (e.g. `render:html`, `afterResponse`) to
58
+ * an existing request record.
59
+ * @param {string} requestId - The request identifier returned by `createSsrRecord`.
60
+ * @param {object} opts - Span options.
61
+ * @param {string} opts.name - Human-readable span name.
62
+ * @param {string} [opts.type] - Span type. Defaults to `server`.
63
+ * @param {number} opts.startMs - Span start, in ms relative to request start.
64
+ * @param {number} opts.endMs - Span end, in ms relative to request start.
65
+ * @param {boolean} [opts.error] - Set to `true` to mark the span status as `error`.
66
+ * @param {Record<string, unknown>} [opts.metadata] - Additional metadata fields.
67
+ */
68
+ export declare function addSsrPhaseSpan(requestId: string, opts: {
69
+ name: string;
70
+ type?: string;
71
+ startMs: number;
72
+ endMs: number;
73
+ error?: boolean;
74
+ metadata?: Record<string, unknown>;
75
+ }): void;
76
+ /**
77
+ * Finalize and remove the record for `requestId`. The pre-populated
78
+ * navigation span is closed with `durationMs`. Returns `undefined` if the
79
+ * requestId is unknown (e.g. non-page requests that never called
80
+ * `createSsrRecord`).
81
+ * @param {string} requestId - The request identifier returned by `createSsrRecord`.
82
+ * @param {number} durationMs - Total SSR request duration in milliseconds, used to close the navigation span.
83
+ * @returns {SsrTraceRecord | undefined} The completed `SsrTraceRecord`, or `undefined` if no record exists for `requestId`.
84
+ */
85
+ export declare function drainSsrRecord(requestId: string, durationMs: number): SsrTraceRecord | undefined;
@@ -0,0 +1,84 @@
1
+ const pending = /* @__PURE__ */ new Map();
2
+ let _counter = 0;
3
+ function newId(prefix) {
4
+ _counter = (_counter + 1) % 999999;
5
+ return `${prefix}_ssr_${Date.now()}_${_counter}`;
6
+ }
7
+ export function createSsrRecord(requestId, route, method) {
8
+ const record = {
9
+ traceId: newId("trace"),
10
+ name: `ssr:${route}`,
11
+ spans: [
12
+ {
13
+ id: newId("span"),
14
+ name: "ssr:navigation",
15
+ type: "navigation",
16
+ startTime: 0,
17
+ status: "active",
18
+ metadata: {
19
+ origin: "ssr",
20
+ route,
21
+ method
22
+ }
23
+ }
24
+ ]
25
+ };
26
+ pending.set(requestId, record);
27
+ return record;
28
+ }
29
+ export function addSsrFetchSpan(requestId, opts) {
30
+ const record = pending.get(requestId);
31
+ if (!record) {
32
+ return;
33
+ }
34
+ const durationMs = Math.max(opts.endMs - opts.startMs, 0);
35
+ record.spans.push({
36
+ id: newId("span"),
37
+ name: opts.url,
38
+ type: "fetch",
39
+ startTime: opts.startMs,
40
+ endTime: opts.endMs,
41
+ durationMs,
42
+ status: opts.error ? "error" : "ok",
43
+ metadata: {
44
+ origin: "ssr",
45
+ url: opts.url,
46
+ method: opts.method,
47
+ statusCode: opts.statusCode
48
+ }
49
+ });
50
+ }
51
+ export function addSsrPhaseSpan(requestId, opts) {
52
+ const record = pending.get(requestId);
53
+ if (!record) {
54
+ return;
55
+ }
56
+ const durationMs = Math.max(opts.endMs - opts.startMs, 0);
57
+ record.spans.push({
58
+ id: newId("span"),
59
+ name: opts.name,
60
+ type: opts.type ?? "server",
61
+ startTime: opts.startMs,
62
+ endTime: opts.endMs,
63
+ durationMs,
64
+ status: opts.error ? "error" : "ok",
65
+ metadata: {
66
+ origin: "ssr",
67
+ ...opts.metadata ?? {}
68
+ }
69
+ });
70
+ }
71
+ export function drainSsrRecord(requestId, durationMs) {
72
+ const record = pending.get(requestId);
73
+ pending.delete(requestId);
74
+ if (!record) {
75
+ return void 0;
76
+ }
77
+ const navSpan = record.spans[0];
78
+ if (navSpan) {
79
+ navSpan.endTime = durationMs;
80
+ navSpan.durationMs = durationMs;
81
+ navSpan.status = "ok";
82
+ }
83
+ return record;
84
+ }
@@ -5,6 +5,10 @@ import { setupFetchRegistry } from "./composables/fetch-registry.js";
5
5
  import { setupProvideInjectRegistry } from "./composables/provide-inject-registry.js";
6
6
  import { setupRenderRegistry } from "./composables/render-registry.js";
7
7
  import { setupTransitionRegistry } from "./composables/transition-registry.js";
8
+ import { setupComponentInstrumentation } from "./instrumentation/component.js";
9
+ import { setupFetchInstrumentation } from "./instrumentation/fetch.js";
10
+ import { setupRouteInstrumentation } from "./instrumentation/route.js";
11
+ import { traceStore } from "./tracing/traceStore.js";
8
12
  export default defineNuxtPlugin(() => {
9
13
  if (!import.meta.dev) {
10
14
  return;
@@ -41,7 +45,55 @@ export default defineNuxtPlugin(() => {
41
45
  if (config.transitionTracker) {
42
46
  registries.transition = setupTransitionRegistry();
43
47
  }
48
+ function mergeSsrSpans() {
49
+ if (!import.meta.client) {
50
+ return;
51
+ }
52
+ const el = document.getElementById("__observatory_ssr_spans__");
53
+ if (!el) {
54
+ return;
55
+ }
56
+ let record;
57
+ try {
58
+ record = JSON.parse(el.textContent ?? "");
59
+ } catch {
60
+ return;
61
+ }
62
+ if (!record?.traceId || !Array.isArray(record.spans)) {
63
+ return;
64
+ }
65
+ const navDurationMs = record.spans[0]?.durationMs ?? 0;
66
+ const traceStartTime = performance.now() - navDurationMs;
67
+ traceStore.createTrace({
68
+ id: record.traceId,
69
+ name: record.name,
70
+ startTime: traceStartTime,
71
+ metadata: { origin: "ssr" }
72
+ });
73
+ for (const span of record.spans) {
74
+ traceStore.addSpan({
75
+ id: span.id,
76
+ traceId: record.traceId,
77
+ name: span.name,
78
+ type: span.type,
79
+ startTime: traceStartTime + span.startTime,
80
+ endTime: span.endTime !== void 0 ? traceStartTime + span.endTime : void 0,
81
+ status: span.status,
82
+ metadata: { ...span.metadata ?? {}, origin: "ssr" }
83
+ });
84
+ }
85
+ traceStore.endTrace(record.traceId, {
86
+ endTime: traceStartTime + navDurationMs,
87
+ status: "ok",
88
+ metadata: { origin: "ssr" }
89
+ });
90
+ }
44
91
  if (import.meta.client) {
92
+ if (config.traceViewer) {
93
+ setupComponentInstrumentation(nuxtApp);
94
+ setupFetchInstrumentation(nuxtApp);
95
+ mergeSsrSpans();
96
+ }
45
97
  delete window.__observatory__;
46
98
  window.__observatory__ = registries;
47
99
  const composableRegistry = registries.composable;
@@ -121,6 +173,11 @@ export default defineNuxtPlugin(() => {
121
173
  });
122
174
  if (import.meta.client) {
123
175
  const router = useRouter();
176
+ if (config.traceViewer) {
177
+ setupRouteInstrumentation(nuxtApp, {
178
+ getCurrentPath: () => router.currentRoute.value.path ?? "/"
179
+ });
180
+ }
124
181
  router.beforeEach(
125
182
  (_to, from) => {
126
183
  if (!from || from.name === void 0) {
@@ -175,7 +232,8 @@ export default defineNuxtPlugin(() => {
175
232
  fetch: Array.isArray(snapshot.fetch) ? snapshot.fetch.length : 0,
176
233
  composables: Array.isArray(snapshot.composables) ? snapshot.composables.length : 0,
177
234
  renders: Array.isArray(snapshot.renders) ? snapshot.renders.length : 0,
178
- transitions: Array.isArray(snapshot.transitions) ? snapshot.transitions.length : 0
235
+ transitions: Array.isArray(snapshot.transitions) ? snapshot.transitions.length : 0,
236
+ traces: Array.isArray(snapshot.traces) ? snapshot.traces.length : 0
179
237
  });
180
238
  lastSnapshotSignature = JSON.stringify(snapshot);
181
239
  import.meta.hot.send("observatory:snapshot", snapshot);
@@ -207,13 +265,35 @@ export default defineNuxtPlugin(() => {
207
265
  const hasGetSnapshot = reg && typeof reg.getSnapshot === "function";
208
266
  snapshot[key === "composable" ? "composables" : key === "render" ? "renders" : key === "transition" ? "transitions" : key] = hasGetSnapshot ? safeParse(reg.getSnapshot(), fallback) : fallback;
209
267
  }
268
+ snapshot.traces = config.traceViewer ? traceStore.getAllTraces().map((trace) => ({
269
+ id: trace.id,
270
+ name: trace.name,
271
+ startTime: trace.startTime,
272
+ endTime: trace.endTime,
273
+ durationMs: trace.durationMs,
274
+ status: trace.status,
275
+ metadata: trace.metadata,
276
+ spans: trace.spans.map((span) => ({
277
+ id: span.id,
278
+ traceId: span.traceId,
279
+ parentSpanId: span.parentSpanId,
280
+ name: span.name,
281
+ type: span.type,
282
+ startTime: span.startTime,
283
+ endTime: span.endTime,
284
+ durationMs: span.durationMs,
285
+ status: span.status,
286
+ metadata: span.metadata
287
+ }))
288
+ })) : [];
210
289
  snapshot.features = {
211
290
  fetchDashboard: !!registries.fetch,
212
291
  provideInjectGraph: !!registries.provideInject,
213
292
  composableTracker: !!registries.composable,
214
293
  composableNavigationMode,
215
294
  renderHeatmap: !!registries.render,
216
- transitionTracker: !!registries.transition
295
+ transitionTracker: !!registries.transition,
296
+ traceViewer: !!config.traceViewer
217
297
  };
218
298
  return snapshot;
219
299
  }
@@ -0,0 +1,9 @@
1
+ declare const TRACE_CONTEXT_KEY = "__observatory_trace_context__";
2
+ type TraceContextCarrier = {
3
+ [TRACE_CONTEXT_KEY]?: {
4
+ currentTraceId?: string;
5
+ };
6
+ };
7
+ export declare function setCurrentTraceId(traceId: string | undefined, carrier?: TraceContextCarrier): void;
8
+ export declare function getCurrentTraceId(carrier?: TraceContextCarrier): string | undefined;
9
+ export {};
@@ -0,0 +1,15 @@
1
+ const TRACE_CONTEXT_KEY = "__observatory_trace_context__";
2
+ function getGlobalCarrier() {
3
+ return globalThis;
4
+ }
5
+ export function setCurrentTraceId(traceId, carrier) {
6
+ const target = carrier ?? getGlobalCarrier();
7
+ if (!target[TRACE_CONTEXT_KEY]) {
8
+ target[TRACE_CONTEXT_KEY] = {};
9
+ }
10
+ target[TRACE_CONTEXT_KEY].currentTraceId = traceId;
11
+ }
12
+ export function getCurrentTraceId(carrier) {
13
+ const target = carrier ?? getGlobalCarrier();
14
+ return target[TRACE_CONTEXT_KEY]?.currentTraceId;
15
+ }
@@ -0,0 +1,25 @@
1
+ export type SpanType = 'render' | 'component' | 'transition' | 'fetch' | 'composable' | 'navigation' | 'custom' | (string & {});
2
+ export type SpanStatus = 'active' | 'ok' | 'error' | 'cancelled';
3
+ export interface Span {
4
+ id: string;
5
+ traceId: string;
6
+ parentSpanId?: string;
7
+ name: string;
8
+ type: SpanType;
9
+ startTime: number;
10
+ endTime?: number;
11
+ durationMs?: number;
12
+ status: SpanStatus;
13
+ metadata?: Record<string, unknown>;
14
+ }
15
+ export type TraceStatus = 'active' | 'ok' | 'error' | 'cancelled';
16
+ export interface Trace {
17
+ id: string;
18
+ name: string;
19
+ startTime: number;
20
+ endTime?: number;
21
+ durationMs?: number;
22
+ status: TraceStatus;
23
+ metadata?: Record<string, unknown>;
24
+ spans: Span[];
25
+ }
File without changes
@@ -0,0 +1,39 @@
1
+ import type { Span, SpanStatus, Trace, TraceStatus } from './trace.js';
2
+ export interface CreateTraceInput {
3
+ id?: string;
4
+ name?: string;
5
+ startTime?: number;
6
+ metadata?: Record<string, unknown>;
7
+ }
8
+ export interface AddSpanInput {
9
+ id?: string;
10
+ traceId: string;
11
+ parentSpanId?: string;
12
+ name: string;
13
+ type: Span['type'];
14
+ startTime?: number;
15
+ endTime?: number;
16
+ status?: SpanStatus;
17
+ metadata?: Record<string, unknown>;
18
+ }
19
+ export interface EndTraceInput {
20
+ endTime?: number;
21
+ status?: TraceStatus;
22
+ metadata?: Record<string, unknown>;
23
+ }
24
+ export declare class TraceStore {
25
+ private readonly traces;
26
+ createTrace(input?: CreateTraceInput): Trace;
27
+ addSpan(input: AddSpanInput): Span;
28
+ endTrace(traceId: string, input?: EndTraceInput): Trace | null;
29
+ endSpan(spanId: string, traceId: string, input?: {
30
+ endTime?: number;
31
+ status?: SpanStatus;
32
+ metadata?: Record<string, unknown>;
33
+ }): Span | null;
34
+ getTrace(traceId: string): Trace | undefined;
35
+ getAllTraces(): Trace[];
36
+ clear(): void;
37
+ private ensureTrace;
38
+ }
39
+ export declare const traceStore: TraceStore;
@@ -0,0 +1,101 @@
1
+ function createId(prefix) {
2
+ const random = Math.random().toString(36).slice(2, 10);
3
+ return `${prefix}_${Date.now()}_${random}`;
4
+ }
5
+ function computeDuration(startTime, endTime) {
6
+ return Math.max(endTime - startTime, 0);
7
+ }
8
+ export class TraceStore {
9
+ traces = /* @__PURE__ */ new Map();
10
+ createTrace(input = {}) {
11
+ const startTime = input.startTime ?? performance.now();
12
+ const trace = {
13
+ id: input.id ?? createId("trace"),
14
+ name: input.name ?? "trace",
15
+ startTime,
16
+ status: "active",
17
+ metadata: input.metadata,
18
+ spans: []
19
+ };
20
+ this.traces.set(trace.id, trace);
21
+ return trace;
22
+ }
23
+ addSpan(input) {
24
+ const trace = this.ensureTrace(input.traceId, input.startTime);
25
+ const startTime = input.startTime ?? performance.now();
26
+ const endTime = input.endTime;
27
+ const span = {
28
+ id: input.id ?? createId("span"),
29
+ traceId: trace.id,
30
+ parentSpanId: input.parentSpanId,
31
+ name: input.name,
32
+ type: input.type,
33
+ startTime,
34
+ endTime,
35
+ durationMs: endTime !== void 0 ? computeDuration(startTime, endTime) : void 0,
36
+ status: input.status ?? (endTime !== void 0 ? "ok" : "active"),
37
+ metadata: input.metadata
38
+ };
39
+ trace.spans.push(span);
40
+ if (trace.endTime !== void 0) {
41
+ trace.durationMs = computeDuration(trace.startTime, trace.endTime);
42
+ }
43
+ return span;
44
+ }
45
+ endTrace(traceId, input = {}) {
46
+ const trace = this.traces.get(traceId);
47
+ if (!trace) {
48
+ return null;
49
+ }
50
+ const endTime = input.endTime ?? performance.now();
51
+ trace.endTime = endTime;
52
+ trace.durationMs = computeDuration(trace.startTime, endTime);
53
+ trace.status = input.status ?? "ok";
54
+ if (input.metadata) {
55
+ trace.metadata = {
56
+ ...trace.metadata ?? {},
57
+ ...input.metadata
58
+ };
59
+ }
60
+ return trace;
61
+ }
62
+ endSpan(spanId, traceId, input = {}) {
63
+ const trace = this.traces.get(traceId);
64
+ if (!trace) {
65
+ return null;
66
+ }
67
+ const span = trace.spans.find((item) => item.id === spanId);
68
+ if (!span) {
69
+ return null;
70
+ }
71
+ const endTime = input.endTime ?? performance.now();
72
+ span.endTime = endTime;
73
+ span.durationMs = computeDuration(span.startTime, endTime);
74
+ span.status = input.status ?? "ok";
75
+ if (input.metadata) {
76
+ span.metadata = {
77
+ ...span.metadata ?? {},
78
+ ...input.metadata
79
+ };
80
+ }
81
+ return span;
82
+ }
83
+ getTrace(traceId) {
84
+ return this.traces.get(traceId);
85
+ }
86
+ getAllTraces() {
87
+ return [...this.traces.values()];
88
+ }
89
+ clear() {
90
+ this.traces.clear();
91
+ }
92
+ ensureTrace(traceId, startTime) {
93
+ const existing = this.traces.get(traceId);
94
+ if (existing) {
95
+ return existing;
96
+ }
97
+ const trace = this.createTrace({ id: traceId, startTime });
98
+ return trace;
99
+ }
100
+ }
101
+ export const traceStore = new TraceStore();
@@ -0,0 +1,27 @@
1
+ import { type TraceStore } from './traceStore.js';
2
+ import type { Span, SpanStatus, SpanType, Trace } from './trace.js';
3
+ export interface StartSpanInput {
4
+ name: string;
5
+ type: SpanType;
6
+ traceId?: string;
7
+ parentSpanId?: string;
8
+ metadata?: Record<string, unknown>;
9
+ startTime?: number;
10
+ }
11
+ export interface EndSpanInput {
12
+ endTime?: number;
13
+ status?: SpanStatus;
14
+ metadata?: Record<string, unknown>;
15
+ }
16
+ export interface SpanHandle {
17
+ trace: Trace;
18
+ span: Span;
19
+ end: (input?: EndSpanInput) => Span;
20
+ }
21
+ export interface StartSpanOptions {
22
+ store?: TraceStore;
23
+ carrier?: object;
24
+ traceName?: string;
25
+ traceMetadata?: Record<string, unknown>;
26
+ }
27
+ export declare function startSpan(input: StartSpanInput, options?: StartSpanOptions): SpanHandle;
@@ -0,0 +1,48 @@
1
+ import { getCurrentTraceId, setCurrentTraceId } from "./context.js";
2
+ import { traceStore } from "./traceStore.js";
3
+ export function startSpan(input, options = {}) {
4
+ const store = options.store ?? traceStore;
5
+ const activeTraceId = input.traceId ?? getCurrentTraceId(options.carrier);
6
+ let trace = activeTraceId ? store.getTrace(activeTraceId) : void 0;
7
+ if (!trace) {
8
+ trace = store.createTrace({
9
+ id: activeTraceId,
10
+ name: options.traceName ?? input.name,
11
+ metadata: options.traceMetadata,
12
+ startTime: input.startTime
13
+ });
14
+ }
15
+ setCurrentTraceId(trace.id, options.carrier);
16
+ const span = store.addSpan({
17
+ traceId: trace.id,
18
+ parentSpanId: input.parentSpanId,
19
+ name: input.name,
20
+ type: input.type,
21
+ metadata: input.metadata,
22
+ startTime: input.startTime
23
+ });
24
+ let ended = false;
25
+ const end = (endInput = {}) => {
26
+ if (ended) {
27
+ return span;
28
+ }
29
+ const endedSpan = store.endSpan(span.id, trace.id, {
30
+ endTime: endInput.endTime,
31
+ status: endInput.status,
32
+ metadata: endInput.metadata
33
+ });
34
+ ended = true;
35
+ if (endedSpan) {
36
+ span.endTime = endedSpan.endTime;
37
+ span.durationMs = endedSpan.durationMs;
38
+ span.status = endedSpan.status;
39
+ span.metadata = endedSpan.metadata;
40
+ }
41
+ return span;
42
+ };
43
+ return {
44
+ trace,
45
+ span,
46
+ end
47
+ };
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-devtools-observatory",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "Nuxt DevTools: useFetch Dashboard, provide/inject Graph, Composable Tracker, Render Heatmap",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -27,6 +27,10 @@
27
27
  "./runtime/fetch-registry": {
28
28
  "types": "./dist/runtime/composables/fetch-registry.d.ts",
29
29
  "import": "./dist/runtime/composables/fetch-registry.js"
30
+ },
31
+ "./runtime/async-data-instrumentation": {
32
+ "types": "./dist/runtime/instrumentation/asyncData.d.ts",
33
+ "import": "./dist/runtime/instrumentation/asyncData.js"
30
34
  }
31
35
  },
32
36
  "files": [
package/client/.env DELETED
@@ -1,16 +0,0 @@
1
- # Observatory registry/configurable limits
2
- VITE_OBSERVATORY_FETCH_DASHBOARD=true
3
- VITE_OBSERVATORY_PROVIDE_INJECT_GRAPH=true
4
- VITE_OBSERVATORY_COMPOSABLE_TRACKER=true
5
- VITE_OBSERVATORY_RENDER_HEATMAP=true
6
- VITE_OBSERVATORY_TRANSITION_TRACKER=true
7
- VITE_OBSERVATORY_MAX_FETCH_ENTRIES=200
8
- VITE_OBSERVATORY_MAX_PAYLOAD_BYTES=10000
9
- VITE_OBSERVATORY_MAX_TRANSITIONS=500
10
- VITE_OBSERVATORY_MAX_COMPOSABLE_HISTORY=50
11
- VITE_OBSERVATORY_MAX_COMPOSABLE_ENTRIES=300
12
- VITE_OBSERVATORY_MAX_RENDER_TIMELINE=100
13
- VITE_OBSERVATORY_HEATMAP_THRESHOLD_COUNT=3
14
- VITE_OBSERVATORY_HEATMAP_THRESHOLD_TIME=1600
15
- VITE_OBSERVATORY_HEATMAP_HIDE_INTERNALS=true
16
- VITE_OBSERVATORY_INSTRUMENT_SERVER=true