From 42688468ddbb768cc672d9a81e002133b5e17343 Mon Sep 17 00:00:00 2001
From: Jonas Kruckenberg <118265418+CrabNejonas@users.noreply.github.com>
Date: Mon, 18 Dec 2023 11:40:40 +0100
Subject: [PATCH 1/6] feat: add span details numbers
---
.../src/components/span/span-detail-trace.tsx | 77 ++++++++++++-------
web-client/src/lib/connection/monitor.ts | 4 +-
web-client/src/lib/formatters.ts | 10 +++
web-client/src/lib/span/normalize-spans.ts | 27 ++++---
web-client/src/lib/span/update-spans.ts | 4 +-
5 files changed, 79 insertions(+), 43 deletions(-)
diff --git a/web-client/src/components/span/span-detail-trace.tsx b/web-client/src/components/span/span-detail-trace.tsx
index 6a313b69..d09c5f70 100644
--- a/web-client/src/components/span/span-detail-trace.tsx
+++ b/web-client/src/components/span/span-detail-trace.tsx
@@ -4,6 +4,8 @@ import {
computeWaterfallStyle,
computeSlices,
} from "~/lib/span/normalize-spans";
+import { Popover } from "@kobalte/core";
+import {getDetailedTime} from "~/lib/formatters.ts";
export function SpanDetailTrace(props: {
span: UiSpan;
@@ -15,33 +17,54 @@ export function SpanDetailTrace(props: {
};
}) {
return (
-
- {props.span.name} |
-
-
-
-
- {/* Slices is "time slices" as in multiple entry points to a given span */}
-
- {(slice) => (
-
- )}
-
+
+ {props.span.name} |
+
+
+
+
+ {/* Slices is "time slices" as in multiple entry points to a given span */}
+
+ {(slice) => (
+
+
+
+
+
+
+
+ time: {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms ({slice.busy.toFixed(3)}% of
+ total)
+
+
+ on thread: {slice.threadID}
+
+
+ entered: {getDetailedTime(new Date(slice.entered / 1e6))}
+
+
+ exited: {getDetailedTime(new Date(slice.exited / 1e6))}
+
+
+
+
+ )}
+
+
-
- |
-
+ |
+ {props.span.time.toFixed(2)}ms |
+
);
}
diff --git a/web-client/src/lib/connection/monitor.ts b/web-client/src/lib/connection/monitor.ts
index 8ff15954..aae83402 100644
--- a/web-client/src/lib/connection/monitor.ts
+++ b/web-client/src/lib/connection/monitor.ts
@@ -15,8 +15,8 @@ export type Span = {
metadataId: bigint;
fields: Field[];
createdAt: number;
- enters: number[];
- exits: number[];
+ enters: { timestamp: number, threadID: number }[];
+ exits: { timestamp: number, threadID: number }[];
closedAt: number;
duration: number;
};
diff --git a/web-client/src/lib/formatters.ts b/web-client/src/lib/formatters.ts
index 9a32d53f..618934cf 100644
--- a/web-client/src/lib/formatters.ts
+++ b/web-client/src/lib/formatters.ts
@@ -36,3 +36,13 @@ export function getTime(date: Date) {
second: "2-digit",
}).format(date);
}
+
+export function getDetailedTime(date: Date) {
+ return Intl.DateTimeFormat('en', {
+ hour: "2-digit",
+ minute: "2-digit",
+ hour12: false,
+ second: "2-digit",
+ fractionalSecondDigits: 3
+ }).format(date);
+}
diff --git a/web-client/src/lib/span/normalize-spans.ts b/web-client/src/lib/span/normalize-spans.ts
index 3ae7ff52..e3138ffe 100644
--- a/web-client/src/lib/span/normalize-spans.ts
+++ b/web-client/src/lib/span/normalize-spans.ts
@@ -54,20 +54,23 @@ export function computeWaterfallStyle(
}
export function computeSlices(span: Span) {
- const allExits = span.exits.reduce((acc, e) => acc + e, 0);
- const allEnters = span.enters.reduce((acc, e) => acc + e, 0);
+ const allExits = span.exits.reduce((acc, e) => acc + e.timestamp, 0);
+ const allEnters = span.enters.reduce((acc, e) => acc + e.timestamp, 0);
- const slices = span.enters.map((enter, i) => {
- const width = scaleToMax([span.exits[i] - enter], allExits - allEnters)[0];
- const offset = scaleNumbers([enter], span.createdAt, span.closedAt)[0];
+ return span.enters.map((entered, i) => {
+ const exited = span.exits[i].timestamp;
+
+ const width = scaleToMax([exited - entered.timestamp], allExits - allEnters)[0];
+ const offset = scaleNumbers([entered.timestamp], span.createdAt, span.closedAt)[0];
const marginLeft = offset - (offset * width) / 100;
+
return {
+ entered: entered.timestamp,
+ exited,
+ busy: width,
+ threadID: entered.threadID,
width,
- marginLeft,
- };
- });
-
- return slices.map(
- (slice) => `width:${slice.width}%;margin-left:${slice.marginLeft}%;`
- );
+ marginLeft
+ }
+ })
}
diff --git a/web-client/src/lib/span/update-spans.ts b/web-client/src/lib/span/update-spans.ts
index 97d5fbe5..74355771 100644
--- a/web-client/src/lib/span/update-spans.ts
+++ b/web-client/src/lib/span/update-spans.ts
@@ -31,7 +31,7 @@ export function updatedSpans(currentSpans: Span[], spanEvents: SpanEvent[]) {
? convertTimestampToNanoseconds(event.event.enterSpan.at)
: -1;
if (span) {
- span.enters.push(enteredAt);
+ span.enters.push({ timestamp: enteredAt, threadID: Number(event.event.enterSpan.threadId) });
}
break;
@@ -43,7 +43,7 @@ export function updatedSpans(currentSpans: Span[], spanEvents: SpanEvent[]) {
? convertTimestampToNanoseconds(event.event.exitSpan.at)
: -1;
if (span) {
- span.exits.push(exitedAt);
+ span.exits.push({ timestamp: exitedAt, threadID: Number(event.event.exitSpan.threadId) });
}
break;
}
From 5bc273dce8c5752f2c06589a27c9115632fa024c Mon Sep 17 00:00:00 2001
From: Jonas Kruckenberg <118265418+CrabNejonas@users.noreply.github.com>
Date: Mon, 18 Dec 2023 12:04:37 +0100
Subject: [PATCH 2/6] format
---
.../src/components/span/span-detail-trace.tsx | 103 +++++++++---------
web-client/src/lib/connection/monitor.ts | 4 +-
web-client/src/lib/formatters.ts | 4 +-
web-client/src/lib/span/normalize-spans.ts | 18 ++-
web-client/src/lib/span/update-spans.ts | 10 +-
5 files changed, 78 insertions(+), 61 deletions(-)
diff --git a/web-client/src/components/span/span-detail-trace.tsx b/web-client/src/components/span/span-detail-trace.tsx
index d09c5f70..5b546681 100644
--- a/web-client/src/components/span/span-detail-trace.tsx
+++ b/web-client/src/components/span/span-detail-trace.tsx
@@ -5,7 +5,7 @@ import {
computeSlices,
} from "~/lib/span/normalize-spans";
import { Popover } from "@kobalte/core";
-import {getDetailedTime} from "~/lib/formatters.ts";
+import { getDetailedTime } from "~/lib/formatters.ts";
export function SpanDetailTrace(props: {
span: UiSpan;
@@ -17,54 +17,59 @@ export function SpanDetailTrace(props: {
};
}) {
return (
-
- {props.span.name} |
-
-
-
-
- {/* Slices is "time slices" as in multiple entry points to a given span */}
-
- {(slice) => (
-
-
-
-
-
-
-
- time: {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms ({slice.busy.toFixed(3)}% of
- total)
-
-
- on thread: {slice.threadID}
-
-
- entered: {getDetailedTime(new Date(slice.entered / 1e6))}
-
-
- exited: {getDetailedTime(new Date(slice.exited / 1e6))}
-
-
-
-
- )}
-
-
+
+ {props.span.name} |
+
+
+
+
+ {/* Slices is "time slices" as in multiple entry points to a given span */}
+
+ {(slice) => (
+
+
+
+
+
+
+ time:{" "}
+ {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms
+
+ on thread: {slice.threadID}
+
+ entered:{" "}
+ {getDetailedTime(new Date(slice.entered / 1e6))}
+
+
+ exited: {getDetailedTime(new Date(slice.exited / 1e6))}
+
+
+
+
+ )}
+
- |
- {props.span.time.toFixed(2)}ms |
-
+
+ |
+ {props.span.time.toFixed(2)}ms |
+
);
}
diff --git a/web-client/src/lib/connection/monitor.ts b/web-client/src/lib/connection/monitor.ts
index aae83402..dde12723 100644
--- a/web-client/src/lib/connection/monitor.ts
+++ b/web-client/src/lib/connection/monitor.ts
@@ -15,8 +15,8 @@ export type Span = {
metadataId: bigint;
fields: Field[];
createdAt: number;
- enters: { timestamp: number, threadID: number }[];
- exits: { timestamp: number, threadID: number }[];
+ enters: { timestamp: number; threadID: number }[];
+ exits: { timestamp: number; threadID: number }[];
closedAt: number;
duration: number;
};
diff --git a/web-client/src/lib/formatters.ts b/web-client/src/lib/formatters.ts
index 618934cf..bd3dac5f 100644
--- a/web-client/src/lib/formatters.ts
+++ b/web-client/src/lib/formatters.ts
@@ -38,11 +38,11 @@ export function getTime(date: Date) {
}
export function getDetailedTime(date: Date) {
- return Intl.DateTimeFormat('en', {
+ return Intl.DateTimeFormat("en", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
second: "2-digit",
- fractionalSecondDigits: 3
+ fractionalSecondDigits: 3,
}).format(date);
}
diff --git a/web-client/src/lib/span/normalize-spans.ts b/web-client/src/lib/span/normalize-spans.ts
index e3138ffe..52c6c413 100644
--- a/web-client/src/lib/span/normalize-spans.ts
+++ b/web-client/src/lib/span/normalize-spans.ts
@@ -60,17 +60,23 @@ export function computeSlices(span: Span) {
return span.enters.map((entered, i) => {
const exited = span.exits[i].timestamp;
- const width = scaleToMax([exited - entered.timestamp], allExits - allEnters)[0];
- const offset = scaleNumbers([entered.timestamp], span.createdAt, span.closedAt)[0];
+ const width = scaleToMax(
+ [exited - entered.timestamp],
+ allExits - allEnters
+ )[0];
+ const offset = scaleNumbers(
+ [entered.timestamp],
+ span.createdAt,
+ span.closedAt
+ )[0];
const marginLeft = offset - (offset * width) / 100;
return {
entered: entered.timestamp,
exited,
- busy: width,
threadID: entered.threadID,
width,
- marginLeft
- }
- })
+ marginLeft,
+ };
+ });
}
diff --git a/web-client/src/lib/span/update-spans.ts b/web-client/src/lib/span/update-spans.ts
index 74355771..368e66c2 100644
--- a/web-client/src/lib/span/update-spans.ts
+++ b/web-client/src/lib/span/update-spans.ts
@@ -31,7 +31,10 @@ export function updatedSpans(currentSpans: Span[], spanEvents: SpanEvent[]) {
? convertTimestampToNanoseconds(event.event.enterSpan.at)
: -1;
if (span) {
- span.enters.push({ timestamp: enteredAt, threadID: Number(event.event.enterSpan.threadId) });
+ span.enters.push({
+ timestamp: enteredAt,
+ threadID: Number(event.event.enterSpan.threadId),
+ });
}
break;
@@ -43,7 +46,10 @@ export function updatedSpans(currentSpans: Span[], spanEvents: SpanEvent[]) {
? convertTimestampToNanoseconds(event.event.exitSpan.at)
: -1;
if (span) {
- span.exits.push({ timestamp: exitedAt, threadID: Number(event.event.exitSpan.threadId) });
+ span.exits.push({
+ timestamp: exitedAt,
+ threadID: Number(event.event.exitSpan.threadId),
+ });
}
break;
}
From cb1ddf12969919ae22dc4303018b395e6fcb01b5 Mon Sep 17 00:00:00 2001
From: Jonas Kruckenberg <118265418+CrabNejonas@users.noreply.github.com>
Date: Tue, 19 Dec 2023 16:01:38 +0100
Subject: [PATCH 3/6] Update span-detail-trace.tsx
---
.../src/components/span/span-detail-trace.tsx | 52 ++++++++++++-------
1 file changed, 34 insertions(+), 18 deletions(-)
diff --git a/web-client/src/components/span/span-detail-trace.tsx b/web-client/src/components/span/span-detail-trace.tsx
index 5b546681..afdcf16a 100644
--- a/web-client/src/components/span/span-detail-trace.tsx
+++ b/web-client/src/components/span/span-detail-trace.tsx
@@ -16,8 +16,15 @@ export function SpanDetailTrace(props: {
longest: number;
};
}) {
+ const busy = () => props.span.original.enters.reduce((acc, enter, i) => {
+ const exit = props.span.original.exits[i];
+
+ return acc + (exit.timestamp - enter.timestamp)
+ }, 0)
+
return (
-
+
+
{props.span.name} |
@@ -37,7 +44,7 @@ export function SpanDetailTrace(props: {
{(slice) => (
-
-
- time:{" "}
- {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms
-
- on thread: {slice.threadID}
-
- entered:{" "}
- {getDetailedTime(new Date(slice.entered / 1e6))}
-
-
- exited: {getDetailedTime(new Date(slice.exited / 1e6))}
-
+
+ Time
+ {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms
+ Thread
+ {slice.threadID}
+ Start
+ {getDetailedTime(new Date(slice.entered / 1e6))}
+ End
+ {getDetailedTime(new Date(slice.exited / 1e6))}
@@ -70,6 +73,19 @@ export function SpanDetailTrace(props: {
|
{props.span.time.toFixed(2)}ms |
-
+
+
+
+
+ {props.span.name}
+ Busy
+ {(busy() / 1e6).toFixed(3)}ms
+ Idle
+ {(props.span.time - busy() / 1e6).toFixed(3)}ms
+
+
+
);
}
From 814ed55a10e278d315b55aa7087f16e2bfc39723 Mon Sep 17 00:00:00 2001
From: Jonas Kruckenberg <118265418+CrabNejonas@users.noreply.github.com>
Date: Tue, 19 Dec 2023 16:03:38 +0100
Subject: [PATCH 4/6] format
---
.../src/components/span/span-detail-trace.tsx | 146 ++++++++++--------
1 file changed, 80 insertions(+), 66 deletions(-)
diff --git a/web-client/src/components/span/span-detail-trace.tsx b/web-client/src/components/span/span-detail-trace.tsx
index afdcf16a..923c0184 100644
--- a/web-client/src/components/span/span-detail-trace.tsx
+++ b/web-client/src/components/span/span-detail-trace.tsx
@@ -16,76 +16,90 @@ export function SpanDetailTrace(props: {
longest: number;
};
}) {
- const busy = () => props.span.original.enters.reduce((acc, enter, i) => {
- const exit = props.span.original.exits[i];
+ const busy = () =>
+ props.span.original.enters.reduce((acc, enter, i) => {
+ const exit = props.span.original.exits[i];
- return acc + (exit.timestamp - enter.timestamp)
- }, 0)
+ return acc + (exit.timestamp - enter.timestamp);
+ }, 0);
return (
-
-
- {props.span.name} |
-
-
-
-
- {/* Slices is "time slices" as in multiple entry points to a given span */}
-
- {(slice) => (
-
-
-
-
-
- Time
- {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms
- Thread
- {slice.threadID}
- Start
- {getDetailedTime(new Date(slice.entered / 1e6))}
- End
- {getDetailedTime(new Date(slice.exited / 1e6))}
-
-
-
+
+
+ {props.span.name} |
+
+
+
+
+ >
+ {/* Slices is "time slices" as in multiple entry points to a given span */}
+
+ {(slice) => (
+
+
+
+
+
+ Time
+
+ {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms
+
+ Thread
+ {slice.threadID}
+ Start
+
+ {getDetailedTime(new Date(slice.entered / 1e6))}
+
+ End
+
+ {getDetailedTime(new Date(slice.exited / 1e6))}
+
+
+
+
+ )}
+
+
-
- |
- {props.span.time.toFixed(2)}ms |
-
-
-
-
- {props.span.name}
- Busy
- {(busy() / 1e6).toFixed(3)}ms
- Idle
- {(props.span.time - busy() / 1e6).toFixed(3)}ms
-
-
-
+ |
+ {props.span.time.toFixed(2)}ms |
+
+
+
+
+ {props.span.name}
+
+ Busy
+ {(busy() / 1e6).toFixed(3)}ms
+ Idle
+ {(props.span.time - busy() / 1e6).toFixed(3)}ms
+
+
+
);
}
From 3e53722c6cb47643e31aa48a8b5e9df9cd2b4b58 Mon Sep 17 00:00:00 2001
From: Johann Derdak
Date: Tue, 19 Dec 2023 16:56:00 +0100
Subject: [PATCH 5/6] fix: lint warnings and improve readability
---
.../src/components/span/span-detail-trace.tsx | 115 ++++++++++--------
1 file changed, 66 insertions(+), 49 deletions(-)
diff --git a/web-client/src/components/span/span-detail-trace.tsx b/web-client/src/components/span/span-detail-trace.tsx
index 923c0184..c7ab83da 100644
--- a/web-client/src/components/span/span-detail-trace.tsx
+++ b/web-client/src/components/span/span-detail-trace.tsx
@@ -1,5 +1,6 @@
import { For } from "solid-js";
import { UiSpan } from "~/lib/span/format-spans-for-ui";
+import { Span } from "~/lib/connection/monitor";
import {
computeWaterfallStyle,
computeSlices,
@@ -16,13 +17,6 @@ export function SpanDetailTrace(props: {
longest: number;
};
}) {
- const busy = () =>
- props.span.original.enters.reduce((acc, enter, i) => {
- const exit = props.span.original.exits[i];
-
- return acc + (exit.timestamp - enter.timestamp);
- }, 0);
-
return (
{/* Slices is "time slices" as in multiple entry points to a given span */}
- {(slice) => (
-
-
-
-
-
- Time
-
- {((slice.exited - slice.entered) / 1e6).toFixed(3)}ms
-
- Thread
- {slice.threadID}
- Start
-
- {getDetailedTime(new Date(slice.entered / 1e6))}
-
- End
-
- {getDetailedTime(new Date(slice.exited / 1e6))}
-
-
-
-
- )}
+ {(slice) => }
{props.span.time.toFixed(2)}ms |
+
+
+
+
+ );
+}
+
+function SpanDetailPopOverContent(props: { span: UiSpan }) {
+ const busy = (span: Span) =>
+ span.enters.reduce((acc, enter, i) => {
+ const exit = span.exits[i];
+
+ return acc + (exit.timestamp - enter.timestamp);
+ }, 0);
+
+ return (
+
+
+ {props.span.name}
+
+ Busy
+ {(busy(props.span.original) / 1e6).toFixed(3)}ms
+ Idle
+
+ {(props.span.time - busy(props.span.original) / 1e6).toFixed(3)}ms
+
+
+ );
+}
+
+function SpanDetailSlice(props: {
+ slice: {
+ entered: number;
+ exited: number;
+ threadID: number;
+ width: number;
+ marginLeft: number;
+ };
+}) {
+ return (
+
+
- {props.span.name}
-
- Busy
- {(busy() / 1e6).toFixed(3)}ms
- Idle
- {(props.span.time - busy() / 1e6).toFixed(3)}ms
+ Time
+
+ {((props.slice.exited - props.slice.entered) / 1e6).toFixed(3)}ms
+
+ Thread
+ {props.slice.threadID}
+ Start
+ {getDetailedTime(new Date(props.slice.entered / 1e6))}
+ End
+ {getDetailedTime(new Date(props.slice.exited / 1e6))}
From 62a90ec62bb9c4eff8d59e4a5d514f52e9a09ee0 Mon Sep 17 00:00:00 2001
From: Johann Derdak
Date: Tue, 19 Dec 2023 20:46:31 +0100
Subject: [PATCH 6/6] fix: use table to represent tabular span data
---
.../src/components/span/span-detail-trace.tsx | 68 ++++++++++++-------
1 file changed, 45 insertions(+), 23 deletions(-)
diff --git a/web-client/src/components/span/span-detail-trace.tsx b/web-client/src/components/span/span-detail-trace.tsx
index c7ab83da..e83b4fa6 100644
--- a/web-client/src/components/span/span-detail-trace.tsx
+++ b/web-client/src/components/span/span-detail-trace.tsx
@@ -1,4 +1,4 @@
-import { For } from "solid-js";
+import { For, JSXElement, Show } from "solid-js";
import { UiSpan } from "~/lib/span/format-spans-for-ui";
import { Span } from "~/lib/connection/monitor";
import {
@@ -63,18 +63,18 @@ function SpanDetailPopOverContent(props: { span: UiSpan }) {
return (
-
- {props.span.name}
-
- Busy
- {(busy(props.span.original) / 1e6).toFixed(3)}ms
- Idle
-
- {(props.span.time - busy(props.span.original) / 1e6).toFixed(3)}ms
-
+
+
+
+ {(busy(props.span.original) / 1e6).toFixed(3)}ms
+
+
+ {(props.span.time - busy(props.span.original) / 1e6).toFixed(3)}ms
+
+
);
}
@@ -99,24 +99,46 @@ function SpanDetailSlice(props: {
/>
-
- Time
-
- {((props.slice.exited - props.slice.entered) / 1e6).toFixed(3)}ms
-
- Thread
- {props.slice.threadID}
- Start
- {getDetailedTime(new Date(props.slice.entered / 1e6))}
- End
- {getDetailedTime(new Date(props.slice.exited / 1e6))}
+
+
+ {((props.slice.exited - props.slice.entered) / 1e6).toFixed(3)}
+ ms
+
+ {props.slice.threadID}
+
+ {getDetailedTime(new Date(props.slice.entered / 1e6))}
+
+
+ {getDetailedTime(new Date(props.slice.exited / 1e6))}
+
+
);
}
+
+function ToolTipContent(props: { children: JSXElement }) {
+ return (
+ <>
+
+
+ >
+ );
+}
+
+function ToolTipRow(props: { title: string; children?: JSXElement }) {
+ return (
+
+ {props.title} |
+
+ {props.children} |
+
+
+ );
+}