Skip to content

Commit

Permalink
Gracefully handle missing recordings.log entries
Browse files Browse the repository at this point in the history
  • Loading branch information
bvaughn committed Jul 9, 2024
1 parent 25fd588 commit 5f6c9e4
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 15 deletions.
10 changes: 10 additions & 0 deletions packages/shared/src/recording/getRecordings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,14 @@ describe("getRecordings", () => {
])
);
});

it("should gracefully handle missing recording log entries", () => {
mockReadFileSync.mockReturnValue(`
{"id":"fake","kind":"addMetadata","metadata":{"processGroupId":"fake"}}
{"id":"fake","kind":"writeFinished"}
`);

const recordings = getRecordings();
expect(recordings).toHaveLength(0);
});
});
93 changes: 78 additions & 15 deletions packages/shared/src/recording/getRecordings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { basename } from "path";
import { logger } from "../logger";
import { recordingLogPath } from "./config";
import { readRecordingLog } from "./readRecordingLog";
import { LocalRecording, RECORDING_LOG_KIND } from "./types";
import { LocalRecording, LogEntry, RECORDING_LOG_KIND } from "./types";

export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
const recordings: LocalRecording[] = [];
Expand All @@ -22,7 +22,10 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
case RECORDING_LOG_KIND.addMetadata: {
const { id, metadata = {} } = entry;
const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

Object.assign(recording.metadata, metadata);

Expand Down Expand Up @@ -58,7 +61,11 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
const { data, id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

if (recording.crashData) {
recording.crashData.push(data);
} else {
Expand All @@ -70,7 +77,11 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
const { id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.recordingStatus = "crashed";
break;
}
Expand Down Expand Up @@ -117,7 +128,10 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
);

const recording = idToRecording[recordingId];
assert(recording, `Recording with ID "${recordingId}" not found`);
if (!recording) {
logNotFoundWarning(recordingId, entries, entry);
continue;
}

const sourceMap = recording.metadata.sourceMaps.find(
sourceMap => sourceMap.id === parentId
Expand All @@ -134,31 +148,47 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
const { id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.processingStatus = "failed";
break;
}
case RECORDING_LOG_KIND.processingFinished: {
const { id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.processingStatus = "processed";
break;
}
case RECORDING_LOG_KIND.processingStarted: {
const { id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.processingStatus = "processing";
break;
}
case RECORDING_LOG_KIND.recordingUnusable: {
const { id, reason } = entry;
const recording = idToRecording[id];

assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.recordingStatus = "unusable";
recording.unusableReason = reason;
break;
Expand All @@ -179,7 +209,10 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
assert(targetMapURLHash, '"sourcemapAdded" entry must have a "targetMapURLHash"');

const recording = idToRecording[recordingId];
assert(recording, `Recording with ID "${recordingId}" not found`);
if (!recording) {
logNotFoundWarning(recordingId, entries, entry);
continue;
}

recording.metadata.sourceMaps.push({
id,
Expand All @@ -196,31 +229,47 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
const { id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.uploadStatus = "failed";
break;
}
case RECORDING_LOG_KIND.uploadFinished: {
const { id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.uploadStatus = "uploaded";
break;
}
case RECORDING_LOG_KIND.uploadStarted: {
const { id } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.uploadStatus = "uploading";
break;
}
case RECORDING_LOG_KIND.writeFinished: {
const { id, timestamp } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.recordingStatus = "finished";

const startTimestamp = idToStartTimestamp[id];
Expand All @@ -233,7 +282,11 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
const { id, path, timestamp } = entry;

const recording = idToRecording[id];
assert(recording, `Recording with ID "${id}" not found`);
if (!recording) {
logNotFoundWarning(id, entries, entry);
continue;
}

recording.path = path;
idToStartTimestamp[id] = timestamp;
break;
Expand Down Expand Up @@ -273,3 +326,13 @@ export function getRecordings(processGroupIdFilter?: string): LocalRecording[] {
.sort((a, b) => b.date.getTime() - a.date.getTime())
);
}

function logNotFoundWarning(recordingId: string, entries: LogEntry[], entry: LogEntry) {
logger.error(`Recording with ID "${recordingId}" not found`, {
recordingId,
entry,
entries: JSON.stringify(
entries.filter(entry => entry.id === recordingId || entry.recordingId === recordingId)
),
});
}

0 comments on commit 5f6c9e4

Please sign in to comment.