lopata 0.5.2 → 0.7.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/dist/dashboard/{chunk-rae638a4.js → chunk-5nxa3jfc.js} +296 -93
- package/dist/dashboard/{chunk-a68x1m5f.css → chunk-pqnphvm2.css} +16 -0
- package/dist/dashboard/index.html +1 -1
- package/package.json +1 -1
- package/src/bindings/do-websocket-bridge.ts +9 -0
- package/src/bindings/durable-object.ts +6 -0
- package/src/bindings/websocket-pair.ts +13 -0
- package/src/cli/dev.ts +3 -0
- package/src/plugin.ts +3 -112
- package/src/setup-globals.ts +150 -0
- package/src/vite-plugin/config-plugin.ts +6 -2
- package/src/vite-plugin/dev-server-plugin.ts +217 -196
- package/src/vite-plugin/globals-plugin.ts +5 -79
|
@@ -5044,28 +5044,38 @@ function TraceWaterfall({ spans, events, highlightSpanId, onAddAttributeFilter }
|
|
|
5044
5044
|
childMap.set(key, []);
|
|
5045
5045
|
childMap.get(key).push(s3);
|
|
5046
5046
|
}
|
|
5047
|
+
const processedSpanIdsRef = A2(new Set);
|
|
5047
5048
|
const spanIdKey = spans.map((s3) => s3.spanId).join(",");
|
|
5048
5049
|
y2(() => {
|
|
5049
5050
|
if (spans.length === 0)
|
|
5050
5051
|
return;
|
|
5051
|
-
const
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5052
|
+
const previousProcessed = processedSpanIdsRef.current;
|
|
5053
|
+
const currentIds = spans.map((s3) => s3.spanId);
|
|
5054
|
+
const newSpanIds = new Set(currentIds.filter((id) => !previousProcessed.has(id)));
|
|
5055
|
+
processedSpanIdsRef.current = new Set(currentIds);
|
|
5056
|
+
if (newSpanIds.size === 0)
|
|
5057
|
+
return;
|
|
5058
|
+
setCollapsedSpans((prev) => {
|
|
5059
|
+
const next = new Set(prev);
|
|
5060
|
+
function walk(parentId, depth) {
|
|
5061
|
+
const children = childMap.get(parentId) ?? [];
|
|
5062
|
+
for (const child of children) {
|
|
5063
|
+
if (newSpanIds.has(child.spanId)) {
|
|
5064
|
+
const hasChildren = (childMap.get(child.spanId) ?? []).length > 0;
|
|
5065
|
+
if (hasChildren) {
|
|
5066
|
+
const spanDur = child.durationMs ?? 0;
|
|
5067
|
+
const significantDuration = spanDur > traceDuration * 0.1;
|
|
5068
|
+
if (depth >= 2 && !significantDuration) {
|
|
5069
|
+
next.add(child.spanId);
|
|
5070
|
+
}
|
|
5071
|
+
}
|
|
5061
5072
|
}
|
|
5073
|
+
walk(child.spanId, depth + 1);
|
|
5062
5074
|
}
|
|
5063
|
-
walk(child.spanId, depth + 1);
|
|
5064
5075
|
}
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
setExpandedSpan(null);
|
|
5076
|
+
walk(null, 0);
|
|
5077
|
+
return next;
|
|
5078
|
+
});
|
|
5069
5079
|
}, [spanIdKey]);
|
|
5070
5080
|
const toggleCollapse = (spanId) => {
|
|
5071
5081
|
setCollapsedSpans((prev) => {
|
|
@@ -5090,6 +5100,19 @@ function TraceWaterfall({ spans, events, highlightSpanId, onAddAttributeFilter }
|
|
|
5090
5100
|
return result;
|
|
5091
5101
|
}
|
|
5092
5102
|
const flatSpans = flattenTree(null, 0);
|
|
5103
|
+
const descendantErrorCount = new Map;
|
|
5104
|
+
function countErrors(parentId) {
|
|
5105
|
+
let count = 0;
|
|
5106
|
+
for (const child of childMap.get(parentId) ?? []) {
|
|
5107
|
+
if (child.status === "error")
|
|
5108
|
+
count++;
|
|
5109
|
+
const childErrors = countErrors(child.spanId);
|
|
5110
|
+
count += childErrors;
|
|
5111
|
+
descendantErrorCount.set(child.spanId, childErrors);
|
|
5112
|
+
}
|
|
5113
|
+
return count;
|
|
5114
|
+
}
|
|
5115
|
+
countErrors(null);
|
|
5093
5116
|
const getParentAttributes = (span) => {
|
|
5094
5117
|
if (!span.parentSpanId)
|
|
5095
5118
|
return {};
|
|
@@ -5146,8 +5169,13 @@ function TraceWaterfall({ spans, events, highlightSpanId, onAddAttributeFilter }
|
|
|
5146
5169
|
class: "inline-block w-4 flex-shrink-0"
|
|
5147
5170
|
}, undefined, false, undefined, this),
|
|
5148
5171
|
/* @__PURE__ */ u3("span", {
|
|
5149
|
-
class:
|
|
5172
|
+
class: `truncate ${span.status === "error" ? "text-red-400" : ""}`,
|
|
5150
5173
|
children: span.name
|
|
5174
|
+
}, undefined, false, undefined, this),
|
|
5175
|
+
(descendantErrorCount.get(span.spanId) ?? 0) > 0 && /* @__PURE__ */ u3("span", {
|
|
5176
|
+
class: "ml-1 flex-shrink-0 inline-flex items-center justify-center min-w-[16px] h-4 px-1 rounded-full text-[10px] font-medium",
|
|
5177
|
+
style: { background: "var(--color-badge-red-bg)", color: "var(--color-badge-red-text)" },
|
|
5178
|
+
children: descendantErrorCount.get(span.spanId)
|
|
5151
5179
|
}, undefined, false, undefined, this)
|
|
5152
5180
|
]
|
|
5153
5181
|
}, undefined, true, undefined, this),
|
|
@@ -5718,14 +5746,11 @@ function ErrorList() {
|
|
|
5718
5746
|
/* @__PURE__ */ u3("td", {
|
|
5719
5747
|
class: "px-4 py-2.5 text-right",
|
|
5720
5748
|
children: err.traceId ? /* @__PURE__ */ u3("a", {
|
|
5721
|
-
href: `#/traces
|
|
5749
|
+
href: `#/traces/${err.traceId}`,
|
|
5722
5750
|
onClick: (e3) => e3.stopPropagation(),
|
|
5723
5751
|
class: "text-link hover:text-accent-lime text-xs font-mono",
|
|
5724
|
-
children:
|
|
5725
|
-
|
|
5726
|
-
"..."
|
|
5727
|
-
]
|
|
5728
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */ u3("span", {
|
|
5752
|
+
children: err.traceId
|
|
5753
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ u3("span", {
|
|
5729
5754
|
class: "text-text-dim text-xs",
|
|
5730
5755
|
children: "-"
|
|
5731
5756
|
}, undefined, false, undefined, this)
|
|
@@ -5883,14 +5908,30 @@ function ErrorDetailPage({ errorId }) {
|
|
|
5883
5908
|
}, undefined, false, undefined, this)
|
|
5884
5909
|
}, undefined, false, undefined, this)
|
|
5885
5910
|
}, undefined, false, undefined, this),
|
|
5886
|
-
|
|
5911
|
+
detail.traceId && /* @__PURE__ */ u3(Section, {
|
|
5887
5912
|
title: "Trace",
|
|
5888
5913
|
open: true,
|
|
5889
|
-
children:
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5914
|
+
children: [
|
|
5915
|
+
/* @__PURE__ */ u3("div", {
|
|
5916
|
+
class: "px-4 py-2.5 border-b border-border-subtle flex items-center gap-2",
|
|
5917
|
+
children: [
|
|
5918
|
+
/* @__PURE__ */ u3("span", {
|
|
5919
|
+
class: "text-xs text-text-muted",
|
|
5920
|
+
children: "Trace ID:"
|
|
5921
|
+
}, undefined, false, undefined, this),
|
|
5922
|
+
/* @__PURE__ */ u3("a", {
|
|
5923
|
+
href: `#/traces/${detail.traceId}`,
|
|
5924
|
+
class: "text-link hover:text-accent-lime text-xs font-mono",
|
|
5925
|
+
children: detail.traceId
|
|
5926
|
+
}, undefined, false, undefined, this)
|
|
5927
|
+
]
|
|
5928
|
+
}, undefined, true, undefined, this),
|
|
5929
|
+
traceSpans && traceSpans.length > 0 && /* @__PURE__ */ u3(SimpleTraceWaterfall, {
|
|
5930
|
+
spans: traceSpans,
|
|
5931
|
+
highlightSpanId: detail.spanId
|
|
5932
|
+
}, undefined, false, undefined, this)
|
|
5933
|
+
]
|
|
5934
|
+
}, undefined, true, undefined, this),
|
|
5894
5935
|
data.request.method && data.request.url && /* @__PURE__ */ u3(Section, {
|
|
5895
5936
|
title: "Request",
|
|
5896
5937
|
open: true,
|
|
@@ -7554,6 +7595,14 @@ function ScheduledList() {
|
|
|
7554
7595
|
}
|
|
7555
7596
|
|
|
7556
7597
|
// src/dashboard/views/traces.tsx
|
|
7598
|
+
var SOURCE_BADGE_STYLES = {
|
|
7599
|
+
fetch: { bg: "var(--color-badge-blue-bg)", color: "var(--color-badge-blue-text)" },
|
|
7600
|
+
scheduled: { bg: "var(--color-badge-purple-bg)", color: "var(--color-badge-purple-text)" },
|
|
7601
|
+
queue: { bg: "var(--color-badge-orange-bg)", color: "var(--color-badge-orange-text)" },
|
|
7602
|
+
alarm: { bg: "var(--color-badge-yellow-bg)", color: "var(--color-badge-yellow-text)" },
|
|
7603
|
+
workflow: { bg: "var(--color-badge-emerald-bg)", color: "var(--color-badge-emerald-text)" }
|
|
7604
|
+
};
|
|
7605
|
+
var DEFAULT_BADGE_STYLE = { bg: "var(--color-badge-red-bg)", color: "var(--color-badge-red-text)" };
|
|
7557
7606
|
var eventListeners = new Set;
|
|
7558
7607
|
function onTraceEvents(fn) {
|
|
7559
7608
|
eventListeners.add(fn);
|
|
@@ -7568,6 +7617,39 @@ function emitTraceEvents(events) {
|
|
|
7568
7617
|
} catch {}
|
|
7569
7618
|
}
|
|
7570
7619
|
}
|
|
7620
|
+
function useTraceData(traceId) {
|
|
7621
|
+
const [spans, setSpans] = d2([]);
|
|
7622
|
+
const [events, setEvents] = d2([]);
|
|
7623
|
+
const [traceErrors, setTraceErrors] = d2([]);
|
|
7624
|
+
const [isLoading, setIsLoading] = d2(true);
|
|
7625
|
+
y2(() => {
|
|
7626
|
+
setIsLoading(true);
|
|
7627
|
+
rpc("traces.getTrace", { traceId }).then((data) => {
|
|
7628
|
+
setSpans(data.spans);
|
|
7629
|
+
setEvents(data.events);
|
|
7630
|
+
setIsLoading(false);
|
|
7631
|
+
});
|
|
7632
|
+
rpc("traces.errors", { traceId }).then(setTraceErrors).catch(() => {});
|
|
7633
|
+
}, [traceId]);
|
|
7634
|
+
y2(() => {
|
|
7635
|
+
return onTraceEvents((traceEvents) => {
|
|
7636
|
+
for (const ev of traceEvents) {
|
|
7637
|
+
if (ev.type === "span.start" && ev.span.traceId === traceId) {
|
|
7638
|
+
setSpans((prev) => {
|
|
7639
|
+
if (prev.some((s3) => s3.spanId === ev.span.spanId))
|
|
7640
|
+
return prev;
|
|
7641
|
+
return [...prev, ev.span];
|
|
7642
|
+
});
|
|
7643
|
+
} else if (ev.type === "span.end" && ev.span.traceId === traceId) {
|
|
7644
|
+
setSpans((prev) => prev.map((s3) => s3.spanId === ev.span.spanId ? ev.span : s3));
|
|
7645
|
+
} else if (ev.type === "span.event" && ev.event.traceId === traceId) {
|
|
7646
|
+
setEvents((prev) => [...prev, ev.event]);
|
|
7647
|
+
}
|
|
7648
|
+
}
|
|
7649
|
+
});
|
|
7650
|
+
}, [traceId]);
|
|
7651
|
+
return { spans, events, traceErrors, isLoading };
|
|
7652
|
+
}
|
|
7571
7653
|
function useTraceStream() {
|
|
7572
7654
|
const [traces, setTraces] = d2(new Map);
|
|
7573
7655
|
const [wsStatus, setWsStatus] = d2("connecting");
|
|
@@ -7679,7 +7761,16 @@ var TIME_RANGE_OPTIONS = [
|
|
|
7679
7761
|
{ label: "24h", ms: 24 * 60 * 60 * 1000 },
|
|
7680
7762
|
{ label: "All", ms: 0 }
|
|
7681
7763
|
];
|
|
7682
|
-
function TracesView() {
|
|
7764
|
+
function TracesView({ route }) {
|
|
7765
|
+
const traceIdFromRoute = route.startsWith("/traces/") ? route.slice("/traces/".length) : null;
|
|
7766
|
+
if (traceIdFromRoute) {
|
|
7767
|
+
return /* @__PURE__ */ u3(TraceDetailPage, {
|
|
7768
|
+
traceId: traceIdFromRoute
|
|
7769
|
+
}, undefined, false, undefined, this);
|
|
7770
|
+
}
|
|
7771
|
+
return /* @__PURE__ */ u3(TracesListView, {}, undefined, false, undefined, this);
|
|
7772
|
+
}
|
|
7773
|
+
function TracesListView() {
|
|
7683
7774
|
const { traces, setFilter, wsStatus } = useTraceStream();
|
|
7684
7775
|
const [selectedTraceId, setSelectedTraceId] = d2(null);
|
|
7685
7776
|
const [pathFilter, setPathFilter] = d2("");
|
|
@@ -7766,10 +7857,7 @@ function TracesView() {
|
|
|
7766
7857
|
]
|
|
7767
7858
|
}, undefined, true, undefined, this),
|
|
7768
7859
|
/* @__PURE__ */ u3("button", {
|
|
7769
|
-
onClick: () =>
|
|
7770
|
-
clearTraces.mutate();
|
|
7771
|
-
setSelectedTraceId(null);
|
|
7772
|
-
},
|
|
7860
|
+
onClick: () => clearTraces.mutate(),
|
|
7773
7861
|
class: "rounded-md px-3 py-1.5 text-sm font-medium bg-panel border border-border text-text-secondary btn-danger transition-all",
|
|
7774
7862
|
children: "Clear all"
|
|
7775
7863
|
}, undefined, false, undefined, this)
|
|
@@ -7973,6 +8061,132 @@ function TracesView() {
|
|
|
7973
8061
|
]
|
|
7974
8062
|
}, undefined, true, undefined, this);
|
|
7975
8063
|
}
|
|
8064
|
+
function TraceDetailPage({ traceId }) {
|
|
8065
|
+
const { spans, events, traceErrors, isLoading } = useTraceData(traceId);
|
|
8066
|
+
const rootSpan = spans.find((s3) => !s3.parentSpanId);
|
|
8067
|
+
return /* @__PURE__ */ u3("div", {
|
|
8068
|
+
class: "p-4 sm:p-8 h-full flex flex-col",
|
|
8069
|
+
children: [
|
|
8070
|
+
/* @__PURE__ */ u3("div", {
|
|
8071
|
+
class: "flex items-center gap-3 mb-6",
|
|
8072
|
+
children: [
|
|
8073
|
+
/* @__PURE__ */ u3("button", {
|
|
8074
|
+
onClick: () => navigate("/traces"),
|
|
8075
|
+
class: "flex items-center gap-1.5 text-sm text-text-secondary hover:text-ink transition-colors",
|
|
8076
|
+
children: [
|
|
8077
|
+
/* @__PURE__ */ u3("svg", {
|
|
8078
|
+
class: "w-4 h-4",
|
|
8079
|
+
viewBox: "0 0 20 20",
|
|
8080
|
+
fill: "currentColor",
|
|
8081
|
+
children: /* @__PURE__ */ u3("path", {
|
|
8082
|
+
"fill-rule": "evenodd",
|
|
8083
|
+
d: "M17 10a.75.75 0 01-.75.75H5.612l4.158 3.96a.75.75 0 11-1.04 1.08l-5.5-5.25a.75.75 0 010-1.08l5.5-5.25a.75.75 0 111.04 1.08L5.612 9.25H16.25A.75.75 0 0117 10z",
|
|
8084
|
+
"clip-rule": "evenodd"
|
|
8085
|
+
}, undefined, false, undefined, this)
|
|
8086
|
+
}, undefined, false, undefined, this),
|
|
8087
|
+
"Back to traces"
|
|
8088
|
+
]
|
|
8089
|
+
}, undefined, true, undefined, this),
|
|
8090
|
+
/* @__PURE__ */ u3("div", {
|
|
8091
|
+
class: "h-5 w-px bg-border"
|
|
8092
|
+
}, undefined, false, undefined, this),
|
|
8093
|
+
/* @__PURE__ */ u3("div", {
|
|
8094
|
+
children: [
|
|
8095
|
+
/* @__PURE__ */ u3("div", {
|
|
8096
|
+
class: "flex items-center gap-2",
|
|
8097
|
+
children: [
|
|
8098
|
+
rootSpan && /* @__PURE__ */ u3(TraceStatusBadge, {
|
|
8099
|
+
status: rootSpan.status
|
|
8100
|
+
}, undefined, false, undefined, this),
|
|
8101
|
+
/* @__PURE__ */ u3("h1", {
|
|
8102
|
+
class: "text-lg font-bold text-ink",
|
|
8103
|
+
children: rootSpan?.name ?? "Loading..."
|
|
8104
|
+
}, undefined, false, undefined, this)
|
|
8105
|
+
]
|
|
8106
|
+
}, undefined, true, undefined, this),
|
|
8107
|
+
/* @__PURE__ */ u3("div", {
|
|
8108
|
+
class: "text-xs text-text-muted font-mono mt-0.5",
|
|
8109
|
+
children: [
|
|
8110
|
+
"Trace ",
|
|
8111
|
+
traceId,
|
|
8112
|
+
rootSpan?.workerName && /* @__PURE__ */ u3("span", {
|
|
8113
|
+
class: "ml-2 inline-flex px-2 py-0.5 rounded-md text-xs font-medium bg-panel-hover text-text-secondary",
|
|
8114
|
+
children: rootSpan.workerName
|
|
8115
|
+
}, undefined, false, undefined, this),
|
|
8116
|
+
rootSpan?.durationMs != null && /* @__PURE__ */ u3("span", {
|
|
8117
|
+
class: "ml-2 text-text-secondary",
|
|
8118
|
+
children: formatDuration(rootSpan.durationMs)
|
|
8119
|
+
}, undefined, false, undefined, this)
|
|
8120
|
+
]
|
|
8121
|
+
}, undefined, true, undefined, this)
|
|
8122
|
+
]
|
|
8123
|
+
}, undefined, true, undefined, this)
|
|
8124
|
+
]
|
|
8125
|
+
}, undefined, true, undefined, this),
|
|
8126
|
+
/* @__PURE__ */ u3("div", {
|
|
8127
|
+
class: "flex-1 overflow-y-auto scrollbar-thin min-h-0",
|
|
8128
|
+
children: isLoading ? /* @__PURE__ */ u3("div", {
|
|
8129
|
+
class: "text-text-muted text-sm py-12 text-center",
|
|
8130
|
+
children: "Loading trace..."
|
|
8131
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ u3("div", {
|
|
8132
|
+
children: [
|
|
8133
|
+
traceErrors.length > 0 && /* @__PURE__ */ u3("div", {
|
|
8134
|
+
class: "mb-4",
|
|
8135
|
+
children: [
|
|
8136
|
+
/* @__PURE__ */ u3("div", {
|
|
8137
|
+
class: "text-xs font-medium text-text-muted uppercase tracking-wider mb-2",
|
|
8138
|
+
children: [
|
|
8139
|
+
"Errors (",
|
|
8140
|
+
traceErrors.length,
|
|
8141
|
+
")"
|
|
8142
|
+
]
|
|
8143
|
+
}, undefined, true, undefined, this),
|
|
8144
|
+
/* @__PURE__ */ u3("div", {
|
|
8145
|
+
class: "space-y-1",
|
|
8146
|
+
children: traceErrors.map((err) => /* @__PURE__ */ u3("a", {
|
|
8147
|
+
href: `#/errors/${err.id}`,
|
|
8148
|
+
class: "flex items-center gap-2 px-3 py-2 rounded-md text-xs no-underline transition-colors",
|
|
8149
|
+
style: { background: "var(--color-error-highlight)", borderColor: "var(--color-error-ring)" },
|
|
8150
|
+
children: [
|
|
8151
|
+
err.source && (() => {
|
|
8152
|
+
const s3 = SOURCE_BADGE_STYLES[err.source] ?? DEFAULT_BADGE_STYLE;
|
|
8153
|
+
return /* @__PURE__ */ u3("span", {
|
|
8154
|
+
class: "inline-flex px-1.5 py-0.5 rounded text-[10px] font-medium",
|
|
8155
|
+
style: { background: s3.bg, color: s3.color },
|
|
8156
|
+
children: err.source
|
|
8157
|
+
}, undefined, false, undefined, this);
|
|
8158
|
+
})(),
|
|
8159
|
+
/* @__PURE__ */ u3("span", {
|
|
8160
|
+
class: "font-medium",
|
|
8161
|
+
style: { color: "var(--color-badge-red-text)" },
|
|
8162
|
+
children: err.errorName
|
|
8163
|
+
}, undefined, false, undefined, this),
|
|
8164
|
+
/* @__PURE__ */ u3("span", {
|
|
8165
|
+
style: { color: "var(--color-badge-red-text)" },
|
|
8166
|
+
class: "truncate",
|
|
8167
|
+
children: err.errorMessage
|
|
8168
|
+
}, undefined, false, undefined, this),
|
|
8169
|
+
/* @__PURE__ */ u3("span", {
|
|
8170
|
+
style: { color: "var(--color-badge-red-text)", opacity: 0.7 },
|
|
8171
|
+
class: "font-mono ml-auto flex-shrink-0",
|
|
8172
|
+
children: formatTimestamp(err.timestamp)
|
|
8173
|
+
}, undefined, false, undefined, this)
|
|
8174
|
+
]
|
|
8175
|
+
}, err.id, true, undefined, this))
|
|
8176
|
+
}, undefined, false, undefined, this)
|
|
8177
|
+
]
|
|
8178
|
+
}, undefined, true, undefined, this),
|
|
8179
|
+
/* @__PURE__ */ u3(TraceWaterfall, {
|
|
8180
|
+
spans,
|
|
8181
|
+
events,
|
|
8182
|
+
onAddAttributeFilter: () => {}
|
|
8183
|
+
}, undefined, false, undefined, this)
|
|
8184
|
+
]
|
|
8185
|
+
}, undefined, true, undefined, this)
|
|
8186
|
+
}, undefined, false, undefined, this)
|
|
8187
|
+
]
|
|
8188
|
+
}, undefined, true, undefined, this);
|
|
8189
|
+
}
|
|
7976
8190
|
function SpansListTab() {
|
|
7977
8191
|
const [spans, setSpans] = d2([]);
|
|
7978
8192
|
const [cursor, setCursor] = d2(null);
|
|
@@ -8070,11 +8284,8 @@ function SpansListTab() {
|
|
|
8070
8284
|
children: /* @__PURE__ */ u3("button", {
|
|
8071
8285
|
onClick: () => setSelectedTraceId(span.traceId),
|
|
8072
8286
|
class: "text-link hover:text-accent-lime text-xs font-mono",
|
|
8073
|
-
children:
|
|
8074
|
-
|
|
8075
|
-
"..."
|
|
8076
|
-
]
|
|
8077
|
-
}, undefined, true, undefined, this)
|
|
8287
|
+
children: span.traceId
|
|
8288
|
+
}, undefined, false, undefined, this)
|
|
8078
8289
|
}, undefined, false, undefined, this)
|
|
8079
8290
|
]
|
|
8080
8291
|
}, span.spanId, true, undefined, this))
|
|
@@ -8098,8 +8309,7 @@ function SpansListTab() {
|
|
|
8098
8309
|
}, undefined, false, undefined, this),
|
|
8099
8310
|
selectedTraceId && /* @__PURE__ */ u3(TraceDrawer, {
|
|
8100
8311
|
traceId: selectedTraceId,
|
|
8101
|
-
onClose: () => setSelectedTraceId(null)
|
|
8102
|
-
onAddAttributeFilter: () => {}
|
|
8312
|
+
onClose: () => setSelectedTraceId(null)
|
|
8103
8313
|
}, undefined, false, undefined, this)
|
|
8104
8314
|
]
|
|
8105
8315
|
}, undefined, true, undefined, this);
|
|
@@ -8108,6 +8318,7 @@ function LogsListTab() {
|
|
|
8108
8318
|
const [logs, setLogs] = d2([]);
|
|
8109
8319
|
const [cursor, setCursor] = d2(null);
|
|
8110
8320
|
const [isLoading, setIsLoading] = d2(true);
|
|
8321
|
+
const [selectedTraceId, setSelectedTraceId] = d2(null);
|
|
8111
8322
|
const loadLogs = q2((cur) => {
|
|
8112
8323
|
setIsLoading(true);
|
|
8113
8324
|
rpc("traces.listLogs", { limit: 50, cursor: cur }).then((data) => {
|
|
@@ -8188,12 +8399,13 @@ function LogsListTab() {
|
|
|
8188
8399
|
children: formatTimestamp(log.timestamp)
|
|
8189
8400
|
}, undefined, false, undefined, this),
|
|
8190
8401
|
/* @__PURE__ */ u3("td", {
|
|
8191
|
-
class: "px-4 py-2.5 text-right
|
|
8192
|
-
children:
|
|
8193
|
-
log.traceId
|
|
8194
|
-
"
|
|
8195
|
-
|
|
8196
|
-
|
|
8402
|
+
class: "px-4 py-2.5 text-right",
|
|
8403
|
+
children: /* @__PURE__ */ u3("button", {
|
|
8404
|
+
onClick: () => setSelectedTraceId(log.traceId),
|
|
8405
|
+
class: "text-link hover:text-accent-lime text-xs font-mono",
|
|
8406
|
+
children: log.traceId
|
|
8407
|
+
}, undefined, false, undefined, this)
|
|
8408
|
+
}, undefined, false, undefined, this)
|
|
8197
8409
|
]
|
|
8198
8410
|
}, log.id, true, undefined, this))
|
|
8199
8411
|
}, undefined, false, undefined, this)
|
|
@@ -8213,49 +8425,16 @@ function LogsListTab() {
|
|
|
8213
8425
|
isLoading && logs.length === 0 && /* @__PURE__ */ u3("div", {
|
|
8214
8426
|
class: "text-text-muted text-sm text-center py-12",
|
|
8215
8427
|
children: "Loading logs..."
|
|
8428
|
+
}, undefined, false, undefined, this),
|
|
8429
|
+
selectedTraceId && /* @__PURE__ */ u3(TraceDrawer, {
|
|
8430
|
+
traceId: selectedTraceId,
|
|
8431
|
+
onClose: () => setSelectedTraceId(null)
|
|
8216
8432
|
}, undefined, false, undefined, this)
|
|
8217
8433
|
]
|
|
8218
8434
|
}, undefined, true, undefined, this);
|
|
8219
8435
|
}
|
|
8220
|
-
var SOURCE_BADGE_STYLES = {
|
|
8221
|
-
fetch: { bg: "var(--color-badge-blue-bg)", color: "var(--color-badge-blue-text)" },
|
|
8222
|
-
scheduled: { bg: "var(--color-badge-purple-bg)", color: "var(--color-badge-purple-text)" },
|
|
8223
|
-
queue: { bg: "var(--color-badge-orange-bg)", color: "var(--color-badge-orange-text)" },
|
|
8224
|
-
alarm: { bg: "var(--color-badge-yellow-bg)", color: "var(--color-badge-yellow-text)" },
|
|
8225
|
-
workflow: { bg: "var(--color-badge-emerald-bg)", color: "var(--color-badge-emerald-text)" }
|
|
8226
|
-
};
|
|
8227
|
-
var DEFAULT_BADGE_STYLE = { bg: "var(--color-badge-red-bg)", color: "var(--color-badge-red-text)" };
|
|
8228
8436
|
function TraceDrawer({ traceId, onClose, onAddAttributeFilter }) {
|
|
8229
|
-
const
|
|
8230
|
-
const [events, setEvents] = d2([]);
|
|
8231
|
-
const [traceErrors, setTraceErrors] = d2([]);
|
|
8232
|
-
const [isLoading, setIsLoading] = d2(true);
|
|
8233
|
-
y2(() => {
|
|
8234
|
-
setIsLoading(true);
|
|
8235
|
-
rpc("traces.getTrace", { traceId }).then((data) => {
|
|
8236
|
-
setSpans(data.spans);
|
|
8237
|
-
setEvents(data.events);
|
|
8238
|
-
setIsLoading(false);
|
|
8239
|
-
});
|
|
8240
|
-
rpc("traces.errors", { traceId }).then(setTraceErrors).catch(() => {});
|
|
8241
|
-
}, [traceId]);
|
|
8242
|
-
y2(() => {
|
|
8243
|
-
return onTraceEvents((traceEvents) => {
|
|
8244
|
-
for (const ev of traceEvents) {
|
|
8245
|
-
if (ev.type === "span.start" && ev.span.traceId === traceId) {
|
|
8246
|
-
setSpans((prev) => {
|
|
8247
|
-
if (prev.some((s3) => s3.spanId === ev.span.spanId))
|
|
8248
|
-
return prev;
|
|
8249
|
-
return [...prev, ev.span];
|
|
8250
|
-
});
|
|
8251
|
-
} else if (ev.type === "span.end" && ev.span.traceId === traceId) {
|
|
8252
|
-
setSpans((prev) => prev.map((s3) => s3.spanId === ev.span.spanId ? ev.span : s3));
|
|
8253
|
-
} else if (ev.type === "span.event" && ev.event.traceId === traceId) {
|
|
8254
|
-
setEvents((prev) => [...prev, ev.event]);
|
|
8255
|
-
}
|
|
8256
|
-
}
|
|
8257
|
-
});
|
|
8258
|
-
}, [traceId]);
|
|
8437
|
+
const { spans, events, traceErrors, isLoading } = useTraceData(traceId);
|
|
8259
8438
|
return /* @__PURE__ */ u3(k, {
|
|
8260
8439
|
children: [
|
|
8261
8440
|
/* @__PURE__ */ u3("div", {
|
|
@@ -8274,8 +8453,7 @@ function TraceDrawer({ traceId, onClose, onAddAttributeFilter }) {
|
|
|
8274
8453
|
class: "text-xs text-text-muted font-mono",
|
|
8275
8454
|
children: [
|
|
8276
8455
|
"Trace ",
|
|
8277
|
-
traceId
|
|
8278
|
-
"..."
|
|
8456
|
+
traceId
|
|
8279
8457
|
]
|
|
8280
8458
|
}, undefined, true, undefined, this),
|
|
8281
8459
|
/* @__PURE__ */ u3("div", {
|
|
@@ -8284,11 +8462,34 @@ function TraceDrawer({ traceId, onClose, onAddAttributeFilter }) {
|
|
|
8284
8462
|
}, undefined, false, undefined, this)
|
|
8285
8463
|
]
|
|
8286
8464
|
}, undefined, true, undefined, this),
|
|
8287
|
-
/* @__PURE__ */ u3("
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8465
|
+
/* @__PURE__ */ u3("div", {
|
|
8466
|
+
class: "flex items-center gap-1",
|
|
8467
|
+
children: [
|
|
8468
|
+
/* @__PURE__ */ u3("a", {
|
|
8469
|
+
href: `#/traces/${traceId}`,
|
|
8470
|
+
class: "w-7 h-7 flex items-center justify-center rounded-md hover:bg-panel-hover transition-colors text-text-muted hover:text-ink",
|
|
8471
|
+
title: "Open full page",
|
|
8472
|
+
children: /* @__PURE__ */ u3("svg", {
|
|
8473
|
+
class: "w-4 h-4",
|
|
8474
|
+
viewBox: "0 0 20 20",
|
|
8475
|
+
fill: "currentColor",
|
|
8476
|
+
children: [
|
|
8477
|
+
/* @__PURE__ */ u3("path", {
|
|
8478
|
+
d: "M4.75 5.75a.75.75 0 00.75.75h4.69l-4.22 4.22a.75.75 0 001.06 1.06L11.25 7.56v4.69a.75.75 0 001.5 0v-6.5a.75.75 0 00-.75-.75h-6.5a.75.75 0 00-.75.75z"
|
|
8479
|
+
}, undefined, false, undefined, this),
|
|
8480
|
+
/* @__PURE__ */ u3("path", {
|
|
8481
|
+
d: "M3 13.5a1.5 1.5 0 011.5-1.5h1.25a.75.75 0 010 1.5H4.5v4h4v-1.25a.75.75 0 011.5 0v1.25a1.5 1.5 0 01-1.5 1.5h-4A1.5 1.5 0 013 17.5v-4z"
|
|
8482
|
+
}, undefined, false, undefined, this)
|
|
8483
|
+
]
|
|
8484
|
+
}, undefined, true, undefined, this)
|
|
8485
|
+
}, undefined, false, undefined, this),
|
|
8486
|
+
/* @__PURE__ */ u3("button", {
|
|
8487
|
+
onClick: onClose,
|
|
8488
|
+
class: "w-7 h-7 flex items-center justify-center rounded-md hover:bg-panel-hover transition-colors text-text-muted hover:text-ink",
|
|
8489
|
+
children: "×"
|
|
8490
|
+
}, undefined, false, undefined, this)
|
|
8491
|
+
]
|
|
8492
|
+
}, undefined, true, undefined, this)
|
|
8292
8493
|
]
|
|
8293
8494
|
}, undefined, true, undefined, this),
|
|
8294
8495
|
/* @__PURE__ */ u3("div", {
|
|
@@ -8347,7 +8548,7 @@ function TraceDrawer({ traceId, onClose, onAddAttributeFilter }) {
|
|
|
8347
8548
|
/* @__PURE__ */ u3(TraceWaterfall, {
|
|
8348
8549
|
spans,
|
|
8349
8550
|
events,
|
|
8350
|
-
onAddAttributeFilter
|
|
8551
|
+
onAddAttributeFilter: onAddAttributeFilter ?? (() => {})
|
|
8351
8552
|
}, undefined, false, undefined, this)
|
|
8352
8553
|
]
|
|
8353
8554
|
}, undefined, true, undefined, this)
|
|
@@ -9333,7 +9534,9 @@ function App() {
|
|
|
9333
9534
|
route
|
|
9334
9535
|
}, undefined, false, undefined, this);
|
|
9335
9536
|
if (route.startsWith("/traces"))
|
|
9336
|
-
return /* @__PURE__ */ u3(TracesView, {
|
|
9537
|
+
return /* @__PURE__ */ u3(TracesView, {
|
|
9538
|
+
route
|
|
9539
|
+
}, undefined, false, undefined, this);
|
|
9337
9540
|
if (route.startsWith("/workers"))
|
|
9338
9541
|
return /* @__PURE__ */ u3(WorkersView, {}, undefined, false, undefined, this);
|
|
9339
9542
|
if (route.startsWith("/kv"))
|
|
@@ -683,6 +683,10 @@
|
|
|
683
683
|
height: calc(var(--spacing) * 2.5);
|
|
684
684
|
}
|
|
685
685
|
|
|
686
|
+
.h-4 {
|
|
687
|
+
height: calc(var(--spacing) * 4);
|
|
688
|
+
}
|
|
689
|
+
|
|
686
690
|
.h-5 {
|
|
687
691
|
height: calc(var(--spacing) * 5);
|
|
688
692
|
}
|
|
@@ -824,6 +828,10 @@
|
|
|
824
828
|
width: 100%;
|
|
825
829
|
}
|
|
826
830
|
|
|
831
|
+
.w-px {
|
|
832
|
+
width: 1px;
|
|
833
|
+
}
|
|
834
|
+
|
|
827
835
|
.max-w-4xl {
|
|
828
836
|
max-width: var(--container-4xl);
|
|
829
837
|
}
|
|
@@ -880,6 +888,10 @@
|
|
|
880
888
|
min-width: calc(var(--spacing) * 0);
|
|
881
889
|
}
|
|
882
890
|
|
|
891
|
+
.min-w-\[16px\] {
|
|
892
|
+
min-width: 16px;
|
|
893
|
+
}
|
|
894
|
+
|
|
883
895
|
.min-w-\[20px\] {
|
|
884
896
|
min-width: 20px;
|
|
885
897
|
}
|
|
@@ -1370,6 +1382,10 @@
|
|
|
1370
1382
|
background-color: var(--color-blue-600);
|
|
1371
1383
|
}
|
|
1372
1384
|
|
|
1385
|
+
.bg-border {
|
|
1386
|
+
background-color: var(--color-border);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1373
1389
|
.bg-cyan-500\/15 {
|
|
1374
1390
|
background-color: #00b7d726;
|
|
1375
1391
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
|
|
10
10
|
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/__dashboard/assets/chunk-
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/__dashboard/assets/chunk-pqnphvm2.css"><script type="module" crossorigin src="/__dashboard/assets/chunk-5nxa3jfc.js"></script></head>
|
|
12
12
|
<body class="h-full bg-surface text-ink" style="font-family: system-ui, -apple-system, sans-serif;">
|
|
13
13
|
<script>
|
|
14
14
|
// Apply saved theme before first paint to prevent flash
|
package/package.json
CHANGED
|
@@ -28,6 +28,7 @@ export class BridgeWebSocket extends EventTarget {
|
|
|
28
28
|
readonly wsId: string
|
|
29
29
|
readyState = 1 // OPEN
|
|
30
30
|
private _postMessage: (msg: WsBridgeOutbound) => void
|
|
31
|
+
private _attachment: any = null
|
|
31
32
|
|
|
32
33
|
constructor(wsId: string, postMessage: (msg: WsBridgeOutbound) => void) {
|
|
33
34
|
super()
|
|
@@ -35,6 +36,14 @@ export class BridgeWebSocket extends EventTarget {
|
|
|
35
36
|
this._postMessage = postMessage
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
serializeAttachment(attachment: any): void {
|
|
40
|
+
this._attachment = JSON.parse(JSON.stringify(attachment))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
deserializeAttachment(): any | null {
|
|
44
|
+
return this._attachment
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
send(data: string | ArrayBuffer): void {
|
|
39
48
|
if (this.readyState !== 1) return
|
|
40
49
|
this._postMessage({ type: 'ws-send', wsId: this.wsId, data })
|
|
@@ -602,6 +602,12 @@ export class DurableObjectStateImpl {
|
|
|
602
602
|
if (this._acceptedWebSockets.size >= this._limits.maxConcurrentWebSockets) {
|
|
603
603
|
throw new Error(`Exceeded max concurrent WebSocket connections (${this._limits.maxConcurrentWebSockets})`)
|
|
604
604
|
}
|
|
605
|
+
|
|
606
|
+
// Implicitly accept the WebSocket (in CF production, ctx.acceptWebSocket handles this)
|
|
607
|
+
if ('accept' in ws && typeof ws.accept === 'function') {
|
|
608
|
+
;(ws as any).accept()
|
|
609
|
+
}
|
|
610
|
+
|
|
605
611
|
const entry: AcceptedWebSocket = { ws, tags: tagList, autoResponseTimestamp: null }
|
|
606
612
|
this._acceptedWebSockets.add(entry)
|
|
607
613
|
|
|
@@ -41,6 +41,7 @@ export class CFWebSocket extends EventTarget {
|
|
|
41
41
|
/** @internal */ _peer: CFWebSocket | null = null
|
|
42
42
|
/** @internal */ _accepted = false
|
|
43
43
|
/** @internal */ _eventQueue: WSEvent[] = []
|
|
44
|
+
/** @internal */ _attachment: any = null
|
|
44
45
|
|
|
45
46
|
// Callback-style handlers (standard WebSocket compat)
|
|
46
47
|
onopen: ((ev: Event) => void) | null = null
|
|
@@ -48,6 +49,18 @@ export class CFWebSocket extends EventTarget {
|
|
|
48
49
|
onclose: ((ev: CloseEvent) => void) | null = null
|
|
49
50
|
onerror: ((ev: Event) => void) | null = null
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* CF-specific: attach serializable data to this WebSocket.
|
|
54
|
+
* Survives hibernation in production; here it's just in-memory.
|
|
55
|
+
*/
|
|
56
|
+
serializeAttachment(attachment: any): void {
|
|
57
|
+
this._attachment = JSON.parse(JSON.stringify(attachment))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
deserializeAttachment(): any | null {
|
|
61
|
+
return this._attachment
|
|
62
|
+
}
|
|
63
|
+
|
|
51
64
|
/**
|
|
52
65
|
* CF-specific: begin dispatching events.
|
|
53
66
|
* Must be called before messages can be sent or received.
|
package/src/cli/dev.ts
CHANGED
|
@@ -333,6 +333,9 @@ export async function run(ctx: CliContext) {
|
|
|
333
333
|
const ce = ev as CloseEvent
|
|
334
334
|
ws.close(ce.code, ce.reason)
|
|
335
335
|
})
|
|
336
|
+
// Accept the client side so events from server.send() are dispatched
|
|
337
|
+
// (in CF production the runtime handles this; here we bridge manually)
|
|
338
|
+
cfSocket.accept()
|
|
336
339
|
},
|
|
337
340
|
message(ws, message) {
|
|
338
341
|
const data = ws.data as unknown as Record<string, unknown>
|