causal-inspector 0.1.5 → 0.2.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/CausalInspector.d.ts +8 -1
- package/dist/CausalInspector.js +32 -9
- package/dist/components/EffectList.d.ts +4 -0
- package/dist/components/EffectList.js +15 -0
- package/dist/components/FilterBar.js +2 -2
- package/dist/components/GlobalScrubber.js +6 -6
- package/dist/engines/query.js +134 -53
- package/dist/engines/scrubber.js +1 -1
- package/dist/engines/url.d.ts +5 -2
- package/dist/engines/url.js +50 -22
- package/dist/events.d.ts +41 -12
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/panes/AggregateTimelinePane.js +4 -4
- package/dist/panes/CausalFlowPane.js +16 -16
- package/dist/panes/CausalTreePane.js +51 -17
- package/dist/panes/CorrelationExplorerPane.d.ts +2 -2
- package/dist/panes/CorrelationExplorerPane.js +10 -10
- package/dist/panes/LogsPane.js +6 -6
- package/dist/panes/SubjectChainPane.d.ts +1 -0
- package/dist/panes/SubjectChainPane.js +50 -0
- package/dist/panes/TimelinePane.js +32 -16
- package/dist/panes/WaterfallPane.js +185 -72
- package/dist/panes/WorkflowExplorerPane.d.ts +2 -0
- package/dist/panes/WorkflowExplorerPane.js +46 -0
- package/dist/queries.d.ts +16 -11
- package/dist/queries.js +114 -24
- package/dist/reducer.js +102 -36
- package/dist/state.d.ts +16 -5
- package/dist/state.js +17 -6
- package/dist/theme.js +1 -0
- package/dist/types.d.ts +59 -11
- package/dist/utils.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { useSelector, useDispatch } from "../machine";
|
|
4
|
+
import { CopyablePayload } from "../components/CopyablePayload";
|
|
5
|
+
import { EffectList } from "../components/EffectList";
|
|
6
|
+
import { eventTextColor, eventBg } from "../theme";
|
|
7
|
+
import { formatTs, compactPayload } from "../utils";
|
|
8
|
+
import { AlertTriangle, ChevronRight, Zap } from "lucide-react";
|
|
9
|
+
// ── SubjectChainEventRow ──────────────────────────────────────────────────
|
|
10
|
+
function SubjectChainEventRow({ event, showSourceBadge, effects, loadingEffects, dispatch, }) {
|
|
11
|
+
const [payloadOpen, setPayloadOpen] = useState(false);
|
|
12
|
+
const [effectsOpen, setEffectsOpen] = useState(false);
|
|
13
|
+
const handleEffectsToggle = (e) => {
|
|
14
|
+
e.stopPropagation();
|
|
15
|
+
if (!effectsOpen && effects === undefined && event.id) {
|
|
16
|
+
dispatch({ type: "ui/event_effects_requested", payload: { eventId: event.id } });
|
|
17
|
+
}
|
|
18
|
+
setEffectsOpen((v) => !v);
|
|
19
|
+
};
|
|
20
|
+
return (_jsxs("div", { className: "group px-3 py-2 border-b border-border hover:bg-white/[0.02] transition-all duration-150", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("span", { className: "text-[10px] font-mono text-muted-foreground/60 w-10 shrink-0 text-right tabular-nums", children: event.seq }), _jsx("span", { className: "text-[10px] text-muted-foreground/70 shrink-0 w-28 tabular-nums", children: formatTs(event.ts) }), showSourceBadge && (_jsx("span", { className: `px-1.5 py-0.5 rounded text-[8px] font-medium shrink-0 border ${event.sourceMode === "stream"
|
|
21
|
+
? "bg-indigo-500/10 text-indigo-400/80 border-indigo-500/20"
|
|
22
|
+
: "bg-zinc-500/10 text-zinc-400/60 border-zinc-500/15"}`, children: event.sourceMode })), _jsx("span", { className: "text-xs font-mono shrink-0 px-1.5 py-0.5 rounded", style: { color: eventTextColor(event.name), background: eventBg(event.name) }, children: event.name }), _jsxs("button", { onClick: (e) => { e.stopPropagation(); setPayloadOpen((v) => !v); }, className: "flex items-center gap-1 text-[10px] font-mono text-muted-foreground/60 hover:text-muted-foreground truncate text-left min-w-0 transition-colors", children: [_jsx(ChevronRight, { size: 10, className: `shrink-0 transition-transform duration-150 ${payloadOpen ? "rotate-90" : ""}` }), _jsx("span", { className: "truncate", children: event.summary ?? compactPayload(event.payload) })] }), event.id && (_jsxs("button", { onClick: handleEffectsToggle, className: `ml-auto opacity-0 group-hover:opacity-100 transition-all duration-150 flex items-center gap-1 px-1.5 py-0.5 rounded text-[9px] shrink-0 ${effectsOpen
|
|
23
|
+
? "opacity-100 bg-indigo-500/10 text-indigo-400/70 border border-indigo-500/20"
|
|
24
|
+
: "hover:bg-white/[0.05] text-muted-foreground/50 border border-transparent"}`, title: "Show effects", children: [_jsx(Zap, { size: 9 }), effects !== undefined && effects.length > 0 && (_jsx("span", { children: effects.length }))] }))] }), payloadOpen && (_jsx(CopyablePayload, { payload: event.payload, className: "mt-2 ml-12 max-h-48" })), effectsOpen && (_jsx("div", { className: "mt-1 ml-12", children: loadingEffects ? (_jsx("div", { className: "text-[9px] text-muted-foreground/40 italic py-1", children: "Loading\u2026" })) : (_jsx(EffectList, { effects: effects ?? [] })) }))] }));
|
|
25
|
+
}
|
|
26
|
+
// ── SubjectChainPane ──────────────────────────────────────────────────────
|
|
27
|
+
export function SubjectChainPane() {
|
|
28
|
+
const dispatch = useDispatch();
|
|
29
|
+
const subjectType = useSelector((s) => s.subjectType);
|
|
30
|
+
const subjectId = useSelector((s) => s.subjectId);
|
|
31
|
+
const subjectMode = useSelector((s) => s.subjectMode);
|
|
32
|
+
const subjectChain = useSelector((s) => s.subjectChain);
|
|
33
|
+
const loading = useSelector((s) => s.subjectChainLoading);
|
|
34
|
+
const hasMore = useSelector((s) => s.subjectChainHasMore);
|
|
35
|
+
const depthCapped = useSelector((s) => s.subjectDepthCapped);
|
|
36
|
+
const expandedEffects = useSelector((s) => s.expandedEffects);
|
|
37
|
+
const loadingEffectsIds = useSelector((s) => s.loadingEffects);
|
|
38
|
+
if (!subjectType || !subjectId) {
|
|
39
|
+
return (_jsx("div", { className: "flex items-center justify-center h-full text-xs text-muted-foreground/50 tracking-wide", children: "Select an entity to view its subject chain" }));
|
|
40
|
+
}
|
|
41
|
+
const modes = [
|
|
42
|
+
{ label: "Stream", value: "stream" },
|
|
43
|
+
{ label: "Descendants", value: "descendants" },
|
|
44
|
+
{ label: "Both", value: "both" },
|
|
45
|
+
];
|
|
46
|
+
const shortId = subjectId.length > 8 ? subjectId.slice(0, 8) + "…" : subjectId;
|
|
47
|
+
return (_jsxs("div", { className: "h-full flex flex-col", children: [_jsxs("div", { className: "px-3 py-2 border-b border-border shrink-0 space-y-1.5", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("span", { className: "text-[10px] font-mono text-muted-foreground/60 shrink-0", children: subjectType }), _jsx("span", { className: "text-[10px] font-mono text-foreground/80 truncate", title: subjectId, children: shortId })] }), _jsx("div", { className: "flex items-center gap-1", children: modes.map(({ label, value }) => (_jsx("button", { onClick: () => dispatch({ type: "ui/subject_mode_changed", payload: { mode: value } }), className: `px-2 py-0.5 rounded text-[10px] transition-all ${subjectMode === value
|
|
48
|
+
? "bg-indigo-500/20 text-indigo-300 border border-indigo-500/30"
|
|
49
|
+
: "text-muted-foreground/60 hover:text-foreground border border-transparent hover:border-border"}`, children: label }, value))) })] }), depthCapped && (_jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-yellow-500/8 border-b border-yellow-500/15 text-[10px] text-yellow-400/80 shrink-0", children: [_jsx(AlertTriangle, { size: 10, className: "shrink-0" }), "Descendants truncated at depth 10. Some events may not be shown."] })), _jsx("div", { className: "flex-1 overflow-y-auto", children: loading && subjectChain.length === 0 ? (_jsx("div", { className: "p-3 space-y-2 animate-pulse", children: [...Array(5)].map((_, i) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-3 w-10 bg-muted rounded" }), _jsx("div", { className: "h-3 w-24 bg-muted rounded" }), _jsx("div", { className: "h-3 w-20 bg-muted rounded" }), _jsx("div", { className: "h-3 w-36 bg-muted rounded" })] }, i))) })) : subjectChain.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32 text-xs text-muted-foreground/50", children: "No events found" })) : (_jsxs(_Fragment, { children: [subjectChain.map((event) => (_jsx(SubjectChainEventRow, { event: event, showSourceBadge: subjectMode === "both", effects: event.id ? expandedEffects[event.id] : undefined, loadingEffects: event.id ? loadingEffectsIds.includes(event.id) : false, dispatch: dispatch }, event.seq))), hasMore && (_jsx("div", { className: "flex items-center justify-center py-3", children: _jsx("button", { onClick: () => dispatch({ type: "ui/subject_chain_load_more" }), disabled: loading, className: "text-[10px] text-muted-foreground/60 hover:text-foreground px-3 py-1.5 rounded border border-border hover:border-foreground/20 transition-all disabled:opacity-40", children: loading ? "Loading…" : "Load more" }) }))] })) })] }));
|
|
50
|
+
}
|
|
@@ -3,17 +3,25 @@ import { useState, useCallback, useEffect, useRef, useMemo } from "react";
|
|
|
3
3
|
import { useSelector, useDispatch } from "../machine";
|
|
4
4
|
import { FilterBar } from "../components/FilterBar";
|
|
5
5
|
import { CopyablePayload } from "../components/CopyablePayload";
|
|
6
|
+
import { EffectList } from "../components/EffectList";
|
|
6
7
|
import { eventTextColor, eventBg } from "../theme";
|
|
7
8
|
import { formatTs, compactPayload, inScrubberRange } from "../utils";
|
|
8
|
-
import { Search, ChevronRight } from "lucide-react";
|
|
9
|
-
function EventRow({ event, isSelected, onClick,
|
|
9
|
+
import { Search, ChevronRight, Zap } from "lucide-react";
|
|
10
|
+
function EventRow({ event, isSelected, onClick, onFilterWorkflow, onInvestigate, onSubjectSelected, onEffectsRequested, effects, loadingEffects, }) {
|
|
10
11
|
const [payloadOpen, setPayloadOpen] = useState(false);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const [effectsOpen, setEffectsOpen] = useState(false);
|
|
13
|
+
const handleEffectsToggle = (e) => {
|
|
14
|
+
e.stopPropagation();
|
|
15
|
+
setEffectsOpen((v) => !v);
|
|
16
|
+
};
|
|
17
|
+
return (_jsxs("div", { className: `group w-full text-left px-3 py-2 border-b border-border transition-all duration-150 ${isSelected ? "bg-indigo-500/15" : "hover:bg-white/[0.02]"}`, children: [_jsx("div", { onClick: onClick, role: "button", tabIndex: 0, className: "w-full text-left cursor-pointer", children: _jsxs("div", { className: "flex items-center gap-2.5 min-w-0", children: [_jsx("span", { className: "text-[10px] font-mono text-muted-foreground/60 w-10 shrink-0 text-right tabular-nums", children: event.seq }), _jsx("span", { className: "text-[10px] text-muted-foreground/70 shrink-0 w-32 tabular-nums", children: formatTs(event.ts) }), event.workflowId && (_jsx("button", { onClick: (e) => { e.stopPropagation(); onFilterWorkflow(event.workflowId); }, className: "px-1.5 py-0.5 rounded-full text-[9px] font-mono bg-purple-500/8 text-purple-400/80 hover:bg-purple-500/15 hover:text-purple-400 shrink-0 transition-all border border-purple-500/10", title: `Filter by workflow ${event.workflowId}`, children: event.workflowId.slice(0, 8) })), event.aggregateType && event.aggregateId && onSubjectSelected && (_jsxs("button", { onClick: (e) => { e.stopPropagation(); onSubjectSelected(event.aggregateType, event.aggregateId); }, className: "px-1.5 py-0.5 rounded-full text-[9px] font-mono bg-teal-500/8 text-teal-400/80 hover:bg-teal-500/15 hover:text-teal-400 shrink-0 transition-all border border-teal-500/10", title: `View subject ${event.aggregateType}:${event.aggregateId}`, children: [event.aggregateType, ":", event.aggregateId.slice(0, 8)] })), _jsx("span", { className: "text-xs font-mono shrink-0 px-1.5 py-0.5 rounded", style: { color: eventTextColor(event.name), background: eventBg(event.name) }, children: event.name }), _jsxs("button", { onClick: (e) => { e.stopPropagation(); setPayloadOpen((v) => !v); }, className: "flex items-center gap-1 text-[10px] font-mono text-muted-foreground/60 hover:text-muted-foreground truncate text-left min-w-0 transition-colors", title: "Click to expand payload", children: [_jsx(ChevronRight, { size: 10, className: `shrink-0 transition-transform duration-150 ${payloadOpen ? "rotate-90" : ""}` }), _jsx("span", { className: "truncate", children: event.summary ?? compactPayload(event.payload) })] }), _jsxs("div", { className: "ml-auto flex items-center gap-1 shrink-0", children: [event.id && (_jsxs("button", { onClick: (e) => {
|
|
18
|
+
handleEffectsToggle(e);
|
|
19
|
+
if (!effectsOpen && effects === undefined && event.id) {
|
|
20
|
+
onEffectsRequested?.(event.id);
|
|
21
|
+
}
|
|
22
|
+
}, className: `opacity-0 group-hover:opacity-100 transition-all duration-150 flex items-center gap-1 px-1.5 py-0.5 rounded text-[9px] ${effectsOpen
|
|
23
|
+
? "opacity-100 bg-indigo-500/10 text-indigo-400/70 border border-indigo-500/20"
|
|
24
|
+
: "hover:bg-white/[0.05] text-muted-foreground/50 border border-transparent"}`, title: "Show effects", children: [_jsx(Zap, { size: 9 }), effects !== undefined && effects.length > 0 && _jsx("span", { children: effects.length })] })), onInvestigate && (_jsx("button", { onClick: (e) => { e.stopPropagation(); onInvestigate(); }, className: "opacity-0 group-hover:opacity-100 transition-opacity duration-150 p-1 rounded-md hover:bg-white/[0.05] shrink-0 text-muted-foreground", title: "Investigate", children: _jsx(Search, { size: 12 }) }))] })] }) }), payloadOpen && (_jsx(CopyablePayload, { payload: event.payload, className: "mt-2 ml-12 max-h-64" })), effectsOpen && (_jsx("div", { className: "mt-1 ml-12", children: loadingEffects ? (_jsx("div", { className: "text-[9px] text-muted-foreground/40 italic py-1", children: "Loading\u2026" })) : (_jsx(EffectList, { effects: effects ?? [] })) }))] }));
|
|
17
25
|
}
|
|
18
26
|
function InfiniteScrollSentinel({ onVisible, loading }) {
|
|
19
27
|
const ref = useRef(null);
|
|
@@ -35,14 +43,14 @@ function InfiniteScrollSentinel({ onVisible, loading }) {
|
|
|
35
43
|
export function TimelinePane({ onInvestigate } = {}) {
|
|
36
44
|
const events = useSelector((s) => {
|
|
37
45
|
let result = s.events;
|
|
38
|
-
const cid = s.filters.
|
|
46
|
+
const cid = s.filters.workflowId;
|
|
39
47
|
if (cid)
|
|
40
|
-
result = result.filter((e) => e.
|
|
48
|
+
result = result.filter((e) => e.workflowId === cid);
|
|
41
49
|
const search = s.filters.search?.toLowerCase();
|
|
42
50
|
if (search) {
|
|
43
51
|
result = result.filter((e) => e.name.toLowerCase().includes(search) ||
|
|
44
52
|
e.payload.toLowerCase().includes(search) ||
|
|
45
|
-
(e.
|
|
53
|
+
(e.workflowId ?? "").toLowerCase().includes(search));
|
|
46
54
|
}
|
|
47
55
|
return result;
|
|
48
56
|
});
|
|
@@ -51,6 +59,8 @@ export function TimelinePane({ onInvestigate } = {}) {
|
|
|
51
59
|
const selectedSeq = useSelector((s) => s.selectedSeq);
|
|
52
60
|
const scrubberStart = useSelector((s) => s.scrubberStart);
|
|
53
61
|
const scrubberEnd = useSelector((s) => s.scrubberEnd);
|
|
62
|
+
const expandedEffects = useSelector((s) => s.expandedEffects);
|
|
63
|
+
const loadingEffectsIds = useSelector((s) => s.loadingEffects);
|
|
54
64
|
const dispatch = useDispatch();
|
|
55
65
|
const displayedEvents = useMemo(() => {
|
|
56
66
|
if (scrubberStart == null && scrubberEnd == null)
|
|
@@ -59,15 +69,21 @@ export function TimelinePane({ onInvestigate } = {}) {
|
|
|
59
69
|
}, [events, scrubberStart, scrubberEnd]);
|
|
60
70
|
const handleSelect = useCallback((event) => {
|
|
61
71
|
dispatch({ type: "ui/event_selected", payload: { seq: event.seq } });
|
|
62
|
-
if (event.
|
|
63
|
-
dispatch({ type: "ui/flow_opened", payload: {
|
|
72
|
+
if (event.workflowId) {
|
|
73
|
+
dispatch({ type: "ui/flow_opened", payload: { workflowId: event.workflowId } });
|
|
64
74
|
}
|
|
65
75
|
}, [dispatch]);
|
|
66
|
-
const
|
|
67
|
-
dispatch({ type: "ui/filter_changed", payload: {
|
|
76
|
+
const handleFilterWorkflow = useCallback((workflowId) => {
|
|
77
|
+
dispatch({ type: "ui/filter_changed", payload: { workflowId } });
|
|
68
78
|
}, [dispatch]);
|
|
69
79
|
const handleLoadMore = useCallback(() => {
|
|
70
80
|
dispatch({ type: "ui/load_more_requested" });
|
|
71
81
|
}, [dispatch]);
|
|
72
|
-
|
|
82
|
+
const handleSubjectSelected = useCallback((aggregateType, aggregateId) => {
|
|
83
|
+
dispatch({ type: "ui/subject_selected", payload: { aggregateType, aggregateId, mode: "both" } });
|
|
84
|
+
}, [dispatch]);
|
|
85
|
+
const handleEffectsRequested = useCallback((eventId) => {
|
|
86
|
+
dispatch({ type: "ui/event_effects_requested", payload: { eventId } });
|
|
87
|
+
}, [dispatch]);
|
|
88
|
+
return (_jsxs("div", { className: "flex flex-col h-full", children: [_jsx(FilterBar, {}), loading && events.length === 0 ? (_jsx("div", { className: "animate-pulse p-1", children: Array.from({ length: 12 }).map((_, i) => (_jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5 border-b border-border", children: [_jsx("div", { className: "h-3 w-10 bg-white/[0.03] rounded shrink-0" }), _jsx("div", { className: "h-3 w-32 bg-white/[0.03] rounded shrink-0" }), _jsx("div", { className: "h-3 bg-white/[0.03] rounded flex-1", style: { maxWidth: `${150 + (i * 37) % 200}px` } })] }, i))) })) : events.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32 text-sm text-muted-foreground/60", children: "No events found" })) : (_jsxs("div", { className: "flex-1 overflow-y-auto", children: [displayedEvents.map((event) => (_jsx(EventRow, { event: event, isSelected: event.seq === selectedSeq, onClick: () => handleSelect(event), onFilterWorkflow: handleFilterWorkflow, onInvestigate: onInvestigate ? () => onInvestigate(event) : undefined, onSubjectSelected: handleSubjectSelected, onEffectsRequested: handleEffectsRequested, effects: event.id ? expandedEffects[event.id] : undefined, loadingEffects: event.id ? loadingEffectsIds.includes(event.id) : false }, event.seq))), hasMore && (_jsx(InfiniteScrollSentinel, { onVisible: handleLoadMore, loading: loading }))] }))] }));
|
|
73
89
|
}
|
|
@@ -27,6 +27,7 @@ const STATUS_COLORS = {
|
|
|
27
27
|
completed: { bar: "#22c55e", barEnd: "#16a34a", text: "#bbf7d0" },
|
|
28
28
|
running: { bar: "#eab308", barEnd: "#ca8a04", text: "#fef08a" },
|
|
29
29
|
error: { bar: "#ef4444", barEnd: "#dc2626", text: "#fecaca" },
|
|
30
|
+
retry: { bar: "#f97316", barEnd: "#ea580c", text: "#fed7aa" },
|
|
30
31
|
};
|
|
31
32
|
function statusColor(status) {
|
|
32
33
|
return STATUS_COLORS[status] ?? STATUS_COLORS.running;
|
|
@@ -57,15 +58,48 @@ function buildBars(outcomes) {
|
|
|
57
58
|
return { bars, minMs, maxMs };
|
|
58
59
|
}
|
|
59
60
|
// ---------------------------------------------------------------------------
|
|
61
|
+
// Attempt helpers
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
/** Group attempts by reactorId, sorted by attempt number. */
|
|
64
|
+
function groupAttempts(attempts) {
|
|
65
|
+
const map = new Map();
|
|
66
|
+
for (const a of attempts) {
|
|
67
|
+
let list = map.get(a.reactorId);
|
|
68
|
+
if (!list) {
|
|
69
|
+
list = [];
|
|
70
|
+
map.set(a.reactorId, list);
|
|
71
|
+
}
|
|
72
|
+
list.push(a);
|
|
73
|
+
}
|
|
74
|
+
for (const list of map.values()) {
|
|
75
|
+
list.sort((a, b) => a.attempt - b.attempt);
|
|
76
|
+
}
|
|
77
|
+
return map;
|
|
78
|
+
}
|
|
79
|
+
/** Factor attempts into the global min/max time range. */
|
|
80
|
+
function expandRange(attempts, minMs, maxMs) {
|
|
81
|
+
for (const a of attempts) {
|
|
82
|
+
const s = new Date(a.startedAt).getTime();
|
|
83
|
+
const e = new Date(a.completedAt).getTime();
|
|
84
|
+
if (s < minMs)
|
|
85
|
+
minMs = s;
|
|
86
|
+
if (e > maxMs)
|
|
87
|
+
maxMs = e;
|
|
88
|
+
}
|
|
89
|
+
return { minMs, maxMs };
|
|
90
|
+
}
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
60
92
|
// Constants
|
|
61
93
|
// ---------------------------------------------------------------------------
|
|
62
94
|
const ROW_HEIGHT = 36;
|
|
95
|
+
const ATTEMPT_ROW_HEIGHT = 26;
|
|
63
96
|
const LABEL_WIDTH = 160;
|
|
64
97
|
const BAR_MIN_WIDTH = 4;
|
|
65
98
|
const PADDING_X = 12;
|
|
66
99
|
export function WaterfallPane() {
|
|
67
|
-
const
|
|
68
|
-
const outcomes = useSelector((s) =>
|
|
100
|
+
const workflowId = useSelector((s) => s.flowWorkflowId);
|
|
101
|
+
const outcomes = useSelector((s) => workflowId ? s.outcomes[workflowId] ?? [] : []);
|
|
102
|
+
const attempts = useSelector((s) => workflowId ? s.attempts[workflowId] ?? [] : []);
|
|
69
103
|
const flowData = useSelector((s) => s.flowData);
|
|
70
104
|
const scrubberStart = useSelector((s) => s.scrubberStart);
|
|
71
105
|
const scrubberEnd = useSelector((s) => s.scrubberEnd);
|
|
@@ -74,7 +108,17 @@ export function WaterfallPane() {
|
|
|
74
108
|
const handleBarClick = useCallback((bar) => {
|
|
75
109
|
dispatch({ type: "ui/handler_selected", payload: { reactorId: bar.reactorId } });
|
|
76
110
|
}, [dispatch]);
|
|
77
|
-
const
|
|
111
|
+
const attemptsByReactor = useMemo(() => groupAttempts(attempts), [attempts]);
|
|
112
|
+
const { bars, minMs, maxMs } = useMemo(() => {
|
|
113
|
+
const result = buildBars(outcomes);
|
|
114
|
+
// Expand range to include attempt times
|
|
115
|
+
if (attempts.length > 0) {
|
|
116
|
+
const expanded = expandRange(attempts, result.minMs, result.maxMs);
|
|
117
|
+
result.minMs = expanded.minMs;
|
|
118
|
+
result.maxMs = expanded.maxMs;
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}, [outcomes, attempts]);
|
|
78
122
|
const rangeMs = maxMs - minMs || 1;
|
|
79
123
|
// Map event id → seq for scrubber sync
|
|
80
124
|
const eventIdToSeq = useMemo(() => {
|
|
@@ -94,11 +138,11 @@ export function WaterfallPane() {
|
|
|
94
138
|
return null;
|
|
95
139
|
return new Date(event.ts).getTime();
|
|
96
140
|
}, [scrubberEnd, flowData]);
|
|
97
|
-
if (!
|
|
141
|
+
if (!workflowId) {
|
|
98
142
|
return (_jsx("div", { style: { height: "100%", display: "flex", alignItems: "center", justifyContent: "center", color: "#50506a", fontSize: 12, letterSpacing: "0.03em" }, children: "Open a flow to see the reactor waterfall" }));
|
|
99
143
|
}
|
|
100
144
|
if (bars.length === 0) {
|
|
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
|
|
145
|
+
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 workflow" }));
|
|
102
146
|
}
|
|
103
147
|
const hasReactorFilter = logsFilter.reactorId != null;
|
|
104
148
|
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: () => {
|
|
@@ -129,78 +173,147 @@ export function WaterfallPane() {
|
|
|
129
173
|
? ((scrubberMs - minMs) / rangeMs) * 100
|
|
130
174
|
: null;
|
|
131
175
|
const isSelected = logsFilter.reactorId === bar.reactorId;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
flexShrink: 0,
|
|
147
|
-
fontSize: 11,
|
|
148
|
-
color: "#c0c0d0",
|
|
149
|
-
fontWeight: 500,
|
|
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",
|
|
176
|
+
const reactorAttempts = attemptsByReactor.get(bar.reactorId) ?? [];
|
|
177
|
+
const hasMultipleAttempts = reactorAttempts.length > 1;
|
|
178
|
+
return (_jsxs("div", { children: [_jsxs("div", { onClick: () => handleBarClick(bar), style: {
|
|
179
|
+
display: "flex",
|
|
180
|
+
alignItems: "center",
|
|
181
|
+
height: ROW_HEIGHT,
|
|
182
|
+
gap: 0,
|
|
183
|
+
opacity: isFuture ? 0.25 : (hasReactorFilter && !isSelected) ? 0.35 : 1,
|
|
184
|
+
transition: "opacity 200ms, background 150ms",
|
|
185
|
+
cursor: "pointer",
|
|
186
|
+
borderRadius: 6,
|
|
187
|
+
background: isSelected ? "rgba(99, 102, 241, 0.15)" : "transparent",
|
|
188
|
+
paddingLeft: 4,
|
|
189
|
+
paddingRight: 4,
|
|
162
190
|
}, children: [_jsx("div", { style: {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
191
|
+
width: LABEL_WIDTH,
|
|
192
|
+
flexShrink: 0,
|
|
193
|
+
fontSize: 11,
|
|
194
|
+
color: "#c0c0d0",
|
|
195
|
+
fontWeight: 500,
|
|
196
|
+
overflow: "hidden",
|
|
197
|
+
textOverflow: "ellipsis",
|
|
198
|
+
whiteSpace: "nowrap",
|
|
199
|
+
paddingRight: 10,
|
|
200
|
+
letterSpacing: "0.01em",
|
|
201
|
+
}, title: bar.reactorId, children: bar.reactorId }), _jsxs("div", { style: {
|
|
202
|
+
flex: 1,
|
|
203
|
+
position: "relative",
|
|
204
|
+
height: 22,
|
|
205
|
+
background: "rgba(255, 255, 255, 0.02)",
|
|
206
|
+
borderRadius: 5,
|
|
207
|
+
overflow: "hidden",
|
|
208
|
+
}, children: [_jsx("div", { style: {
|
|
209
|
+
position: "absolute",
|
|
210
|
+
left: `${offsetPct}%`,
|
|
211
|
+
width: `${widthPct}%`,
|
|
212
|
+
minWidth: BAR_MIN_WIDTH,
|
|
213
|
+
height: "100%",
|
|
214
|
+
background: `linear-gradient(90deg, ${colors.bar}, ${colors.barEnd})`,
|
|
215
|
+
borderRadius: 4,
|
|
216
|
+
opacity: 0.8,
|
|
217
|
+
display: "flex",
|
|
218
|
+
alignItems: "center",
|
|
219
|
+
paddingLeft: 5,
|
|
220
|
+
paddingRight: 5,
|
|
221
|
+
boxShadow: `0 1px 4px ${colors.bar}30`,
|
|
222
|
+
}, title: `${bar.reactorId}: ${bar.status} (${formatDuration(duration)})${bar.attempts > 1 ? ` — ${bar.attempts} attempts` : ""}${bar.error ? `\nError: ${bar.error}` : ""}`, children: _jsx("span", { style: {
|
|
223
|
+
fontSize: 9,
|
|
224
|
+
fontWeight: 600,
|
|
225
|
+
color: "#0a0a0f",
|
|
226
|
+
whiteSpace: "nowrap",
|
|
227
|
+
overflow: "hidden",
|
|
228
|
+
textOverflow: "ellipsis",
|
|
229
|
+
}, children: formatDuration(duration) }) }), cursorPct != null && (_jsx("div", { style: {
|
|
230
|
+
position: "absolute",
|
|
231
|
+
left: `${cursorPct}%`,
|
|
232
|
+
top: 0,
|
|
233
|
+
bottom: 0,
|
|
234
|
+
width: 1,
|
|
235
|
+
background: "#6366f1",
|
|
236
|
+
pointerEvents: "none",
|
|
237
|
+
boxShadow: "0 0 4px rgba(99, 102, 241, 0.3)",
|
|
238
|
+
} }))] }), _jsxs("div", { style: {
|
|
239
|
+
width: 80,
|
|
240
|
+
flexShrink: 0,
|
|
171
241
|
display: "flex",
|
|
172
242
|
alignItems: "center",
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
243
|
+
gap: 4,
|
|
244
|
+
paddingLeft: 10,
|
|
245
|
+
}, children: [_jsx("span", { style: {
|
|
246
|
+
fontSize: 10,
|
|
247
|
+
fontWeight: 500,
|
|
248
|
+
color: colors.text,
|
|
249
|
+
opacity: 0.8,
|
|
250
|
+
}, children: bar.status }), bar.attempts > 1 && (_jsxs("span", { style: { fontSize: 9, color: "#50506a" }, children: ["x", bar.attempts] }))] })] }), bar.status === "error" && bar.error && (_jsx("div", { style: {
|
|
251
|
+
marginLeft: LABEL_WIDTH + 4,
|
|
252
|
+
marginTop: -2,
|
|
253
|
+
marginBottom: 4,
|
|
254
|
+
fontSize: 10,
|
|
255
|
+
color: "#f87171",
|
|
256
|
+
paddingLeft: 4,
|
|
257
|
+
overflow: "hidden",
|
|
258
|
+
textOverflow: "ellipsis",
|
|
259
|
+
whiteSpace: "nowrap",
|
|
260
|
+
}, title: bar.error, children: bar.error })), hasMultipleAttempts && reactorAttempts.map((att) => {
|
|
261
|
+
const attStartMs = new Date(att.startedAt).getTime();
|
|
262
|
+
const attEndMs = new Date(att.completedAt).getTime();
|
|
263
|
+
const attOffsetPct = ((attStartMs - minMs) / rangeMs) * 100;
|
|
264
|
+
const attWidthPct = Math.max(((attEndMs - attStartMs) / rangeMs) * 100, 0.3);
|
|
265
|
+
const attColors = statusColor(att.status);
|
|
266
|
+
const attDuration = attEndMs - attStartMs;
|
|
267
|
+
return (_jsxs("div", { style: {
|
|
268
|
+
display: "flex",
|
|
269
|
+
alignItems: "center",
|
|
270
|
+
height: ATTEMPT_ROW_HEIGHT,
|
|
271
|
+
opacity: isFuture ? 0.25 : (hasReactorFilter && !isSelected) ? 0.35 : 0.7,
|
|
272
|
+
paddingLeft: 4,
|
|
273
|
+
paddingRight: 4,
|
|
274
|
+
}, children: [_jsxs("div", { style: {
|
|
275
|
+
width: LABEL_WIDTH,
|
|
276
|
+
flexShrink: 0,
|
|
177
277
|
fontSize: 9,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
whiteSpace: "nowrap",
|
|
278
|
+
color: "#70708a",
|
|
279
|
+
paddingLeft: 16,
|
|
181
280
|
overflow: "hidden",
|
|
182
281
|
textOverflow: "ellipsis",
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
282
|
+
whiteSpace: "nowrap",
|
|
283
|
+
paddingRight: 10,
|
|
284
|
+
}, children: ["attempt ", att.attempt + 1] }), _jsx("div", { style: {
|
|
285
|
+
flex: 1,
|
|
286
|
+
position: "relative",
|
|
287
|
+
height: 14,
|
|
288
|
+
borderRadius: 3,
|
|
289
|
+
}, children: _jsx("div", { style: {
|
|
290
|
+
position: "absolute",
|
|
291
|
+
left: `${attOffsetPct}%`,
|
|
292
|
+
width: `${attWidthPct}%`,
|
|
293
|
+
minWidth: 3,
|
|
294
|
+
height: "100%",
|
|
295
|
+
background: `linear-gradient(90deg, ${attColors.bar}, ${attColors.barEnd})`,
|
|
296
|
+
borderRadius: 3,
|
|
297
|
+
opacity: 0.6,
|
|
298
|
+
display: "flex",
|
|
299
|
+
alignItems: "center",
|
|
300
|
+
paddingLeft: 4,
|
|
301
|
+
paddingRight: 4,
|
|
302
|
+
}, title: `Attempt ${att.attempt + 1}: ${att.status} (${formatDuration(attDuration)})${att.error ? `\n${att.error}` : ""}`, children: _jsx("span", { style: {
|
|
303
|
+
fontSize: 8,
|
|
304
|
+
fontWeight: 600,
|
|
305
|
+
color: "#0a0a0f",
|
|
306
|
+
whiteSpace: "nowrap",
|
|
307
|
+
overflow: "hidden",
|
|
308
|
+
textOverflow: "ellipsis",
|
|
309
|
+
}, children: formatDuration(attDuration) }) }) }), _jsxs("div", { style: {
|
|
310
|
+
width: 80,
|
|
311
|
+
flexShrink: 0,
|
|
312
|
+
paddingLeft: 10,
|
|
313
|
+
fontSize: 9,
|
|
314
|
+
color: attColors.text,
|
|
315
|
+
opacity: 0.6,
|
|
316
|
+
}, children: [att.status, att.error && (_jsx("span", { style: { color: "#70708a", marginLeft: 4 }, title: att.error, children: "!" }))] })] }, `${att.reactorId}-attempt-${att.attempt}`));
|
|
317
|
+
})] }, bar.reactorId));
|
|
205
318
|
}), _jsxs("div", { style: { marginTop: 10, fontSize: 10, color: "#40405a", marginLeft: LABEL_WIDTH, letterSpacing: "0.03em" }, children: ["Total wall time: ", formatDuration(rangeMs)] })] })] }));
|
|
206
319
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback, useEffect, useRef } from "react";
|
|
3
|
+
import { useSelector, useDispatch } from "../machine";
|
|
4
|
+
import { eventTextColor, eventBg } from "../theme";
|
|
5
|
+
import { formatTs } from "../utils";
|
|
6
|
+
function RelativeDuration({ firstTs, lastTs }) {
|
|
7
|
+
const first = new Date(firstTs).getTime();
|
|
8
|
+
const last = new Date(lastTs).getTime();
|
|
9
|
+
const diffMs = last - first;
|
|
10
|
+
if (diffMs < 1000)
|
|
11
|
+
return _jsxs("span", { children: [diffMs, "ms"] });
|
|
12
|
+
if (diffMs < 60_000)
|
|
13
|
+
return _jsxs("span", { children: [(diffMs / 1000).toFixed(1), "s"] });
|
|
14
|
+
if (diffMs < 3_600_000)
|
|
15
|
+
return _jsxs("span", { children: [(diffMs / 60_000).toFixed(1), "m"] });
|
|
16
|
+
return _jsxs("span", { children: [(diffMs / 3_600_000).toFixed(1), "h"] });
|
|
17
|
+
}
|
|
18
|
+
export function WorkflowExplorerPane() {
|
|
19
|
+
const workflows = useSelector((s) => s.workflows);
|
|
20
|
+
const loading = useSelector((s) => s.workflowsLoading);
|
|
21
|
+
const dispatch = useDispatch();
|
|
22
|
+
const [search, setSearch] = useState("");
|
|
23
|
+
const searchTimerRef = useRef(null);
|
|
24
|
+
// Request workflows on mount
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
dispatch({ type: "ui/workflows_requested", payload: {} });
|
|
27
|
+
}, [dispatch]);
|
|
28
|
+
const handleSearchChange = useCallback((value) => {
|
|
29
|
+
setSearch(value);
|
|
30
|
+
if (searchTimerRef.current)
|
|
31
|
+
clearTimeout(searchTimerRef.current);
|
|
32
|
+
searchTimerRef.current = setTimeout(() => {
|
|
33
|
+
dispatch({ type: "ui/workflows_requested", payload: { search: value || undefined } });
|
|
34
|
+
}, 300);
|
|
35
|
+
}, [dispatch]);
|
|
36
|
+
const handleRowClick = useCallback((workflowId) => {
|
|
37
|
+
dispatch({ type: "ui/flow_opened", payload: { workflowId } });
|
|
38
|
+
}, [dispatch]);
|
|
39
|
+
const handleCopy = useCallback((text) => {
|
|
40
|
+
navigator.clipboard.writeText(text).catch(() => { });
|
|
41
|
+
}, []);
|
|
42
|
+
return (_jsxs("div", { className: "flex flex-col h-full", children: [_jsx("div", { className: "px-3 py-2.5 border-b border-border", style: { background: "rgba(15, 15, 20, 0.6)", backdropFilter: "blur(8px)" }, children: _jsx("input", { type: "text", placeholder: "Search by workflow ID or event type...", value: search, onChange: (e) => handleSearchChange(e.target.value), className: "w-full px-3 py-1.5 text-xs bg-background/50 border border-border rounded-md text-foreground placeholder:text-muted-foreground/40 focus:outline-none focus:ring-1 focus:ring-indigo-500/40 focus:border-indigo-500/30 transition-all" }) }), _jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border text-[9px] font-semibold text-muted-foreground/40 uppercase tracking-widest", children: [_jsx("span", { className: "w-28 shrink-0", children: "Root Event" }), _jsx("span", { className: "w-24 shrink-0", children: "Workflow" }), _jsx("span", { className: "w-12 shrink-0 text-right", children: "Events" }), _jsx("span", { className: "w-20 shrink-0 text-right", children: "Duration" }), _jsx("span", { className: "flex-1", children: "Last Activity" })] }), loading && workflows.length === 0 ? (_jsx("div", { className: "animate-pulse p-3", children: Array.from({ length: 8 }).map((_, i) => (_jsxs("div", { className: "flex items-center gap-2 py-2.5", children: [_jsx("div", { className: "h-3 w-28 bg-white/[0.03] rounded" }), _jsx("div", { className: "h-3 w-24 bg-white/[0.03] rounded" }), _jsx("div", { className: "h-3 w-12 bg-white/[0.03] rounded" })] }, i))) })) : workflows.length === 0 ? (_jsx("div", { className: "flex items-center justify-center h-32 text-xs text-muted-foreground/50 tracking-wide", children: "No workflows found" })) : (_jsx("div", { className: "flex-1 overflow-y-auto", children: workflows.map((corr) => (_jsxs("button", { onClick: () => handleRowClick(corr.workflowId), className: "group w-full text-left flex items-center gap-2 px-3 py-2.5 border-b border-border hover:bg-indigo-500/8 transition-all duration-150", children: [_jsx("span", { className: "text-[10px] font-mono shrink-0 w-28 truncate px-1.5 py-0.5 rounded", style: {
|
|
43
|
+
color: eventTextColor(corr.rootEventType),
|
|
44
|
+
background: eventBg(corr.rootEventType),
|
|
45
|
+
}, title: corr.rootEventType, children: corr.rootEventType }), _jsx("span", { className: "text-[10px] font-mono text-purple-400/70 w-24 shrink-0 truncate cursor-pointer hover:text-purple-400 transition-colors", title: `Click to copy: ${corr.workflowId}`, onClick: (e) => { e.stopPropagation(); handleCopy(corr.workflowId); }, children: corr.workflowId.slice(0, 8) }), _jsx("span", { className: "text-[11px] font-mono text-foreground/70 w-12 shrink-0 text-right tabular-nums", children: corr.eventCount }), _jsx("span", { className: "text-[10px] text-muted-foreground/50 w-20 shrink-0 text-right font-mono tabular-nums", children: _jsx(RelativeDuration, { firstTs: corr.firstTs, lastTs: corr.lastTs }) }), _jsx("span", { className: "text-[10px] text-muted-foreground/40 flex-1 truncate tabular-nums", children: formatTs(corr.lastTs) }), corr.hasErrors && (_jsx("span", { className: "flex items-center gap-1 px-1.5 py-0.5 rounded text-[9px] font-semibold shrink-0 bg-red-500/10 text-red-400/80 border border-red-500/20", style: { boxShadow: "0 0 6px rgba(239, 68, 68, 0.15)" }, title: "This workflow has errors", children: "error" }))] }, corr.workflowId))) }))] }));
|
|
46
|
+
}
|
package/dist/queries.d.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/** GraphQL query and subscription documents for the causal inspector API. */
|
|
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
|
|
3
|
-
export declare const INSPECTOR_EVENTS = "\n query InspectorEvents(\n $limit: Int!\n $cursor: Int\n $search: String\n $
|
|
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
|
|
5
|
-
export declare const INSPECTOR_CAUSAL_FLOW = "\n query InspectorCausalFlow($
|
|
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 causationId\n workflowId\n reactorId\n aggregateType\n aggregateId\n streamRevision\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 $workflowId: String\n $aggregateKey: String\n ) {\n inspectorEvents(\n limit: $limit\n cursor: $cursor\n search: $search\n workflowId: $workflowId\n aggregateKey: $aggregateKey\n ) {\n events {\n \n seq\n ts\n type\n name\n id\n causationId\n workflowId\n reactorId\n aggregateType\n aggregateId\n streamRevision\n summary\n payload\n\n }\n nextCursor\n }\n }\n";
|
|
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 causationId\n workflowId\n reactorId\n aggregateType\n aggregateId\n streamRevision\n summary\n payload\n\n }\n rootSeq\n }\n }\n";
|
|
5
|
+
export declare const INSPECTOR_CAUSAL_FLOW = "\n query InspectorCausalFlow($workflowId: String!) {\n inspectorCausalFlow(workflowId: $workflowId) {\n events {\n \n seq\n ts\n type\n name\n id\n causationId\n workflowId\n reactorId\n aggregateType\n aggregateId\n streamRevision\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";
|
|
7
|
-
export declare const
|
|
8
|
-
export declare const INSPECTOR_REACTOR_DESCRIPTIONS = "\n query InspectorReactorDescriptions($
|
|
9
|
-
export declare const INSPECTOR_REACTOR_DESCRIPTION_SNAPSHOTS = "\n query InspectorReactorDescriptionSnapshots($
|
|
10
|
-
export declare const INSPECTOR_AGGREGATE_TIMELINE = "\n query InspectorAggregateTimeline($
|
|
7
|
+
export declare const INSPECTOR_REACTOR_LOGS_BY_WORKFLOW = "\n query InspectorReactorLogsByWorkflow($workflowId: String!) {\n inspectorReactorLogsByWorkflow(workflowId: $workflowId) {\n eventId\n reactorId\n level\n message\n data\n loggedAt\n }\n }\n";
|
|
8
|
+
export declare const INSPECTOR_REACTOR_DESCRIPTIONS = "\n query InspectorReactorDescriptions($workflowId: String!) {\n inspectorReactorDescriptions(workflowId: $workflowId) {\n reactorId\n blocks\n }\n }\n";
|
|
9
|
+
export declare const INSPECTOR_REACTOR_DESCRIPTION_SNAPSHOTS = "\n query InspectorReactorDescriptionSnapshots($workflowId: String!) {\n inspectorReactorDescriptionSnapshots(workflowId: $workflowId) {\n seq\n eventId\n reactorId\n blocks\n }\n }\n";
|
|
10
|
+
export declare const INSPECTOR_AGGREGATE_TIMELINE = "\n query InspectorAggregateTimeline($workflowId: String!) {\n inspectorAggregateTimeline(workflowId: $workflowId) {\n seq\n eventId\n eventType\n aggregates {\n key\n state\n }\n }\n }\n";
|
|
11
11
|
export declare const INSPECTOR_REACTOR_DEPENDENCIES = "\n query InspectorReactorDependencies {\n inspectorReactorDependencies {\n reactorId\n inputEventTypes\n outputEventTypes\n }\n }\n";
|
|
12
12
|
export declare const INSPECTOR_AGGREGATE_KEYS = "\n query InspectorAggregateKeys {\n inspectorAggregateKeys\n }\n";
|
|
13
|
-
export declare const INSPECTOR_AGGREGATE_LIFECYCLE = "\n query InspectorAggregateLifecycle($aggregateKey: String!, $limit: Int) {\n inspectorAggregateLifecycle(aggregateKey: $aggregateKey, limit: $limit) {\n seq\n eventId\n eventType\n ts\n
|
|
14
|
-
export declare const
|
|
15
|
-
export declare const INSPECTOR_REACTOR_OUTCOMES = "\n query InspectorReactorOutcomes($
|
|
13
|
+
export declare const INSPECTOR_AGGREGATE_LIFECYCLE = "\n query InspectorAggregateLifecycle($aggregateKey: String!, $limit: Int) {\n inspectorAggregateLifecycle(aggregateKey: $aggregateKey, limit: $limit) {\n seq\n eventId\n eventType\n ts\n workflowId\n aggregateKey\n state\n }\n }\n";
|
|
14
|
+
export declare const INSPECTOR_WORKFLOWS = "\n query InspectorWorkflows($search: String, $limit: Int, $cursor: String) {\n inspectorWorkflows(search: $search, limit: $limit, cursor: $cursor) {\n workflows {\n workflowId\n eventCount\n firstTs\n lastTs\n rootEventType\n hasErrors\n }\n nextCursor\n }\n }\n";
|
|
15
|
+
export declare const INSPECTOR_REACTOR_OUTCOMES = "\n query InspectorReactorOutcomes($workflowId: String!) {\n inspectorReactorOutcomes(workflowId: $workflowId) {\n reactorId\n status\n error\n attempts\n startedAt\n completedAt\n triggeringEventIds\n }\n }\n";
|
|
16
|
+
export declare const INSPECTOR_REACTOR_ATTEMPTS = "\n query InspectorReactorAttempts($workflowId: String!) {\n inspectorReactorAttempts(workflowId: $workflowId) {\n eventId\n reactorId\n workflowId\n attempt\n status\n error\n startedAt\n completedAt\n }\n }\n";
|
|
17
|
+
export declare const INSPECTOR_SUBJECT_CHAIN = "\n query InspectorSubjectChain(\n $aggregateType: String!\n $aggregateId: String!\n $mode: SubjectChainMode!\n $limit: Int\n $cursor: Int\n ) {\n inspectorSubjectChain(\n aggregateType: $aggregateType\n aggregateId: $aggregateId\n mode: $mode\n limit: $limit\n cursor: $cursor\n ) {\n events {\n \n seq\n ts\n type\n name\n id\n causationId\n workflowId\n reactorId\n aggregateType\n aggregateId\n streamRevision\n summary\n payload\n sourceMode\n\n }\n nextCursor\n depthCapReached\n }\n }\n";
|
|
18
|
+
export declare const INSPECTOR_EFFECTS_FOR_EVENT = "\n query InspectorEffectsForEvent($eventId: String!) {\n inspectorEffectsForEvent(eventId: $eventId) {\n consumer\n label\n value\n createdAt\n }\n }\n";
|
|
19
|
+
export declare const INSPECTOR_AGGREGATE_TYPES = "\n query InspectorAggregateTypes($search: String, $limit: Int) {\n inspectorAggregateTypes(search: $search, limit: $limit)\n }\n";
|
|
20
|
+
export declare const INSPECTOR_AGGREGATE_KEYS_BY_TYPE = "\n query InspectorAggregateKeysByType(\n $aggregateType: String!\n $search: String\n $limit: Int\n $cursor: String\n ) {\n inspectorAggregateKeysByType(\n aggregateType: $aggregateType\n search: $search\n limit: $limit\n cursor: $cursor\n ) {\n entries {\n aggregateId\n displayLabel\n }\n nextCursor\n }\n }\n";
|