Skip to content

Commit

Permalink
feat(spans-waterfall): add event spans
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog-crabnebula committed Nov 16, 2023
1 parent 06ec98f commit 8980e29
Show file tree
Hide file tree
Showing 13 changed files with 386 additions and 141 deletions.
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion examples/tauri/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@

use std::time::Duration;

use tauri::Manager;

#[tauri::command]
async fn test1(url: String, timeout_seconds: u64) -> String {
async fn test1(app: tauri::AppHandle, url: String, timeout_seconds: u64) -> String {
tracing::trace!("test trace event");
tracing::debug!("test debug event");
tracing::info!("test info event");
tracing::warn!("test warn event");
tracing::error!("test error event");

app.emit_all("test1-event", "sleeping").unwrap();

tokio::time::sleep(Duration::from_secs(timeout_seconds)).await;

app.emit_all("test1-event", "making get request").unwrap();

reqwest::get(url)
.await
.expect("valid response")
Expand Down
80 changes: 80 additions & 0 deletions web-client/src/components/span/EventSpanDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { For, Show } from "solid-js";
import { useMonitor } from "~/lib/connection/monitor";
import { formatSpansForUi } from "~/lib/span/formatSpansForUi";
import { useSearchParams } from "@solidjs/router";
import { processFieldValue } from "~/lib/span/processFieldValue";
import { recursivelyFindSpanById } from "~/lib/span/recursivelyFindSpanById";
import { getEventPayload } from "~/lib/span/getEventPayload";

export function EventSpanDetail() {
const [searchParams] = useSearchParams();
const { monitorData } = useMonitor();
const spanId = () => BigInt(searchParams.span);
const span = () =>
formatSpansForUi({
spans: [recursivelyFindSpanById(monitorData.spans, spanId())!],
metadata: monitorData.metadata,
})[0];
console.log(span());

const payload = () =>
getEventPayload({
metadata: monitorData.metadata,
rootSpan: recursivelyFindSpanById(monitorData.spans, spanId())!,
})("window::emit")?.fields.map((f) => processFieldValue(f.payload))[0];

return (
<div class="h-full overflow-auto grid gap-4 content-start border-l border-gray-800">
<div class="pt-4 px-4">
<h2 class="text-2xl">{span?.name ?? "-"}</h2>
</div>
<table>
<tbody>
<For each={span().children ?? []}>
{(span) => {
return (
<tr class="even:bg-[#ffffff09] cursor-pointer hover:bg-[#ffffff05] even:hover:bg-[#ffffff10]">
<td class="py-1 px-4">{span.name}</td>
<td class="py-1 px-4 relative w-[60%]">
<div class="relative w-[90%]">
<div class="bg-gray-800 w-full absolute rounded-sm h-2" />
<div class="relative h-2" style={span.waterfall}>
{/* Slices is "time slices" as in multiple entry points to a given span */}
<For each={span.slices}>
{(slice) => (
<div
class="absolute bg-teal-500 top-0 left-0 h-full"
style={slice}
/>
)}
</For>
</div>
</div>
</td>
</tr>
);
}}
</For>
</tbody>
</table>
<div class="grid gap-2">
<h2 class="text-xl p-4">Payload</h2>
<table>
<tbody>
<Show when={payload()}>
{(payload) => {
return (
<p class="py-1 px-4">
{typeof payload() === "object"
? JSON.stringify(payload())
: String(payload())}
</p>
);
}}
</Show>
</tbody>
</table>
</div>
</div>
);
}
130 changes: 130 additions & 0 deletions web-client/src/components/span/IpcSpanDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { For, createResource, Show } from "solid-js";
import { useMonitor } from "~/lib/connection/monitor";
import { formatSpansForUi } from "~/lib/span/formatSpansForUi";
import { getIpcRequestValues } from "~/lib/span/getIpcRequestValue";
import { getHighlightedCode } from "~/lib/sources/code-highlight";
import { useSearchParams } from "@solidjs/router";
import { processFieldValue } from "~/lib/span/processFieldValue";

export function IpcSpanDetail() {
const [searchParams] = useSearchParams();
const { monitorData } = useMonitor();
const spanId = () => BigInt(searchParams.span);
const span = () =>
formatSpansForUi({
spans: monitorData.spans.filter((s) => s.id === spanId()),
metadata: monitorData.metadata,
})[0];

const responseCode = () => {
const field = getIpcRequestValues({
metadata: monitorData.metadata,
rootSpan: monitorData.spans.find((s) => s.id === spanId())!,
})("ipc::request::response")?.fields[0]?.response;
return field ? processFieldValue(field) : null;
};

const args = () =>
getIpcRequestValues({
metadata: monitorData.metadata,
rootSpan: monitorData.spans.find((s) => s.id === spanId())!,
})("ipc::request")!.fields.map((f) => processFieldValue(f.request));

const [responseHtml] = createResource(
() => [responseCode()] as const,
async ([code]) => {
return code === null
? null
: (await getHighlightedCode({ lang: "rust" }))(code).replace(
/\\n/gim, // Turn escaped newlines into actual newlines
"\n"
);
}
);

return (
<div class="h-full overflow-auto grid gap-4 content-start border-l border-gray-800">
<div class="pt-4 px-4">
<h2 class="text-2xl">{span?.name ?? "-"}</h2>
</div>
<table>
<tbody>
<For each={span().children ?? []}>
{(span) => {
return (
<tr class="even:bg-[#ffffff09] cursor-pointer hover:bg-[#ffffff05] even:hover:bg-[#ffffff10]">
<td class="py-1 px-4">{span.name}</td>
<td class="py-1 px-4 relative w-[60%]">
<div class="relative w-[90%]">
<div class="bg-gray-800 w-full absolute rounded-sm h-2" />
<div class="relative h-2" style={span.waterfall}>
{/* Slices is "time slices" as in multiple entry points to a given span */}
<For each={span.slices}>
{(slice) => (
<div
class="absolute bg-teal-500 top-0 left-0 h-full"
style={slice}
/>
)}
</For>
</div>
</div>
</td>
</tr>
);
}}
</For>
</tbody>
</table>
<div class="grid gap-2">
<h2 class="text-xl p-4">Inputs</h2>
<table>
<tbody>
<For each={args()}>
{(arg) => {
return (
<For each={Object.entries(JSON.parse(arg))}>
{([k, v]) => (
<Show
when={
![
"cmd",
"callback",
"error",
"__tauriModule",
].includes(k)
}
>
<tr class="even:bg-[#ffffff09]">
<td class="py-1 px-4 font-bold">{k}</td>
<td class="py-1 px-4">
{typeof v === "object"
? JSON.stringify(v)
: String(v)}
</td>
</tr>
</Show>
)}
</For>
);
}}
</For>
</tbody>
</table>
</div>
<Show when={responseHtml()}>
{(html) => (
<div class="grid gap-2">
<h2 class="text-xl p-4">Response</h2>
<pre class="bg-black rounded max-w-full overflow-auto">
<code
// eslint-disable-next-line solid/no-innerhtml
innerHTML={html()}
/>
</pre>
</div>
)}
</Show>
</div>
);
}
Loading

0 comments on commit 8980e29

Please sign in to comment.