Skip to content

Commit

Permalink
Consolidate rows
Browse files Browse the repository at this point in the history
  • Loading branch information
benbrandt committed Oct 27, 2023
1 parent 01289c1 commit b66637b
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 87 deletions.
35 changes: 0 additions & 35 deletions log-viewer/src/lib/components/timeline/LogDurations.svelte

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
tags: ['autodocs'],
args: {
span,
runStart: range.from,
runEnd: range.to
range
}
};
</script>
Expand Down
21 changes: 7 additions & 14 deletions log-viewer/src/lib/components/timeline/SpanDuration.svelte
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
<script lang="ts">
import { differenceInMilliseconds } from 'date-fns';
import { type SpanEntry, isSpan } from '../../log';
import { type SpanEntry, type TimeRange, isSpan } from '../../log';
/**
* A Span or TaskSpan to show the duration of
*/
export let span: SpanEntry;
/**
* The start of the entire run of the logger
* The duration of the entire run of the logger
*/
export let runStart: Date;
/**
* The end of the entire run of the logger
*/
export let runEnd: Date;
export let range: TimeRange;
$: spanStart = new Date(span.start_timestamp);
$: spanOffset = differenceInMilliseconds(spanStart, runStart);
$: spanOffset = differenceInMilliseconds(spanStart, range.from);
$: spanLength = differenceInMilliseconds(new Date(span.end_timestamp), spanStart);
$: runLength = differenceInMilliseconds(runEnd, runStart);
$: runLength = differenceInMilliseconds(range.to, range.from);
// Filter out LogEntry's, only show the Span/TaskSpan in the tree
$: childSpans = span.logs.filter(isSpan);
Expand Down Expand Up @@ -49,16 +45,13 @@
This is a recursive component that builds itself up by creating the same component for sub-spans.
-->
<div class="h-8 w-full border-t py-0.5 last:border-b hover:bg-gray-50">
<div class="w-full pb-1">
<button
class="bg-accent-400 py-1 text-right text-xs font-extrabold text-gray-950 shadow outline-none ring-1 ring-gray-950/20 hover:bg-accent-500"
class="bg-accent-400 py-0.5 text-right text-xs font-extrabold text-gray-950 shadow outline-none ring-1 ring-gray-950/20 hover:bg-accent-500"
style="margin-left: {Math.round((spanOffset / runLength) * 100)}%; width:{Math.round(
(spanLength / runLength) * 100
)}%;"
>
<span class="px-1">{renderDuration(spanLength)}</span>
</button>
</div>
{#each childSpans as span}
<svelte:self {span} {runStart} {runEnd} />
{/each}
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<script context="module" lang="ts">
import type { MetaProps } from '@storybook/addon-svelte-csf';
import { randomLogger } from '../../log.test_utils';
import LogDurations from './LogDurations.svelte';
import { randomDateRange, randomSpan } from '../../log.test_utils';
import SpanRow from './SpanRow.svelte';
const logger = randomLogger();
const range = randomDateRange();
const span = randomSpan(range);
export const meta: MetaProps = {
title: 'Timeline/Molecules/LogDurations',
component: LogDurations,
title: 'Timeline/Molecules/SpanRow',
component: SpanRow,
tags: ['autodocs'],
args: {
logs: logger.logs
span,
range
}
};
</script>
Expand All @@ -20,7 +22,7 @@
</script>

<Template let:args>
<LogDurations {...args} />
<SpanRow {...args} />
</Template>

<Story name="Base" />
39 changes: 39 additions & 0 deletions log-viewer/src/lib/components/timeline/SpanRow.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script lang="ts">
import type { SpanEntry, TimeRange } from '../../log';
import SpanDuration from './SpanDuration.svelte';
/**
* The Span to render in the tree.
*/
export let span: SpanEntry;
/**
* How deeply nested is this sub-tree?
*/
export let level: number = 0;
/**
* The duration of the entire run of the logger
*/
export let range: TimeRange;
</script>

<!--
@component
A tree-view of Spans/TaskSpans to show their names and nested structure.
This is a recursive component that builds itself up by creating sub-trees.
-->

<div class="group grid grid-cols-3 grid-rows-1 items-stretch border-b bg-gray-50">
<div class="col-span-1 grid items-stretch">
<button class="group grid w-full items-stretch text-left" style="padding-left: {level}em">
<span
class="grid items-center border-l border-r border-gray-300 bg-white px-2 text-sm group-hover:bg-gray-100"
>
<span>{span.name}</span>
</span>
</button>
</div>
<div class="col-span-2 bg-white px-2 group-hover:bg-gray-100">
<SpanDuration {span} {range} />
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
<script context="module" lang="ts">
import type { MetaProps } from '@storybook/addon-svelte-csf';
import { randomLogger } from '../../log.test_utils';
import { logRange } from '../../log';
import SpanTree from './SpanTree.svelte';
const logger = randomLogger();
const range = logRange(logger);
export const meta: MetaProps = {
title: 'Timeline/Atoms/SpanTree',
title: 'Timeline/Molecules/SpanTree',
component: SpanTree,
tags: ['autodocs'],
args: {
logs: logger.logs
logs: logger.logs,
range
}
};
</script>
Expand Down
22 changes: 9 additions & 13 deletions log-viewer/src/lib/components/timeline/SpanTree.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { type Entry, isSpan } from '../../log';
import { type Entry, type TimeRange, isSpan } from '../../log';
import SpanRow from './SpanRow.svelte';
/**
* The list of log entries to render in the tree.
Expand All @@ -9,6 +10,10 @@
* How deeply nested is this sub-tree?
*/
export let level: number = 0;
/**
* The duration of the entire run of the logger
*/
export let range: TimeRange;
// Filter out LogEntry's, only show the Span/TaskSpan in the tree
$: spans = logs.filter(isSpan);
Expand All @@ -22,19 +27,10 @@
-->
{#if spans.length}
<ul class:border-t={level === 0}>
{#each spans as log}
{#each spans as span}
<li>
<button
class="group h-8 w-full border-b bg-gray-50 text-left"
style="padding-left: {level}em"
>
<span
class="block border-l border-gray-300 bg-white px-2 py-1 text-sm group-hover:bg-gray-100"
>
{log.name}
</span>
</button>
<svelte:self logs={log.logs} level={level + 1} />
<SpanRow {span} {level} {range} />
<svelte:self logs={span.logs} level={level + 1} {range} />
</li>
{/each}
</ul>
Expand Down
12 changes: 4 additions & 8 deletions log-viewer/src/lib/components/timeline/Timeline.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
<script lang="ts">
import type { DebugLog } from '../../log';
import LogDurations from './LogDurations.svelte';
import { type DebugLog, logRange } from '../../log';
import SpanTree from './SpanTree.svelte';
/**
* The Debug Log you want to render
*/
export let log: DebugLog;
$: range = logRange(log);
</script>

<!--
@component
Timeline and Tree view of the given DebugLog
-->

<div class="grid grid-cols-3 grid-rows-1">
<div class="col-span-1">
<SpanTree logs={log.logs} />
</div>
<div class="col-span-2"><LogDurations logs={log.logs} /></div>
</div>
<SpanTree logs={log.logs} {range} />
7 changes: 1 addition & 6 deletions log-viewer/src/lib/log.test_utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { faker } from '@faker-js/faker';
import { compareAsc } from 'date-fns';
import type { Entry, LogEntry, Span, TaskSpan, JSONValue, DebugLog } from './log';

export interface TimeRange {
from: Date;
to: Date;
}
import type { Entry, LogEntry, Span, TaskSpan, JSONValue, DebugLog, TimeRange } from './log';

/**
* Produces a random time range, with optional time bounds
Expand Down
24 changes: 24 additions & 0 deletions log-viewer/src/lib/log.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { compareAsc } from 'date-fns';

export type JSONValue =
| string
| number
Expand Down Expand Up @@ -38,3 +40,25 @@ export function isLogEntry(entry: Entry): entry is LogEntry {
export function isSpan(entry: Entry): entry is SpanEntry {
return 'logs' in entry;
}

export interface TimeRange {
from: Date;
to: Date;
}

/**
* Calculate the first and last timestamp of a logger
*/
export function logRange(log: DebugLog): TimeRange | null {
const logTimes = log.logs.reduce<Date[]>((acc, i) => {
if ('timestamp' in i) acc.push(new Date(i.timestamp));
if ('start_timestamp' in i) acc.push(new Date(i.start_timestamp));
if ('end_timestamp' in i) acc.push(new Date(i.end_timestamp));
return acc;
}, []);
logTimes.sort(compareAsc);

const from = logTimes.at(0);
const to = logTimes.at(-1);
return from && to ? { from, to } : null;
}

0 comments on commit b66637b

Please sign in to comment.