Error resistant data dump from TimelinePanel
(#9079)
Error resistant data dump from `TimelinePanel` so we still have some data to dump if one of the pieces errors out. Example error that can happen (as seen in https://github.com/matrix-org/element-web-rageshakes/issues/14197): ``` Uncaught TypeError: Cannot read properties of null (reading 'getEvents') at TimelineWindow.getEvents (timeline-window.ts:378:37) at TimelinePanel_TimelinePanel.onDumpDebugLogs (TimelinePanel.tsx:434:60) at Object.ID_727 (TimelinePanel.tsx:609:22) at MatrixDispatcher._invokeCallback (Dispatcher.js:198:1) at MatrixDispatcher.dispatch (Dispatcher.js:174:1) at sentryWrapped (helpers.js:77:1) ```
This commit is contained in:
parent
e694e87814
commit
dfa844a035
1 changed files with 50 additions and 28 deletions
|
@ -384,24 +384,28 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
||||||
* every message change so instead we only log it out when asked.
|
* every message change so instead we only log it out when asked.
|
||||||
*/
|
*/
|
||||||
private onDumpDebugLogs = (): void => {
|
private onDumpDebugLogs = (): void => {
|
||||||
const room = this.props.timelineSet.room;
|
const room = this.props.timelineSet?.room;
|
||||||
// Get a list of the event IDs used in this TimelinePanel.
|
// Get a list of the event IDs used in this TimelinePanel.
|
||||||
// This includes state and hidden events which we don't render
|
// This includes state and hidden events which we don't render
|
||||||
const eventIdList = this.state.events.map((ev) => ev.getId());
|
const eventIdList = this.state?.events?.map((ev) => ev.getId());
|
||||||
|
|
||||||
// Get the list of actually rendered events seen in the DOM.
|
// Get the list of actually rendered events seen in the DOM.
|
||||||
// This is useful to know for sure what's being shown on screen.
|
// This is useful to know for sure what's being shown on screen.
|
||||||
// And we can suss out any corrupted React `key` problems.
|
// And we can suss out any corrupted React `key` problems.
|
||||||
let renderedEventIds: string[];
|
let renderedEventIds: string[];
|
||||||
const messagePanel = this.messagePanel.current;
|
try {
|
||||||
if (messagePanel) {
|
const messagePanel = this.messagePanel.current;
|
||||||
const messagePanelNode = ReactDOM.findDOMNode(messagePanel) as Element;
|
if (messagePanel) {
|
||||||
if (messagePanelNode) {
|
const messagePanelNode = ReactDOM.findDOMNode(messagePanel) as Element;
|
||||||
const actuallyRenderedEvents = messagePanelNode.querySelectorAll('[data-event-id]');
|
if (messagePanelNode) {
|
||||||
renderedEventIds = [...actuallyRenderedEvents].map((renderedEvent) => {
|
const actuallyRenderedEvents = messagePanelNode.querySelectorAll('[data-event-id]');
|
||||||
return renderedEvent.getAttribute('data-event-id');
|
renderedEventIds = [...actuallyRenderedEvents].map((renderedEvent) => {
|
||||||
});
|
return renderedEvent.getAttribute('data-event-id');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`onDumpDebugLogs: Failed to get the actual event ID's in the DOM`, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of events and threads for the room as seen by the
|
// Get the list of events and threads for the room as seen by the
|
||||||
|
@ -413,26 +417,44 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
||||||
const timelineSets = room.getTimelineSets();
|
const timelineSets = room.getTimelineSets();
|
||||||
const threadsTimelineSets = room.threadsTimelineSets;
|
const threadsTimelineSets = room.threadsTimelineSets;
|
||||||
|
|
||||||
// Serialize all of the timelineSets and timelines in each set to their event IDs
|
try {
|
||||||
serializedEventIdsFromTimelineSets = serializeEventIdsFromTimelineSets(timelineSets);
|
// Serialize all of the timelineSets and timelines in each set to their event IDs
|
||||||
serializedEventIdsFromThreadsTimelineSets = serializeEventIdsFromTimelineSets(threadsTimelineSets);
|
serializedEventIdsFromTimelineSets = serializeEventIdsFromTimelineSets(timelineSets);
|
||||||
|
serializedEventIdsFromThreadsTimelineSets = serializeEventIdsFromTimelineSets(threadsTimelineSets);
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`onDumpDebugLogs: Failed to serialize event IDs from timelinesets`, err);
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize all threads in the room from theadId -> event IDs in the thread
|
try {
|
||||||
room.getThreads().forEach((thread) => {
|
// Serialize all threads in the room from theadId -> event IDs in the thread
|
||||||
serializedThreadsMap[thread.id] = {
|
room.getThreads().forEach((thread) => {
|
||||||
events: thread.events.map(ev => ev.getId()),
|
serializedThreadsMap[thread.id] = {
|
||||||
numTimelines: thread.timelineSet.getTimelines().length,
|
events: thread.events.map(ev => ev.getId()),
|
||||||
liveTimeline: thread.timelineSet.getLiveTimeline().getEvents().length,
|
numTimelines: thread.timelineSet.getTimelines().length,
|
||||||
prevTimeline: thread.timelineSet.getLiveTimeline().getNeighbouringTimeline(Direction.Backward)
|
liveTimeline: thread.timelineSet.getLiveTimeline().getEvents().length,
|
||||||
?.getEvents().length,
|
prevTimeline: thread.timelineSet.getLiveTimeline().getNeighbouringTimeline(Direction.Backward)
|
||||||
nextTimeline: thread.timelineSet.getLiveTimeline().getNeighbouringTimeline(Direction.Forward)
|
?.getEvents().length,
|
||||||
?.getEvents().length,
|
nextTimeline: thread.timelineSet.getLiveTimeline().getNeighbouringTimeline(Direction.Forward)
|
||||||
};
|
?.getEvents().length,
|
||||||
});
|
};
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`onDumpDebugLogs: Failed to serialize event IDs from the threads`, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const timelineWindowEventIds = this.timelineWindow.getEvents().map(ev => ev.getId());
|
let timelineWindowEventIds: string[];
|
||||||
const pendingEvents = this.props.timelineSet.getPendingEvents().map(ev => ev.getId());
|
try {
|
||||||
|
timelineWindowEventIds = this.timelineWindow.getEvents().map(ev => ev.getId());
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`onDumpDebugLogs: Failed to get event IDs from the timelineWindow`, err);
|
||||||
|
}
|
||||||
|
let pendingEventIds: string[];
|
||||||
|
try {
|
||||||
|
pendingEventIds = this.props.timelineSet.getPendingEvents().map(ev => ev.getId());
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`onDumpDebugLogs: Failed to get pending event IDs`, err);
|
||||||
|
}
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`TimelinePanel(${this.context.timelineRenderingType}): Debugging info for ${room?.roomId}\n` +
|
`TimelinePanel(${this.context.timelineRenderingType}): Debugging info for ${room?.roomId}\n` +
|
||||||
|
@ -444,7 +466,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
||||||
`${JSON.stringify(serializedEventIdsFromThreadsTimelineSets)}\n` +
|
`${JSON.stringify(serializedEventIdsFromThreadsTimelineSets)}\n` +
|
||||||
`\tserializedThreadsMap=${JSON.stringify(serializedThreadsMap)}\n` +
|
`\tserializedThreadsMap=${JSON.stringify(serializedThreadsMap)}\n` +
|
||||||
`\ttimelineWindowEventIds(${timelineWindowEventIds.length})=${JSON.stringify(timelineWindowEventIds)}\n` +
|
`\ttimelineWindowEventIds(${timelineWindowEventIds.length})=${JSON.stringify(timelineWindowEventIds)}\n` +
|
||||||
`\tpendingEvents(${pendingEvents.length})=${JSON.stringify(pendingEvents)}`,
|
`\tpendingEventIds(${pendingEventIds.length})=${JSON.stringify(pendingEventIds)}`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue