@workflow/web-shared 5.0.0-beta.11 → 5.0.0-beta.13
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/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +9 -9
- package/dist/components/new-trace-viewer/components/event-list.d.ts +1 -1
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/event-list.js +4 -2
- package/dist/components/new-trace-viewer/components/timeline.d.ts +1 -1
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/timeline.js +4 -4
- package/dist/components/new-trace-viewer/context.d.ts +1 -1
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/context.js +1 -1
- package/dist/components/new-trace-viewer/icons.js +3 -3
- package/dist/components/new-trace-viewer/search.d.ts +1 -1
- package/dist/components/new-trace-viewer/search.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/search.js +1 -1
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +2 -2
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/trace-viewer.js +7 -8
- package/dist/components/new-trace-viewer/types.d.ts +2 -0
- package/dist/components/new-trace-viewer/types.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/types.js +2 -2
- package/dist/components/new-trace-viewer/utils.d.ts +1 -1
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/utils.js +1 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +7 -7
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +7 -7
- package/dist/components/trace-viewer-new.d.ts.map +1 -1
- package/dist/components/trace-viewer-new.js +2 -3
- package/dist/components/ui/error-stack-block.d.ts +17 -10
- package/dist/components/ui/error-stack-block.d.ts.map +1 -1
- package/dist/components/ui/error-stack-block.js +30 -19
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +26 -2
- package/package.json +4 -4
- package/src/components/event-list-view.tsx +12 -11
- package/src/components/new-trace-viewer/components/event-list.tsx +4 -3
- package/src/components/new-trace-viewer/components/timeline.tsx +4 -4
- package/src/components/new-trace-viewer/context.tsx +1 -1
- package/src/components/new-trace-viewer/icons.tsx +2 -2
- package/src/components/new-trace-viewer/search.ts +1 -1
- package/src/components/new-trace-viewer/trace-viewer.tsx +8 -15
- package/src/components/new-trace-viewer/types.ts +2 -0
- package/src/components/new-trace-viewer/utils.ts +1 -1
- package/src/components/sidebar/attribute-panel.tsx +6 -9
- package/src/components/sidebar/events-list.tsx +6 -9
- package/src/components/trace-viewer-new.tsx +2 -4
- package/src/components/ui/error-stack-block.tsx +51 -31
- package/src/lib/hydration.ts +28 -1
- package/dist/components/new-trace-viewer/detail-panel.d.ts +0 -10
- package/dist/components/new-trace-viewer/detail-panel.d.ts.map +0 -1
- package/dist/components/new-trace-viewer/detail-panel.js +0 -13
- package/dist/components/new-trace-viewer/util/constants.d.ts +0 -1
- package/dist/components/new-trace-viewer/util/constants.d.ts.map +0 -1
- package/dist/components/new-trace-viewer/util/constants.js +0 -2
- package/src/components/new-trace-viewer/detail-panel.tsx +0 -55
- package/src/components/new-trace-viewer/util/constants.ts +0 -0
|
@@ -26,8 +26,8 @@ import {
|
|
|
26
26
|
EntityDetailPanel,
|
|
27
27
|
type SelectedSpanInfo,
|
|
28
28
|
} from '../sidebar/entity-detail-panel';
|
|
29
|
-
import {
|
|
30
|
-
import type {
|
|
29
|
+
import { useSidebarData } from '../sidebar/sidebar-data-context';
|
|
30
|
+
import type { TraceWithMeta } from './types';
|
|
31
31
|
import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
|
|
32
32
|
import { IconButton } from '../ui/icon-button';
|
|
33
33
|
import { Spinner } from '../ui/spinner';
|
|
@@ -46,12 +46,11 @@ import {
|
|
|
46
46
|
TooltipTrigger,
|
|
47
47
|
} from '../ui/tooltip';
|
|
48
48
|
import { ActiveSpanProvider, useActiveSpan } from './context';
|
|
49
|
-
import { DetailPanel } from './detail-panel';
|
|
50
49
|
import { searchSpans } from './search';
|
|
51
50
|
import { computeRootBounds, computeTimeMarkers } from './utils';
|
|
52
51
|
|
|
53
52
|
interface NewTraceViewerProps {
|
|
54
|
-
trace:
|
|
53
|
+
trace: TraceWithMeta;
|
|
55
54
|
onLoadMore?: () => void | Promise<void>;
|
|
56
55
|
hasMore?: boolean;
|
|
57
56
|
isLoadingMore?: boolean;
|
|
@@ -141,10 +140,10 @@ function useAnimatedViewport(initial: Viewport) {
|
|
|
141
140
|
|
|
142
141
|
function useSelectedSpanInfo(): SelectedSpanInfo | null {
|
|
143
142
|
const { activeSpan } = useActiveSpan();
|
|
144
|
-
const sidebar =
|
|
143
|
+
const sidebar = useSidebarData();
|
|
145
144
|
|
|
146
145
|
return useMemo(() => {
|
|
147
|
-
if (!activeSpan
|
|
146
|
+
if (!activeSpan) return null;
|
|
148
147
|
|
|
149
148
|
const correlationId = activeSpan.spanId;
|
|
150
149
|
const rawEvents = correlationId
|
|
@@ -193,7 +192,7 @@ function NewTraceViewerContent({
|
|
|
193
192
|
const { activeSpan, activeSpanId, setActiveSpan, clearActiveSpan } =
|
|
194
193
|
useActiveSpan();
|
|
195
194
|
|
|
196
|
-
const sidebar =
|
|
195
|
+
const sidebar = useSidebarData();
|
|
197
196
|
const selectedSpan = useSelectedSpanInfo();
|
|
198
197
|
|
|
199
198
|
const [searchQuery, setSearchQuery] = useState('');
|
|
@@ -562,7 +561,7 @@ function NewTraceViewerContent({
|
|
|
562
561
|
<div
|
|
563
562
|
data-pane="pane-root"
|
|
564
563
|
data-has-detail={activeSpan ? '' : undefined}
|
|
565
|
-
className="grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,
|
|
564
|
+
className="grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,360px,100%)]"
|
|
566
565
|
>
|
|
567
566
|
<div
|
|
568
567
|
id="trace-parent"
|
|
@@ -674,7 +673,7 @@ function NewTraceViewerContent({
|
|
|
674
673
|
</div>
|
|
675
674
|
|
|
676
675
|
{/* Detail panel */}
|
|
677
|
-
{activeSpan
|
|
676
|
+
{activeSpan ? (
|
|
678
677
|
<aside className="flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto">
|
|
679
678
|
{/* Panel header */}
|
|
680
679
|
<div className="flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3">
|
|
@@ -750,12 +749,6 @@ function NewTraceViewerContent({
|
|
|
750
749
|
</ErrorBoundary>
|
|
751
750
|
</div>
|
|
752
751
|
</aside>
|
|
753
|
-
) : activeSpan ? (
|
|
754
|
-
<DetailPanel
|
|
755
|
-
span={activeSpan}
|
|
756
|
-
rootStart={root.startTime}
|
|
757
|
-
onClose={clearActiveSpan}
|
|
758
|
-
/>
|
|
759
752
|
) : null}
|
|
760
753
|
</div>
|
|
761
754
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Span, SpanEvent } from '
|
|
1
|
+
import type { Span, SpanEvent } from './types';
|
|
2
2
|
import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
|
|
3
3
|
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
@@ -8,20 +8,17 @@ import { useCallback, useContext, useMemo, useState } from 'react';
|
|
|
8
8
|
import { isEncryptedMarker, isExpiredMarker } from '../../lib/hydration';
|
|
9
9
|
import { useToast } from '../../lib/toast';
|
|
10
10
|
import { extractConversation, isDoStreamStep } from '../../lib/utils';
|
|
11
|
+
import { CopyButton } from '../new-trace-viewer/components/copy-button';
|
|
12
|
+
import { MiddleTruncate } from '../new-trace-viewer/components/middle-truncate/middle-truncate';
|
|
11
13
|
import {
|
|
12
14
|
DecryptClickContext,
|
|
13
15
|
RunClickContext,
|
|
14
16
|
StreamClickContext,
|
|
15
17
|
} from '../ui/data-inspector';
|
|
16
18
|
import { ErrorCard } from '../ui/error-card';
|
|
17
|
-
import {
|
|
18
|
-
ErrorStackBlock,
|
|
19
|
-
isStructuredErrorWithStack,
|
|
20
|
-
} from '../ui/error-stack-block';
|
|
19
|
+
import { ErrorStackBlock, isStructuredError } from '../ui/error-stack-block';
|
|
21
20
|
import { Skeleton } from '../ui/skeleton';
|
|
22
21
|
import { TimestampTooltip } from '../ui/timestamp-tooltip';
|
|
23
|
-
import { CopyButton } from '../new-trace-viewer/components/copy-button';
|
|
24
|
-
import { MiddleTruncate } from '../new-trace-viewer/components/middle-truncate/middle-truncate';
|
|
25
22
|
import { ConversationView } from './conversation-view';
|
|
26
23
|
import { CopyableDataBlock, EncryptedDataBlock } from './copyable-data-block';
|
|
27
24
|
import { DetailCard } from './detail-card';
|
|
@@ -548,9 +545,9 @@ const attributeToDisplayFn: Record<
|
|
|
548
545
|
if (isExpiredMarker(value)) return <ExpiredFieldBlock />;
|
|
549
546
|
if (!hasDisplayContent(value)) return null;
|
|
550
547
|
|
|
551
|
-
//
|
|
552
|
-
//
|
|
553
|
-
if (
|
|
548
|
+
// Structured workflow errors may be persisted as either `{ message }` or
|
|
549
|
+
// `{ message, stack }`. Render both with the dedicated error block.
|
|
550
|
+
if (isStructuredError(value)) {
|
|
554
551
|
return (
|
|
555
552
|
<DetailCard summary="Error" defaultOpen>
|
|
556
553
|
<ErrorStackBlock value={value} />
|
|
@@ -4,10 +4,7 @@ import { EVENT_DATA_REF_FIELDS, type Event } from '@workflow/world';
|
|
|
4
4
|
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
5
5
|
import { hasEncryptedFields, isExpiredMarker } from '../../lib/hydration';
|
|
6
6
|
import { ErrorCard } from '../ui/error-card';
|
|
7
|
-
import {
|
|
8
|
-
ErrorStackBlock,
|
|
9
|
-
isStructuredErrorWithStack,
|
|
10
|
-
} from '../ui/error-stack-block';
|
|
7
|
+
import { ErrorStackBlock, isStructuredError } from '../ui/error-stack-block';
|
|
11
8
|
import { Skeleton } from '../ui/skeleton';
|
|
12
9
|
import { CopyableDataBlock, EncryptedDataBlock } from './copyable-data-block';
|
|
13
10
|
import { DetailCard } from './detail-card';
|
|
@@ -196,8 +193,8 @@ function hasOnlyExpiredFields(data: unknown, eventType: string): boolean {
|
|
|
196
193
|
}
|
|
197
194
|
|
|
198
195
|
/**
|
|
199
|
-
* Renders event data, using ErrorStackBlock for error events that contain
|
|
200
|
-
*
|
|
196
|
+
* Renders event data, using ErrorStackBlock for error events that contain a
|
|
197
|
+
* structured error, and CopyableDataBlock otherwise.
|
|
201
198
|
*/
|
|
202
199
|
function EventDataBlock({
|
|
203
200
|
eventType,
|
|
@@ -239,12 +236,12 @@ function EventDataBlock({
|
|
|
239
236
|
const record = data as Record<string, unknown>;
|
|
240
237
|
|
|
241
238
|
// Check the nested `error` field first (the StructuredError)
|
|
242
|
-
if (
|
|
239
|
+
if (isStructuredError(record.error)) {
|
|
243
240
|
return <ErrorStackBlock value={record.error} />;
|
|
244
241
|
}
|
|
245
242
|
|
|
246
|
-
// Some error formats put the stack at the top level of eventData
|
|
247
|
-
if (
|
|
243
|
+
// Some error formats put the message/stack at the top level of eventData.
|
|
244
|
+
if (isStructuredError(record)) {
|
|
248
245
|
return <ErrorStackBlock value={record} />;
|
|
249
246
|
}
|
|
250
247
|
}
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
type SidebarDataContextValue,
|
|
9
9
|
SidebarDataProvider,
|
|
10
10
|
} from './sidebar/sidebar-data-context';
|
|
11
|
-
import type { Trace } from './trace-viewer/types';
|
|
12
11
|
|
|
13
12
|
const NewTraceViewer = ({
|
|
14
13
|
run,
|
|
@@ -27,14 +26,13 @@ const NewTraceViewer = ({
|
|
|
27
26
|
isLoadingMore?: boolean;
|
|
28
27
|
loading?: boolean;
|
|
29
28
|
}) => {
|
|
30
|
-
const
|
|
29
|
+
const trace: TraceWithMeta | undefined = useMemo(() => {
|
|
31
30
|
if (!run?.runId) {
|
|
32
31
|
return undefined;
|
|
33
32
|
}
|
|
34
33
|
return buildTrace(run, events, new Date());
|
|
35
34
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- `new Date()` is intentionally not a dep
|
|
36
35
|
}, [run, events]);
|
|
37
|
-
const trace = traceWithMeta;
|
|
38
36
|
|
|
39
37
|
if (!trace || (loading && events.length === 0)) {
|
|
40
38
|
return <TraceViewerSkeleton />;
|
|
@@ -44,7 +42,7 @@ const NewTraceViewer = ({
|
|
|
44
42
|
<SidebarDataProvider value={sidebarData}>
|
|
45
43
|
<div className="relative w-full h-full flex">
|
|
46
44
|
<NewTraceViewerComponent
|
|
47
|
-
trace={trace
|
|
45
|
+
trace={trace}
|
|
48
46
|
onLoadMore={onLoadMore}
|
|
49
47
|
hasMore={hasMore}
|
|
50
48
|
isLoadingMore={isLoadingMore}
|
|
@@ -3,18 +3,36 @@
|
|
|
3
3
|
import { AlertCircle } from 'lucide-react';
|
|
4
4
|
import { CopyButton } from '../new-trace-viewer/components/copy-button';
|
|
5
5
|
|
|
6
|
+
export type StructuredErrorRecord = Record<string, unknown> & {
|
|
7
|
+
message?: string;
|
|
8
|
+
stack?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
6
11
|
/**
|
|
7
|
-
* Check whether `value` looks like a structured error object
|
|
8
|
-
*
|
|
12
|
+
* Check whether `value` looks like a structured error object we can render
|
|
13
|
+
* with the error block. Some persisted workflow errors only include a
|
|
14
|
+
* `message`, while runtime errors usually also include `stack`.
|
|
9
15
|
*/
|
|
10
|
-
export function
|
|
16
|
+
export function isStructuredError(
|
|
11
17
|
value: unknown
|
|
12
|
-
): value is
|
|
18
|
+
): value is StructuredErrorRecord {
|
|
13
19
|
return (
|
|
14
20
|
value != null &&
|
|
15
21
|
typeof value === 'object' &&
|
|
16
|
-
'
|
|
17
|
-
|
|
22
|
+
(typeof (value as Record<string, unknown>).message === 'string' ||
|
|
23
|
+
typeof (value as Record<string, unknown>).stack === 'string')
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Narrower guard kept for callers that specifically need a stack trace.
|
|
29
|
+
*/
|
|
30
|
+
export function isStructuredErrorWithStack(
|
|
31
|
+
value: unknown
|
|
32
|
+
): value is StructuredErrorRecord & { stack: string } {
|
|
33
|
+
return (
|
|
34
|
+
isStructuredError(value) &&
|
|
35
|
+
typeof (value as StructuredErrorRecord).stack === 'string'
|
|
18
36
|
);
|
|
19
37
|
}
|
|
20
38
|
|
|
@@ -34,22 +52,22 @@ function deriveTitle(message: string): string {
|
|
|
34
52
|
}
|
|
35
53
|
|
|
36
54
|
/**
|
|
37
|
-
* Renders
|
|
38
|
-
*
|
|
39
|
-
*
|
|
55
|
+
* Renders a structured error as a visually distinct error block. Shows the
|
|
56
|
+
* error message with an alert icon at the top, separated from the stack trace
|
|
57
|
+
* or full message below.
|
|
40
58
|
*/
|
|
41
|
-
export function ErrorStackBlock({
|
|
42
|
-
value
|
|
43
|
-
}: {
|
|
44
|
-
value: Record<string, unknown> & { stack: string };
|
|
45
|
-
}) {
|
|
46
|
-
const stack = value.stack;
|
|
59
|
+
export function ErrorStackBlock({ value }: { value: StructuredErrorRecord }) {
|
|
60
|
+
const stack = typeof value.stack === 'string' ? value.stack : undefined;
|
|
47
61
|
const message = typeof value.message === 'string' ? value.message : undefined;
|
|
48
|
-
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
const
|
|
62
|
+
const body = stack ?? message ?? '';
|
|
63
|
+
// V8's `Error.stack` already starts with `Name: message`; message-only
|
|
64
|
+
// errors use the message as the body so long single-line failures remain
|
|
65
|
+
// readable even when the header truncates.
|
|
66
|
+
const title = message ? deriveTitle(message) : deriveTitle(body);
|
|
67
|
+
const copyText =
|
|
68
|
+
message && stack && !stack.includes(message)
|
|
69
|
+
? `${message}\n\n${stack}`
|
|
70
|
+
: body;
|
|
53
71
|
|
|
54
72
|
return (
|
|
55
73
|
<div
|
|
@@ -76,8 +94,8 @@ export function ErrorStackBlock({
|
|
|
76
94
|
<AlertCircle className="h-4 w-4 shrink-0" />
|
|
77
95
|
<p
|
|
78
96
|
className="text-xs font-semibold m-0 truncate"
|
|
79
|
-
// The full
|
|
80
|
-
//
|
|
97
|
+
// The full message or stack is in the body below; the header just
|
|
98
|
+
// shows the first line, single-line, with overflow
|
|
81
99
|
// ellipsised so a long title doesn't push the copy button or
|
|
82
100
|
// wrap into the framed hint/docs lines.
|
|
83
101
|
title={message}
|
|
@@ -86,15 +104,17 @@ export function ErrorStackBlock({
|
|
|
86
104
|
</p>
|
|
87
105
|
</div>
|
|
88
106
|
)}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
{body && (
|
|
108
|
+
<pre
|
|
109
|
+
className="px-3 py-2.5 text-xs font-mono whitespace-pre-wrap break-words overflow-auto m-0"
|
|
110
|
+
style={{
|
|
111
|
+
color: 'var(--ds-red-900)',
|
|
112
|
+
background: 'var(--ds-red-200)',
|
|
113
|
+
}}
|
|
114
|
+
>
|
|
115
|
+
{body}
|
|
116
|
+
</pre>
|
|
117
|
+
)}
|
|
98
118
|
</div>
|
|
99
119
|
);
|
|
100
120
|
}
|
package/src/lib/hydration.ts
CHANGED
|
@@ -135,7 +135,8 @@ export function getWebRevivers(): Revivers {
|
|
|
135
135
|
// Error family. The reducer side (see
|
|
136
136
|
// `packages/core/src/serialization/reducers/common.ts`) emits a tagged
|
|
137
137
|
// entry for each built-in Error subclass plus the workflow-specific
|
|
138
|
-
// `FatalError` / `RetryableError`
|
|
138
|
+
// `FatalError` / `RetryableError` / `HookConflictError` /
|
|
139
|
+
// `RuntimeDecryptionError` and `AggregateError`. Without
|
|
139
140
|
// matching revivers here, `devalue.unflatten` throws "Unknown type X"
|
|
140
141
|
// — which surfaces in the web o11y UI as "Failed to load resource
|
|
141
142
|
// details: Unknown type FatalError".
|
|
@@ -183,6 +184,20 @@ export function getWebRevivers(): Revivers {
|
|
|
183
184
|
if (value.stack !== undefined) error.stack = value.stack;
|
|
184
185
|
return error;
|
|
185
186
|
},
|
|
187
|
+
HookConflictError: (value) => {
|
|
188
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
189
|
+
const error = new Error(value.message, opts) as Error & {
|
|
190
|
+
token?: string;
|
|
191
|
+
conflictingRunId?: string;
|
|
192
|
+
};
|
|
193
|
+
error.name = 'HookConflictError';
|
|
194
|
+
error.token = value.token;
|
|
195
|
+
if (value.conflictingRunId !== undefined) {
|
|
196
|
+
error.conflictingRunId = value.conflictingRunId;
|
|
197
|
+
}
|
|
198
|
+
if (value.stack !== undefined) error.stack = value.stack;
|
|
199
|
+
return error;
|
|
200
|
+
},
|
|
186
201
|
RetryableError: (value) => {
|
|
187
202
|
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
188
203
|
const error = new Error(value.message, opts) as Error & {
|
|
@@ -201,6 +216,18 @@ export function getWebRevivers(): Revivers {
|
|
|
201
216
|
}
|
|
202
217
|
return error;
|
|
203
218
|
},
|
|
219
|
+
RuntimeDecryptionError: (value) => {
|
|
220
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
221
|
+
const error = new Error(value.message, opts) as Error & {
|
|
222
|
+
context?: unknown;
|
|
223
|
+
};
|
|
224
|
+
error.name = 'RuntimeDecryptionError';
|
|
225
|
+
if (value.context !== undefined) {
|
|
226
|
+
error.context = value.context;
|
|
227
|
+
}
|
|
228
|
+
if (value.stack !== undefined) error.stack = value.stack;
|
|
229
|
+
return error;
|
|
230
|
+
},
|
|
204
231
|
DOMException: (value) => {
|
|
205
232
|
// Modern browsers and Node 18+ expose `DOMException` on globalThis.
|
|
206
233
|
// `AbortController.abort()` with no argument synthesizes one as the
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import type { Span } from '../trace-viewer/types';
|
|
3
|
-
interface DetailPanelProps {
|
|
4
|
-
span: Span;
|
|
5
|
-
rootStart: number;
|
|
6
|
-
onClose: () => void;
|
|
7
|
-
}
|
|
8
|
-
export declare function DetailPanel({ span, rootStart, onClose, }: DetailPanelProps): ReactNode;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=detail-panel.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"detail-panel.d.ts","sourceRoot":"","sources":["../../../src/components/new-trace-viewer/detail-panel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAKlD,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,SAAS,EACT,OAAO,GACR,EAAE,gBAAgB,GAAG,SAAS,CAmC9B"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { X } from 'lucide-react';
|
|
4
|
-
import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
|
|
5
|
-
import { IconButton } from '../ui/icon-button';
|
|
6
|
-
import { getSpanDurationMs } from './utils';
|
|
7
|
-
export function DetailPanel({ span, rootStart, onClose, }) {
|
|
8
|
-
const startMs = getHighResInMs(span.startTime);
|
|
9
|
-
const durationMs = getSpanDurationMs(span);
|
|
10
|
-
const offsetMs = startMs - rootStart;
|
|
11
|
-
return (_jsxs("aside", { className: "grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200", children: [_jsxs("div", { className: "flex items-center justify-between px-3 border-b border-gray-alpha-400", children: [_jsx("span", { className: "text-sm font-medium text-gray-1000 truncate", children: span.name }), _jsx(IconButton, { "aria-label": "Close span details", onClick: onClose, children: _jsx(X, { className: "w-4 h-4" }) })] }), _jsx("div", { className: "overflow-y-auto p-3 space-y-3", children: _jsxs("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-sm", children: [_jsx("dt", { className: "text-gray-900", children: "Resource" }), _jsx("dd", { className: "text-gray-1000 font-mono", children: span.resource }), _jsx("dt", { className: "text-gray-900", children: "Duration" }), _jsx("dd", { className: "text-gray-1000 tabular-nums font-mono", children: formatDuration(durationMs) }), _jsx("dt", { className: "text-gray-900", children: "Offset" }), _jsxs("dd", { className: "text-gray-1000 tabular-nums font-mono", children: ["+", formatDuration(offsetMs)] }), _jsx("dt", { className: "text-gray-900", children: "Status" }), _jsx("dd", { className: "text-gray-1000 font-mono", children: span.status.code === 2 ? 'Error' : 'OK' })] }) })] }));
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV0YWlsLXBhbmVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbmV3LXRyYWNlLXZpZXdlci9kZXRhaWwtcGFuZWwudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFFYixPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBR2pDLE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDN0UsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQVE1QyxNQUFNLFVBQVUsV0FBVyxDQUFDLEVBQzFCLElBQUksRUFDSixTQUFTLEVBQ1QsT0FBTyxHQUNVO0lBQ2pCLE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDL0MsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsTUFBTSxRQUFRLEdBQUcsT0FBTyxHQUFHLFNBQVMsQ0FBQztJQUVyQyxPQUFPLENBQ0wsaUJBQU8sU0FBUyxFQUFDLGlFQUFpRSxhQUNoRixlQUFLLFNBQVMsRUFBQyx1RUFBdUUsYUFDcEYsZUFBTSxTQUFTLEVBQUMsNkNBQTZDLFlBQzFELElBQUksQ0FBQyxJQUFJLEdBQ0wsRUFDUCxLQUFDLFVBQVUsa0JBQVksb0JBQW9CLEVBQUMsT0FBTyxFQUFFLE9BQU8sWUFDMUQsS0FBQyxDQUFDLElBQUMsU0FBUyxFQUFDLFNBQVMsR0FBRyxHQUNkLElBQ1QsRUFDTixjQUFLLFNBQVMsRUFBQywrQkFBK0IsWUFDNUMsY0FBSSxTQUFTLEVBQUMscURBQXFELGFBQ2pFLGFBQUksU0FBUyxFQUFDLGVBQWUseUJBQWMsRUFDM0MsYUFBSSxTQUFTLEVBQUMsMEJBQTBCLFlBQUUsSUFBSSxDQUFDLFFBQVEsR0FBTSxFQUM3RCxhQUFJLFNBQVMsRUFBQyxlQUFlLHlCQUFjLEVBQzNDLGFBQUksU0FBUyxFQUFDLHVDQUF1QyxZQUNsRCxjQUFjLENBQUMsVUFBVSxDQUFDLEdBQ3hCLEVBQ0wsYUFBSSxTQUFTLEVBQUMsZUFBZSx1QkFBWSxFQUN6QyxjQUFJLFNBQVMsRUFBQyx1Q0FBdUMsa0JBQ2pELGNBQWMsQ0FBQyxRQUFRLENBQUMsSUFDdkIsRUFDTCxhQUFJLFNBQVMsRUFBQyxlQUFlLHVCQUFZLEVBQ3pDLGFBQUksU0FBUyxFQUFDLDBCQUEwQixZQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUNyQyxJQUNGLEdBQ0QsSUFDQSxDQUNULENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBjbGllbnQnO1xuXG5pbXBvcnQgeyBYIH0gZnJvbSAnbHVjaWRlLXJlYWN0JztcbmltcG9ydCB0eXBlIHsgUmVhY3ROb2RlIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHR5cGUgeyBTcGFuIH0gZnJvbSAnLi4vdHJhY2Utdmlld2VyL3R5cGVzJztcbmltcG9ydCB7IGZvcm1hdER1cmF0aW9uLCBnZXRIaWdoUmVzSW5NcyB9IGZyb20gJy4uL3RyYWNlLXZpZXdlci91dGlsL3RpbWluZyc7XG5pbXBvcnQgeyBJY29uQnV0dG9uIH0gZnJvbSAnLi4vdWkvaWNvbi1idXR0b24nO1xuaW1wb3J0IHsgZ2V0U3BhbkR1cmF0aW9uTXMgfSBmcm9tICcuL3V0aWxzJztcblxuaW50ZXJmYWNlIERldGFpbFBhbmVsUHJvcHMge1xuICBzcGFuOiBTcGFuO1xuICByb290U3RhcnQ6IG51bWJlcjtcbiAgb25DbG9zZTogKCkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIERldGFpbFBhbmVsKHtcbiAgc3BhbixcbiAgcm9vdFN0YXJ0LFxuICBvbkNsb3NlLFxufTogRGV0YWlsUGFuZWxQcm9wcyk6IFJlYWN0Tm9kZSB7XG4gIGNvbnN0IHN0YXJ0TXMgPSBnZXRIaWdoUmVzSW5NcyhzcGFuLnN0YXJ0VGltZSk7XG4gIGNvbnN0IGR1cmF0aW9uTXMgPSBnZXRTcGFuRHVyYXRpb25NcyhzcGFuKTtcbiAgY29uc3Qgb2Zmc2V0TXMgPSBzdGFydE1zIC0gcm9vdFN0YXJ0O1xuXG4gIHJldHVybiAoXG4gICAgPGFzaWRlIGNsYXNzTmFtZT1cImdyaWQgaC1mdWxsIG1heC1oLWZ1bGwgZ3JpZC1yb3dzLVsyLjVyZW1fMWZyXSBiZy1iYWNrZ3JvdW5kLTIwMFwiPlxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gcHgtMyBib3JkZXItYiBib3JkZXItZ3JheS1hbHBoYS00MDBcIj5cbiAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LWdyYXktMTAwMCB0cnVuY2F0ZVwiPlxuICAgICAgICAgIHtzcGFuLm5hbWV9XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPEljb25CdXR0b24gYXJpYS1sYWJlbD1cIkNsb3NlIHNwYW4gZGV0YWlsc1wiIG9uQ2xpY2s9e29uQ2xvc2V9PlxuICAgICAgICAgIDxYIGNsYXNzTmFtZT1cInctNCBoLTRcIiAvPlxuICAgICAgICA8L0ljb25CdXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwib3ZlcmZsb3cteS1hdXRvIHAtMyBzcGFjZS15LTNcIj5cbiAgICAgICAgPGRsIGNsYXNzTmFtZT1cImdyaWQgZ3JpZC1jb2xzLVthdXRvXzFmcl0gZ2FwLXgtMyBnYXAteS0xLjUgdGV4dC1zbVwiPlxuICAgICAgICAgIDxkdCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktOTAwXCI+UmVzb3VyY2U8L2R0PlxuICAgICAgICAgIDxkZCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktMTAwMCBmb250LW1vbm9cIj57c3Bhbi5yZXNvdXJjZX08L2RkPlxuICAgICAgICAgIDxkdCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktOTAwXCI+RHVyYXRpb248L2R0PlxuICAgICAgICAgIDxkZCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktMTAwMCB0YWJ1bGFyLW51bXMgZm9udC1tb25vXCI+XG4gICAgICAgICAgICB7Zm9ybWF0RHVyYXRpb24oZHVyYXRpb25Ncyl9XG4gICAgICAgICAgPC9kZD5cbiAgICAgICAgICA8ZHQgY2xhc3NOYW1lPVwidGV4dC1ncmF5LTkwMFwiPk9mZnNldDwvZHQ+XG4gICAgICAgICAgPGRkIGNsYXNzTmFtZT1cInRleHQtZ3JheS0xMDAwIHRhYnVsYXItbnVtcyBmb250LW1vbm9cIj5cbiAgICAgICAgICAgICt7Zm9ybWF0RHVyYXRpb24ob2Zmc2V0TXMpfVxuICAgICAgICAgIDwvZGQ+XG4gICAgICAgICAgPGR0IGNsYXNzTmFtZT1cInRleHQtZ3JheS05MDBcIj5TdGF0dXM8L2R0PlxuICAgICAgICAgIDxkZCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktMTAwMCBmb250LW1vbm9cIj5cbiAgICAgICAgICAgIHtzcGFuLnN0YXR1cy5jb2RlID09PSAyID8gJ0Vycm9yJyA6ICdPSyd9XG4gICAgICAgICAgPC9kZD5cbiAgICAgICAgPC9kbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvYXNpZGU+XG4gICk7XG59XG4iXX0=
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/components/new-trace-viewer/util/constants.ts"],"names":[],"mappings":""}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbmV3LXRyYWNlLXZpZXdlci91dGlsL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiIl19
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { X } from 'lucide-react';
|
|
4
|
-
import type { ReactNode } from 'react';
|
|
5
|
-
import type { Span } from '../trace-viewer/types';
|
|
6
|
-
import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
|
|
7
|
-
import { IconButton } from '../ui/icon-button';
|
|
8
|
-
import { getSpanDurationMs } from './utils';
|
|
9
|
-
|
|
10
|
-
interface DetailPanelProps {
|
|
11
|
-
span: Span;
|
|
12
|
-
rootStart: number;
|
|
13
|
-
onClose: () => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function DetailPanel({
|
|
17
|
-
span,
|
|
18
|
-
rootStart,
|
|
19
|
-
onClose,
|
|
20
|
-
}: DetailPanelProps): ReactNode {
|
|
21
|
-
const startMs = getHighResInMs(span.startTime);
|
|
22
|
-
const durationMs = getSpanDurationMs(span);
|
|
23
|
-
const offsetMs = startMs - rootStart;
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<aside className="grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200">
|
|
27
|
-
<div className="flex items-center justify-between px-3 border-b border-gray-alpha-400">
|
|
28
|
-
<span className="text-sm font-medium text-gray-1000 truncate">
|
|
29
|
-
{span.name}
|
|
30
|
-
</span>
|
|
31
|
-
<IconButton aria-label="Close span details" onClick={onClose}>
|
|
32
|
-
<X className="w-4 h-4" />
|
|
33
|
-
</IconButton>
|
|
34
|
-
</div>
|
|
35
|
-
<div className="overflow-y-auto p-3 space-y-3">
|
|
36
|
-
<dl className="grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-sm">
|
|
37
|
-
<dt className="text-gray-900">Resource</dt>
|
|
38
|
-
<dd className="text-gray-1000 font-mono">{span.resource}</dd>
|
|
39
|
-
<dt className="text-gray-900">Duration</dt>
|
|
40
|
-
<dd className="text-gray-1000 tabular-nums font-mono">
|
|
41
|
-
{formatDuration(durationMs)}
|
|
42
|
-
</dd>
|
|
43
|
-
<dt className="text-gray-900">Offset</dt>
|
|
44
|
-
<dd className="text-gray-1000 tabular-nums font-mono">
|
|
45
|
-
+{formatDuration(offsetMs)}
|
|
46
|
-
</dd>
|
|
47
|
-
<dt className="text-gray-900">Status</dt>
|
|
48
|
-
<dd className="text-gray-1000 font-mono">
|
|
49
|
-
{span.status.code === 2 ? 'Error' : 'OK'}
|
|
50
|
-
</dd>
|
|
51
|
-
</dl>
|
|
52
|
-
</div>
|
|
53
|
-
</aside>
|
|
54
|
-
);
|
|
55
|
-
}
|
|
File without changes
|