Skip to content

Commit

Permalink
[testloop] Fix broken visualizer (#13033)
Browse files Browse the repository at this point in the history
The recent change in #13016 to
shift from index to identifier broke the testloop visualizer.

We now have the visualizer showing the identifier instead of just index.


![image](https://github.com/user-attachments/assets/9f062810-8737-4e15-a96d-65e1bf83a484)
  • Loading branch information
shreyan-gupta authored Mar 4, 2025
1 parent aeaac87 commit 47b0a0b
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 47 deletions.
6 changes: 4 additions & 2 deletions core/async/src/test_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ struct EventStartLogOutput {
current_index: usize,
/// See `EventEndLogOutput::total_events`.
total_events: usize,
/// The identifier of the event, usually the node_id.
identifier: String,
/// The Debug representation of the event payload.
current_event: String,
/// The current virtual time.
Expand Down Expand Up @@ -333,11 +335,11 @@ impl TestLoopV2 {

/// Processes the given event, by logging a line first and then finding a handler to run it.
fn process_event(&mut self, event: EventInHeap) {
let description = format!("({},{})", event.event.identifier, event.event.description);
let start_json = serde_json::to_string(&EventStartLogOutput {
current_index: event.id,
total_events: self.next_event_index,
current_event: description,
identifier: event.event.identifier,
current_event: event.event.description,
current_time_ms: event.due.whole_milliseconds() as u64,
})
.unwrap();
Expand Down
16 changes: 8 additions & 8 deletions tools/debug-ui/src/log_visualizer/LogVisualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const LogVisualizer = () => {
})}
</div>
{/* Render the column headers. */}
{layouts.columns.map((_, i) => {
{layouts.columns.map((col, i) => {
return (
<div
key={i}
Expand All @@ -82,7 +82,7 @@ export const LogVisualizer = () => {
left: layouts.getGridColumnXOffset(i),
width: layouts.getGridColumnWidth(i),
}}>
Node {i}
{col.identifier}
</div>
);
})}
Expand Down Expand Up @@ -157,17 +157,17 @@ export const LogVisualizer = () => {
className={
'attached-event' +
(event.id == selectedEventId ||
parent.id == selectedEventId
parent.id == selectedEventId
? ' selected'
: '')
}
style={{
left: layouts.getArrowColumnXOffset(
new ArrowColumn(parent.column, 'middle'),
new ArrowColumn(parent.columnNumber, 'middle'),
arrowGroupId
),
top:
layouts.getItemYOffset(parent.row) +
layouts.getItemYOffset(parent.rowNumber) +
layouts.sizes.itemHeight,
}}
onClick={(e) => {
Expand All @@ -187,9 +187,9 @@ export const LogVisualizer = () => {
key={`event ${event.id}`}
className={'event' + (event.id == selectedEventId ? ' selected' : '')}
style={{
left: layouts.getItemXOffset(event.column),
top: layouts.getItemYOffset(event.row),
width: layouts.getItemWidth(event.column),
left: layouts.getItemXOffset(event.columnNumber),
top: layouts.getItemYOffset(event.rowNumber),
width: layouts.getItemWidth(event.columnNumber),
height: layouts.sizes.itemHeight,
}}
onClick={(e) => {
Expand Down
26 changes: 13 additions & 13 deletions tools/debug-ui/src/log_visualizer/arrows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export type ArrowRowPosition = 'above' | 'inbound' | 'outbound';
export const ARROW_ROW_POSITIONS: ArrowRowPosition[] = ['above', 'inbound', 'outbound'];

export class ArrowRow {
constructor(public readonly gridRow: number, public readonly positioning: ArrowRowPosition) {}
constructor(public readonly gridRow: number, public readonly positioning: ArrowRowPosition) { }

// Gets a unique key for this ArrowRow that is larger if it's more
// vertically down.
Expand Down Expand Up @@ -120,7 +120,7 @@ export class ArrowColumn {
constructor(
public readonly gridColumn: number,
public readonly positioning: ArrowColumnPosition
) {}
) { }

get key(): number {
return this.gridColumn * 2 + (this.positioning == 'left' ? 0 : 1);
Expand Down Expand Up @@ -265,8 +265,8 @@ export function makeOutgoingArrowsForItem(
for (const targetId of targetIds) {
const child = items.get(targetId)!;
columnToMaxRow.set(
child.column,
Math.max(columnToMaxRow.get(child.column) ?? 0, child.row)
child.columnNumber,
Math.max(columnToMaxRow.get(child.columnNumber) ?? 0, child.rowNumber)
);
}
let minColumn = 100000,
Expand All @@ -279,30 +279,30 @@ export function makeOutgoingArrowsForItem(
const verticalParts = [] as ArrowPartVertical[];
// If we only have children to the same instance, then draw them in the
// first fashion (see comment at beginning of file).
if (minColumn == maxColumn && minColumn == item.column && attachmentId === null) {
horizontalParts.push(ArrowPartHorizontal.outOfItem(item.row, item.column));
if (minColumn == maxColumn && minColumn == item.columnNumber && attachmentId === null) {
horizontalParts.push(ArrowPartHorizontal.outOfItem(item.rowNumber, item.columnNumber));
verticalParts.push(
ArrowPartVertical.acrossRows(
new ArrowRow(item.row, 'outbound'),
new ArrowRow(columnToMaxRow.get(item.column)!, 'inbound'),
item.column
new ArrowRow(item.rowNumber, 'outbound'),
new ArrowRow(columnToMaxRow.get(item.columnNumber)!, 'inbound'),
item.columnNumber
)
);
} else {
// Otherwise we draw them in the second fashion.
const verticalOut = ArrowPartVertical.outOfItem(item.row, item.column);
const verticalOut = ArrowPartVertical.outOfItem(item.rowNumber, item.columnNumber);
verticalParts.push(verticalOut);
horizontalParts.push(
ArrowPartHorizontal.acrossColumns(
item.row + 1,
item.rowNumber + 1,
verticalOut.column.min(new ArrowColumn(minColumn, 'left')),
verticalOut.column.max(new ArrowColumn(maxColumn, 'left'))
)
);
for (const column of columnToMaxRow.keys()) {
verticalParts.push(
ArrowPartVertical.acrossRows(
new ArrowRow(item.row + 1, 'above'),
new ArrowRow(item.rowNumber + 1, 'above'),
new ArrowRow(columnToMaxRow.get(column)!, 'inbound'),
column
)
Expand All @@ -311,7 +311,7 @@ export function makeOutgoingArrowsForItem(
}
for (const targetId of targetIds) {
const child = items.get(targetId)!;
horizontalParts.push(ArrowPartHorizontal.intoItem(child.row, child.column));
horizontalParts.push(ArrowPartHorizontal.intoItem(child.rowNumber, child.columnNumber));
}
arrowGroups.push({
horizontalParts,
Expand Down
22 changes: 9 additions & 13 deletions tools/debug-ui/src/log_visualizer/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class EventItem {
// is zero; in a multi-instance test, this is the instance number.
// Emitted from the Rust side as part of the event dump (like "(0, Event)")
// and parsed here.
public readonly column: number;
public readonly identifier: string;
// The title we display for the event. Parsed from the event dump after
// extracting column number; this is usually the enum variant name.
public readonly title: string;
Expand All @@ -25,27 +25,21 @@ export class EventItem {
// for how this is derived.
public readonly parentId: number | null = null;

// The row of the event in the log visualizer. This is set during layout.
public row = 0;
// The row and column of the event in the log visualizer. This is set during layout.
public rowNumber = 0;
public columnNumber = 0;
// The children IDs of this event. Derived from parentId.
public readonly childIds: number[] = [];
// The log lines emitted by the Rust program while handling this event.
public readonly logRows: string[] = [];

constructor(id: number, parentId: number | null, time: number, eventDump: string) {
constructor(id: number, identifier: string, parentId: number | null, time: number, eventDump: string) {
this.id = id;
this.time = time;
this.parentId = parentId;
this.identifier = identifier;
this.data = eventDump;

// If the event dump is a tuple, the first element is the instance ID.
if (eventDump.startsWith('(')) {
const split = eventDump.indexOf(',');
this.column = parseInt(eventDump.substring(1, split));
this.data = eventDump.substring(split + 1, eventDump.length - 1).trim();
} else {
this.column = 0;
this.data = eventDump;
}
// Parse the title and subtitle; for example, if the event dump is
// "OutboundNetwork(NetworkRequests(...))""
// then the title is "OutboundNetwork" and the subtitle is
Expand Down Expand Up @@ -200,6 +194,7 @@ export class EventItemCollection {
type EventStartLogLineData = {
current_index: number;
total_events: number;
identifier: string;
current_event: string;
current_time_ms: number;
};
Expand All @@ -209,6 +204,7 @@ export class EventItemCollection {
totalEventCount = startData.total_events;
const event = new EventItem(
startData.current_index,
startData.identifier,
parentIds[startData.current_index] ?? null,
startData.current_time_ms,
startData.current_event
Expand Down
32 changes: 21 additions & 11 deletions tools/debug-ui/src/log_visualizer/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class OneRowLayout {

public arrowLayout = new Map<ArrowRowPosition, ArrowLayoutStrip>();

constructor(public readonly time: number) {}
constructor(public readonly time: number) { }
}

// The layout parameters for a single column of items.
Expand Down Expand Up @@ -74,8 +74,9 @@ class OneColumnLayout {
public startOffset = 0;
public itemOffset = 0;
public itemEndOffset = 0;

public arrowLayout = new Map<ArrowColumnPosition, ArrowLayoutStrip>();

constructor(public identifier: string) { }
}

// The computed layout parameters for a unique vertical position of horizontal
Expand Down Expand Up @@ -125,12 +126,20 @@ export class Layouts {
const sortedItems = [...items.getAllNonAttachedItems()];
const nextRowForColumn: number[] = [];
let currentTime = 0;

const columnIdentifiers = new Set<string>();
for (const item of sortedItems) {
while (this.columns.length <= item.column) {
this.columns.push(new OneColumnLayout());
nextRowForColumn.push(0);
}
columnIdentifiers.add(item.identifier);
}

// Convert the set to an sorted mapping
const columnIdentifierMap = new Map<string, number>();
Array.from(columnIdentifiers).sort().forEach((identifier, index) => {
columnIdentifierMap.set(identifier, index);
this.columns.push(new OneColumnLayout(identifier));
nextRowForColumn.push(0);
});

sortedItems.sort((a, b) => {
if (a.time < b.time) {
return -1;
Expand All @@ -142,6 +151,7 @@ export class Layouts {
return a.id - b.id;
});
for (const item of sortedItems) {
item.columnNumber = columnIdentifierMap.get(item.identifier)!;
if (item.time > currentTime) {
currentTime = item.time;
for (let i = 0; i < this.columns.length; i++) {
Expand All @@ -159,13 +169,13 @@ export class Layouts {
if (parentItem !== null) {
// Make sure that the child item is always placed below the parent; otherwise the arrows would
// point backwards.
nextRowForColumn[item.column] = Math.max(
nextRowForColumn[item.column],
parentItem.row + 1
nextRowForColumn[item.columnNumber] = Math.max(
nextRowForColumn[item.columnNumber],
parentItem.rowNumber + 1
);
}
item.row = nextRowForColumn[item.column]++;
if (item.row >= this.rows.length) {
item.rowNumber = nextRowForColumn[item.columnNumber]++;
if (item.rowNumber >= this.rows.length) {
this.rows.push(new OneRowLayout(item.time));
}
}
Expand Down

0 comments on commit 47b0a0b

Please sign in to comment.