causal-inspector 0.1.0 → 0.1.1
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/CausalInspector.css +4 -0
- package/dist/CausalInspector.js +3 -2
- package/dist/components/FilterBar.js +1 -7
- package/dist/engines/query.js +0 -2
- package/dist/panes/AggregateTimelinePane.js +19 -4
- package/dist/panes/WaterfallPane.js +101 -97
- package/dist/queries.d.ts +1 -1
- package/dist/queries.js +0 -4
- package/dist/reducer.js +8 -0
- package/dist/state.js +0 -2
- package/dist/types.d.ts +0 -2
- package/package.json +1 -1
package/dist/CausalInspector.css
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
.causal-inspector {
|
|
4
4
|
height: 100%;
|
|
5
5
|
width: 100%;
|
|
6
|
+
overflow: hidden;
|
|
7
|
+
position: relative;
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
6
10
|
background: #0a0a0f;
|
|
7
11
|
color: #e0e0f0;
|
|
8
12
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
|
package/dist/CausalInspector.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useRef, useCallback, useEffect } from "react";
|
|
3
3
|
import { Layout, Model, Actions, DockLocation, } from "flexlayout-react";
|
|
4
4
|
import { createClient } from "graphql-ws";
|
|
@@ -13,6 +13,7 @@ import { LogsPane } from "./panes/LogsPane";
|
|
|
13
13
|
import { AggregateTimelinePane } from "./panes/AggregateTimelinePane";
|
|
14
14
|
import { WaterfallPane } from "./panes/WaterfallPane";
|
|
15
15
|
import { CorrelationExplorerPane } from "./panes/CorrelationExplorerPane";
|
|
16
|
+
import { GlobalScrubber } from "./components/GlobalScrubber";
|
|
16
17
|
import "./CausalInspector.css";
|
|
17
18
|
// ── Transport ─────────────────────────────────────────────────
|
|
18
19
|
function createTransport(endpoint, fetchOptions) {
|
|
@@ -244,7 +245,7 @@ function InspectorLayout() {
|
|
|
244
245
|
setTimeout(() => document.addEventListener("mousedown", close), 0);
|
|
245
246
|
}, children: _jsx(Plus, { size: 14 }) }, "add-pane"));
|
|
246
247
|
}, [addTab]);
|
|
247
|
-
return (_jsx("div", { style: {
|
|
248
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { style: { flex: 1, minHeight: 0 }, children: _jsx(Layout, { ref: layoutRef, model: modelRef.current, factory: factory, onModelChange: onModelChange, onRenderTabSet: onRenderTabSet }) }), _jsx(GlobalScrubber, {})] }));
|
|
248
249
|
}
|
|
249
250
|
// ── CausalInspector (public API) ──────────────────────────────
|
|
250
251
|
const savedLayout = loadSavedLayout();
|
|
@@ -7,13 +7,7 @@ export function FilterBar() {
|
|
|
7
7
|
return (_jsxs("div", { className: "flex flex-wrap items-center gap-2 px-3 py-2 border-b border-border", style: { background: "rgba(15, 15, 20, 0.6)", backdropFilter: "blur(8px)" }, children: [_jsxs("div", { className: "relative flex items-center", children: [_jsx(Search, { size: 12, className: "absolute left-2.5 text-muted-foreground pointer-events-none" }), _jsx("input", { type: "text", placeholder: "search events...", value: filters.search, onChange: (e) => dispatch({
|
|
8
8
|
type: "ui/filter_changed",
|
|
9
9
|
payload: { search: e.target.value },
|
|
10
|
-
}), className: "pl-7 pr-2 py-1.5 text-xs rounded-md bg-background/50 border border-border text-foreground placeholder:text-muted-foreground w-64 focus:outline-none focus:ring-1 focus:ring-indigo-500/40 focus:border-indigo-500/30 transition-all" })] }), _jsx("span", { className: "w-px h-4 bg-border" }),
|
|
11
|
-
type: "ui/filter_changed",
|
|
12
|
-
payload: { from: e.target.value || null },
|
|
13
|
-
}), className: "px-2 py-1.5 text-xs rounded-md bg-background/50 border border-border text-foreground w-32 focus:outline-none focus:ring-1 focus:ring-indigo-500/40 focus:border-indigo-500/30 transition-all" }), _jsx("label", { className: "text-[10px] text-muted-foreground uppercase tracking-wider", children: "To" }), _jsx("input", { type: "date", value: filters.to ?? "", onChange: (e) => dispatch({
|
|
14
|
-
type: "ui/filter_changed",
|
|
15
|
-
payload: { to: e.target.value || null },
|
|
16
|
-
}), className: "px-2 py-1.5 text-xs rounded-md bg-background/50 border border-border text-foreground w-32 focus:outline-none focus:ring-1 focus:ring-indigo-500/40 focus:border-indigo-500/30 transition-all" }), filters.correlationId && (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-px h-4 bg-border" }), _jsxs("span", { className: "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-400 text-[10px] font-mono", children: [filters.correlationId.slice(0, 8), _jsx("button", { onClick: () => dispatch({
|
|
10
|
+
}), className: "pl-7 pr-2 py-1.5 text-xs rounded-md bg-background/50 border border-border text-foreground placeholder:text-muted-foreground w-64 focus:outline-none focus:ring-1 focus:ring-indigo-500/40 focus:border-indigo-500/30 transition-all" })] }), filters.correlationId && (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-px h-4 bg-border" }), _jsxs("span", { className: "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-400 text-[10px] font-mono", children: [filters.correlationId.slice(0, 8), _jsx("button", { onClick: () => dispatch({
|
|
17
11
|
type: "ui/filter_changed",
|
|
18
12
|
payload: { correlationId: null },
|
|
19
13
|
}), className: "hover:text-foreground transition-colors", children: _jsx(X, { size: 10 }) })] })] })), filters.aggregateKey && (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-px h-4 bg-border" }), _jsxs("span", { className: "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-teal-500/10 border border-teal-500/20 text-teal-400 text-[10px] font-mono", children: [filters.aggregateKey.split(":")[0], ":", filters.aggregateKey.split(":").slice(1).join(":").slice(0, 8), _jsx("button", { onClick: () => dispatch({
|
package/dist/engines/query.js
CHANGED
|
@@ -22,8 +22,6 @@ export const createQueryEngine = (transport) => {
|
|
|
22
22
|
limit: 50,
|
|
23
23
|
cursor,
|
|
24
24
|
search: state.filters.search || undefined,
|
|
25
|
-
from: state.filters.from || undefined,
|
|
26
|
-
to: state.filters.to || undefined,
|
|
27
25
|
correlationId: state.filters.correlationId || undefined,
|
|
28
26
|
aggregateKey: state.filters.aggregateKey || undefined,
|
|
29
27
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useCallback, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { useSelector, useDispatch } from "../machine";
|
|
4
4
|
import { eventBg, eventTextColor } from "../theme";
|
|
5
5
|
import { inScrubberRange } from "../utils";
|
|
6
|
+
import { X } from "lucide-react";
|
|
6
7
|
function tokenizeJson(json) {
|
|
7
8
|
const tokens = [];
|
|
8
9
|
const re = /("(?:[^"\\]|\\.)*")\s*:|("(?:[^"\\]|\\.)*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b)|(\bnull\b)|([{}[\]:,])/g;
|
|
@@ -147,8 +148,20 @@ export function AggregateTimelinePane() {
|
|
|
147
148
|
const entries = useSelector((s) => correlationId ? s.aggregateTimeline[correlationId] ?? [] : []);
|
|
148
149
|
const scrubberStart = useSelector((s) => s.scrubberStart);
|
|
149
150
|
const scrubberEnd = useSelector((s) => s.scrubberEnd);
|
|
151
|
+
const logsFilter = useSelector((s) => s.logsFilter);
|
|
152
|
+
const flowData = useSelector((s) => s.flowData);
|
|
150
153
|
const dispatch = useDispatch();
|
|
151
154
|
const [diffMode, setDiffMode] = useState(false);
|
|
155
|
+
// Map eventId → reactorId for handler selection highlighting
|
|
156
|
+
const eventReactorMap = useMemo(() => {
|
|
157
|
+
const map = new Map();
|
|
158
|
+
for (const e of flowData) {
|
|
159
|
+
if (e.id && e.reactorId)
|
|
160
|
+
map.set(e.id, e.reactorId);
|
|
161
|
+
}
|
|
162
|
+
return map;
|
|
163
|
+
}, [flowData]);
|
|
164
|
+
const hasReactorFilter = logsFilter.reactorId != null;
|
|
152
165
|
// Build a lookup: seq → { aggKey → state } for computing diffs
|
|
153
166
|
const prevStateMap = useMemo(() => {
|
|
154
167
|
const map = new Map();
|
|
@@ -200,16 +213,18 @@ export function AggregateTimelinePane() {
|
|
|
200
213
|
cursor: "pointer",
|
|
201
214
|
transition: "all 150ms",
|
|
202
215
|
letterSpacing: "0.02em",
|
|
203
|
-
}, children: "Diff" })] }), _jsx("div", { style: { flex: 1, overflow: "auto", padding: "8px 12px" }, children: entries.map((entry, entryIdx) => {
|
|
216
|
+
}, children: "Diff" }), hasReactorFilter && (_jsxs(_Fragment, { children: [_jsx("div", { style: { width: 1, height: 14, background: "rgba(255,255,255,0.06)", marginLeft: 4, marginRight: 4 } }), _jsx("span", { style: { fontSize: 10, color: "#818cf8", fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" }, children: logsFilter.reactorId }), _jsx("button", { onClick: () => dispatch({ type: "ui/flow_node_selected", payload: null }), style: { background: "none", border: "none", cursor: "pointer", color: "#70708a", padding: 2, borderRadius: 4, display: "flex", alignItems: "center" }, title: "Clear selection", children: _jsx(X, { size: 12 }) })] }))] }), _jsx("div", { style: { flex: 1, overflow: "auto", padding: "8px 12px" }, children: entries.map((entry, entryIdx) => {
|
|
204
217
|
const isOutside = (scrubberStart != null || scrubberEnd != null) && !inScrubberRange(entry.seq, scrubberStart, scrubberEnd);
|
|
205
218
|
const isCurrent = scrubberEnd === entry.seq;
|
|
206
219
|
const prevAggs = prevStateMap.get(entry.seq);
|
|
220
|
+
const entryReactorId = entry.eventId ? eventReactorMap.get(entry.eventId) : null;
|
|
221
|
+
const isReactorMatch = !hasReactorFilter || entryReactorId === logsFilter.reactorId;
|
|
207
222
|
return (_jsxs("div", { ref: isCurrent ? currentRowRef : undefined, onClick: () => handleRowClick(entry.seq), style: {
|
|
208
|
-
opacity: isOutside ? 0.3 : 1,
|
|
223
|
+
opacity: isOutside ? 0.3 : !isReactorMatch ? 0.35 : 1,
|
|
209
224
|
padding: "6px 8px",
|
|
210
225
|
marginBottom: 4,
|
|
211
226
|
borderRadius: 6,
|
|
212
|
-
background: isCurrent ? "rgba(99,102,241,0.15)" : "transparent",
|
|
227
|
+
background: isCurrent ? "rgba(99,102,241,0.15)" : isReactorMatch && hasReactorFilter ? "rgba(99,102,241,0.06)" : "transparent",
|
|
213
228
|
cursor: "pointer",
|
|
214
229
|
transition: "opacity 150ms, background 150ms",
|
|
215
230
|
}, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }, children: [_jsxs("div", { style: { fontSize: 10, fontWeight: 600, color: "#a1a1aa", minWidth: 40 }, children: ["#", entry.seq] }), _jsx("div", { style: {
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useMemo, useCallback } from "react";
|
|
3
3
|
import { useSelector, useDispatch } from "../machine";
|
|
4
4
|
import { inScrubberRange } from "../utils";
|
|
5
|
+
import { X } from "lucide-react";
|
|
5
6
|
// ---------------------------------------------------------------------------
|
|
6
7
|
// Timing helpers
|
|
7
8
|
// ---------------------------------------------------------------------------
|
|
@@ -99,104 +100,107 @@ export function WaterfallPane() {
|
|
|
99
100
|
if (bars.length === 0) {
|
|
100
101
|
return (_jsx("div", { style: { height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: "#50506a", fontSize: 12, letterSpacing: "0.03em" }, children: "No reactor execution data for this correlation" }));
|
|
101
102
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
gap: 0,
|
|
133
|
-
opacity: isFuture ? 0.25 : 1,
|
|
134
|
-
transition: "opacity 200ms, background 150ms",
|
|
135
|
-
cursor: "pointer",
|
|
136
|
-
borderRadius: 6,
|
|
137
|
-
background: isSelected ? "rgba(99, 102, 241, 0.15)" : "transparent",
|
|
138
|
-
paddingLeft: 4,
|
|
139
|
-
paddingRight: 4,
|
|
140
|
-
}, children: [_jsx("div", { style: {
|
|
141
|
-
width: LABEL_WIDTH,
|
|
142
|
-
flexShrink: 0,
|
|
143
|
-
fontSize: 11,
|
|
144
|
-
color: "#c0c0d0",
|
|
145
|
-
fontWeight: 500,
|
|
146
|
-
overflow: "hidden",
|
|
147
|
-
textOverflow: "ellipsis",
|
|
148
|
-
whiteSpace: "nowrap",
|
|
149
|
-
paddingRight: 10,
|
|
150
|
-
letterSpacing: "0.01em",
|
|
151
|
-
}, title: bar.reactorId, children: bar.reactorId }), _jsxs("div", { style: {
|
|
152
|
-
flex: 1,
|
|
153
|
-
position: "relative",
|
|
154
|
-
height: 22,
|
|
155
|
-
background: "rgba(255, 255, 255, 0.02)",
|
|
156
|
-
borderRadius: 5,
|
|
157
|
-
overflow: "hidden",
|
|
158
|
-
}, children: [_jsx("div", { style: {
|
|
159
|
-
position: "absolute",
|
|
160
|
-
left: `${offsetPct}%`,
|
|
161
|
-
width: `${widthPct}%`,
|
|
162
|
-
minWidth: BAR_MIN_WIDTH,
|
|
163
|
-
height: "100%",
|
|
164
|
-
background: `linear-gradient(90deg, ${colors.bar}, ${colors.barEnd})`,
|
|
165
|
-
borderRadius: 4,
|
|
166
|
-
opacity: 0.8,
|
|
167
|
-
display: "flex",
|
|
168
|
-
alignItems: "center",
|
|
169
|
-
paddingLeft: 5,
|
|
170
|
-
paddingRight: 5,
|
|
171
|
-
boxShadow: `0 1px 4px ${colors.bar}30`,
|
|
172
|
-
}, title: `${bar.reactorId}: ${bar.status} (${formatDuration(duration)})${bar.attempts > 1 ? ` — ${bar.attempts} attempts` : ""}${bar.error ? `\nError: ${bar.error}` : ""}`, children: _jsx("span", { style: {
|
|
173
|
-
fontSize: 9,
|
|
174
|
-
fontWeight: 600,
|
|
175
|
-
color: "#0a0a0f",
|
|
176
|
-
whiteSpace: "nowrap",
|
|
177
|
-
overflow: "hidden",
|
|
178
|
-
textOverflow: "ellipsis",
|
|
179
|
-
}, children: formatDuration(duration) }) }), cursorPct != null && (_jsx("div", { style: {
|
|
180
|
-
position: "absolute",
|
|
181
|
-
left: `${cursorPct}%`,
|
|
182
|
-
top: 0,
|
|
183
|
-
bottom: 0,
|
|
184
|
-
width: 1,
|
|
185
|
-
background: "#6366f1",
|
|
186
|
-
pointerEvents: "none",
|
|
187
|
-
boxShadow: "0 0 4px rgba(99, 102, 241, 0.3)",
|
|
188
|
-
} }))] }), _jsxs("div", { style: {
|
|
189
|
-
width: 80,
|
|
190
|
-
flexShrink: 0,
|
|
103
|
+
const hasReactorFilter = logsFilter.reactorId != null;
|
|
104
|
+
return (_jsxs("div", { style: { height: "100%", display: "flex", flexDirection: "column" }, children: [hasReactorFilter && (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, padding: "5px 12px", borderBottom: "1px solid rgba(255,255,255,0.06)", flexShrink: 0, background: "rgba(15, 15, 20, 0.6)", backdropFilter: "blur(8px)" }, children: [_jsx("span", { style: { fontSize: 10, color: "#818cf8", fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" }, children: logsFilter.reactorId }), _jsx("button", { onClick: () => {
|
|
105
|
+
dispatch({ type: "ui/flow_node_selected", payload: null });
|
|
106
|
+
}, style: { marginLeft: "auto", background: "none", border: "none", cursor: "pointer", color: "#70708a", padding: 2, borderRadius: 4, display: "flex", alignItems: "center" }, title: "Clear selection", children: _jsx(X, { size: 12 }) })] })), _jsxs("div", { style: { flex: 1, overflow: "auto", padding: `10px ${PADDING_X}px` }, children: [_jsxs("div", { style: { display: "flex", marginBottom: 6, marginLeft: LABEL_WIDTH, position: "relative", height: 16 }, children: [_jsx("span", { style: { fontSize: 9, color: "#40405a", letterSpacing: "0.04em" }, children: "0ms" }), _jsx("span", { style: { fontSize: 9, color: "#40405a", position: "absolute", right: 0, letterSpacing: "0.04em" }, children: formatDuration(rangeMs) }), scrubberMs != null && scrubberMs >= minMs && scrubberMs <= maxMs && (_jsx("div", { style: {
|
|
107
|
+
position: "absolute",
|
|
108
|
+
left: `${((scrubberMs - minMs) / rangeMs) * 100}%`,
|
|
109
|
+
top: 0,
|
|
110
|
+
bottom: -4,
|
|
111
|
+
width: 1,
|
|
112
|
+
background: "#6366f1",
|
|
113
|
+
pointerEvents: "none",
|
|
114
|
+
boxShadow: "0 0 4px rgba(99, 102, 241, 0.4)",
|
|
115
|
+
} }))] }), bars.map((bar) => {
|
|
116
|
+
const offsetPct = ((bar.startMs - minMs) / rangeMs) * 100;
|
|
117
|
+
const widthPct = Math.max(((bar.endMs - bar.startMs) / rangeMs) * 100, 0.5);
|
|
118
|
+
const colors = statusColor(bar.status);
|
|
119
|
+
const duration = bar.endMs - bar.startMs;
|
|
120
|
+
// Scrubber sync: dim bars whose triggering events are all outside range
|
|
121
|
+
const isFuture = (scrubberStart != null || scrubberEnd != null) &&
|
|
122
|
+
bar.triggeringEventIds.length > 0 &&
|
|
123
|
+
bar.triggeringEventIds.every((eid) => {
|
|
124
|
+
const seq = eventIdToSeq.get(eid);
|
|
125
|
+
return seq != null && !inScrubberRange(seq, scrubberStart, scrubberEnd);
|
|
126
|
+
});
|
|
127
|
+
// Scrubber cursor position within this bar's track
|
|
128
|
+
const cursorPct = scrubberMs != null && scrubberMs >= minMs && scrubberMs <= maxMs
|
|
129
|
+
? ((scrubberMs - minMs) / rangeMs) * 100
|
|
130
|
+
: null;
|
|
131
|
+
const isSelected = logsFilter.reactorId === bar.reactorId;
|
|
132
|
+
return (_jsxs("div", { onClick: () => handleBarClick(bar), style: {
|
|
191
133
|
display: "flex",
|
|
192
134
|
alignItems: "center",
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
135
|
+
height: ROW_HEIGHT,
|
|
136
|
+
gap: 0,
|
|
137
|
+
opacity: isFuture ? 0.25 : (hasReactorFilter && !isSelected) ? 0.35 : 1,
|
|
138
|
+
transition: "opacity 200ms, background 150ms",
|
|
139
|
+
cursor: "pointer",
|
|
140
|
+
borderRadius: 6,
|
|
141
|
+
background: isSelected ? "rgba(99, 102, 241, 0.15)" : "transparent",
|
|
142
|
+
paddingLeft: 4,
|
|
143
|
+
paddingRight: 4,
|
|
144
|
+
}, children: [_jsx("div", { style: {
|
|
145
|
+
width: LABEL_WIDTH,
|
|
146
|
+
flexShrink: 0,
|
|
147
|
+
fontSize: 11,
|
|
148
|
+
color: "#c0c0d0",
|
|
197
149
|
fontWeight: 500,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
150
|
+
overflow: "hidden",
|
|
151
|
+
textOverflow: "ellipsis",
|
|
152
|
+
whiteSpace: "nowrap",
|
|
153
|
+
paddingRight: 10,
|
|
154
|
+
letterSpacing: "0.01em",
|
|
155
|
+
}, title: bar.reactorId, children: bar.reactorId }), _jsxs("div", { style: {
|
|
156
|
+
flex: 1,
|
|
157
|
+
position: "relative",
|
|
158
|
+
height: 22,
|
|
159
|
+
background: "rgba(255, 255, 255, 0.02)",
|
|
160
|
+
borderRadius: 5,
|
|
161
|
+
overflow: "hidden",
|
|
162
|
+
}, children: [_jsx("div", { style: {
|
|
163
|
+
position: "absolute",
|
|
164
|
+
left: `${offsetPct}%`,
|
|
165
|
+
width: `${widthPct}%`,
|
|
166
|
+
minWidth: BAR_MIN_WIDTH,
|
|
167
|
+
height: "100%",
|
|
168
|
+
background: `linear-gradient(90deg, ${colors.bar}, ${colors.barEnd})`,
|
|
169
|
+
borderRadius: 4,
|
|
170
|
+
opacity: 0.8,
|
|
171
|
+
display: "flex",
|
|
172
|
+
alignItems: "center",
|
|
173
|
+
paddingLeft: 5,
|
|
174
|
+
paddingRight: 5,
|
|
175
|
+
boxShadow: `0 1px 4px ${colors.bar}30`,
|
|
176
|
+
}, title: `${bar.reactorId}: ${bar.status} (${formatDuration(duration)})${bar.attempts > 1 ? ` — ${bar.attempts} attempts` : ""}${bar.error ? `\nError: ${bar.error}` : ""}`, children: _jsx("span", { style: {
|
|
177
|
+
fontSize: 9,
|
|
178
|
+
fontWeight: 600,
|
|
179
|
+
color: "#0a0a0f",
|
|
180
|
+
whiteSpace: "nowrap",
|
|
181
|
+
overflow: "hidden",
|
|
182
|
+
textOverflow: "ellipsis",
|
|
183
|
+
}, children: formatDuration(duration) }) }), cursorPct != null && (_jsx("div", { style: {
|
|
184
|
+
position: "absolute",
|
|
185
|
+
left: `${cursorPct}%`,
|
|
186
|
+
top: 0,
|
|
187
|
+
bottom: 0,
|
|
188
|
+
width: 1,
|
|
189
|
+
background: "#6366f1",
|
|
190
|
+
pointerEvents: "none",
|
|
191
|
+
boxShadow: "0 0 4px rgba(99, 102, 241, 0.3)",
|
|
192
|
+
} }))] }), _jsxs("div", { style: {
|
|
193
|
+
width: 80,
|
|
194
|
+
flexShrink: 0,
|
|
195
|
+
display: "flex",
|
|
196
|
+
alignItems: "center",
|
|
197
|
+
gap: 4,
|
|
198
|
+
paddingLeft: 10,
|
|
199
|
+
}, children: [_jsx("span", { style: {
|
|
200
|
+
fontSize: 10,
|
|
201
|
+
fontWeight: 500,
|
|
202
|
+
color: colors.text,
|
|
203
|
+
opacity: 0.8,
|
|
204
|
+
}, children: bar.status }), bar.attempts > 1 && (_jsxs("span", { style: { fontSize: 9, color: "#50506a" }, children: ["x", bar.attempts] }))] })] }, bar.reactorId));
|
|
205
|
+
}), _jsxs("div", { style: { marginTop: 10, fontSize: 10, color: "#40405a", marginLeft: LABEL_WIDTH, letterSpacing: "0.03em" }, children: ["Total wall time: ", formatDuration(rangeMs)] })] })] }));
|
|
202
206
|
}
|
package/dist/queries.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** GraphQL query and subscription documents for the causal inspector API. */
|
|
2
2
|
export declare const EVENTS_SUBSCRIPTION = "\n subscription Events($lastSeq: Int) {\n inspectorEventAdded(lastSeq: $lastSeq) {\n \n seq\n ts\n type\n name\n id\n parentId\n correlationId\n reactorId\n aggregateType\n aggregateId\n streamVersion\n summary\n payload\n\n }\n }\n";
|
|
3
|
-
export declare const INSPECTOR_EVENTS = "\n query InspectorEvents(\n $limit: Int!\n $cursor: Int\n $search: String\n $
|
|
3
|
+
export declare const INSPECTOR_EVENTS = "\n query InspectorEvents(\n $limit: Int!\n $cursor: Int\n $search: String\n $correlationId: String\n $aggregateKey: String\n ) {\n inspectorEvents(\n limit: $limit\n cursor: $cursor\n search: $search\n correlationId: $correlationId\n aggregateKey: $aggregateKey\n ) {\n events {\n \n seq\n ts\n type\n name\n id\n parentId\n correlationId\n reactorId\n aggregateType\n aggregateId\n streamVersion\n summary\n payload\n\n }\n nextCursor\n }\n }\n";
|
|
4
4
|
export declare const INSPECTOR_CAUSAL_TREE = "\n query InspectorCausalTree($seq: Int!) {\n inspectorCausalTree(seq: $seq) {\n events {\n \n seq\n ts\n type\n name\n id\n parentId\n correlationId\n reactorId\n aggregateType\n aggregateId\n streamVersion\n summary\n payload\n\n }\n rootSeq\n }\n }\n";
|
|
5
5
|
export declare const INSPECTOR_CAUSAL_FLOW = "\n query InspectorCausalFlow($correlationId: String!) {\n inspectorCausalFlow(correlationId: $correlationId) {\n events {\n \n seq\n ts\n type\n name\n id\n parentId\n correlationId\n reactorId\n aggregateType\n aggregateId\n streamVersion\n summary\n payload\n\n }\n }\n }\n";
|
|
6
6
|
export declare const INSPECTOR_REACTOR_LOGS = "\n query InspectorReactorLogs($eventId: String!, $reactorId: String!) {\n inspectorReactorLogs(eventId: $eventId, reactorId: $reactorId) {\n eventId\n reactorId\n level\n message\n data\n loggedAt\n }\n }\n";
|
package/dist/queries.js
CHANGED
|
@@ -26,8 +26,6 @@ export const INSPECTOR_EVENTS = `
|
|
|
26
26
|
$limit: Int!
|
|
27
27
|
$cursor: Int
|
|
28
28
|
$search: String
|
|
29
|
-
$from: DateTime
|
|
30
|
-
$to: DateTime
|
|
31
29
|
$correlationId: String
|
|
32
30
|
$aggregateKey: String
|
|
33
31
|
) {
|
|
@@ -35,8 +33,6 @@ export const INSPECTOR_EVENTS = `
|
|
|
35
33
|
limit: $limit
|
|
36
34
|
cursor: $cursor
|
|
37
35
|
search: $search
|
|
38
|
-
from: $from
|
|
39
|
-
to: $to
|
|
40
36
|
correlationId: $correlationId
|
|
41
37
|
aggregateKey: $aggregateKey
|
|
42
38
|
) {
|
package/dist/reducer.js
CHANGED
|
@@ -148,6 +148,14 @@ export const reducer = (draft, event) => {
|
|
|
148
148
|
break;
|
|
149
149
|
case "ui/flow_node_selected":
|
|
150
150
|
draft.flowSelection = event.payload;
|
|
151
|
+
// Clear reactor filter when deselecting a node
|
|
152
|
+
if (event.payload == null && draft.logsFilter.reactorId != null) {
|
|
153
|
+
draft.logsFilter = {
|
|
154
|
+
scope: "correlation",
|
|
155
|
+
reactorId: null,
|
|
156
|
+
correlationId: draft.flowCorrelationId,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
151
159
|
break;
|
|
152
160
|
case "ui/filter_changed":
|
|
153
161
|
Object.assign(draft.filters, event.payload);
|
package/dist/state.js
CHANGED
package/dist/types.d.ts
CHANGED