Skip to content

Commit 9201e18

Browse files
[Error Boundary] Add stack trace to error payload to aid in troubleshooting rendering errors (#3032)
## Summary: The current Rendering Errors dashboard displays an error message, but nothing about where the error occurred. This PR adds the error stack to the error object sent to the dashboard service. Issue: LEMS-3714 ## Test plan: 1. Deploy to PROD 1. Wait a day or two to start receiving the data 1. Update dashboard to use the new data **OR** 1. Run the updated unit test for the `widget-container.tsx` Author: mark-fitzgerald Reviewers: catandthemachines Required Reviewers: Approved By: catandthemachines Checks: ⏭️ 1 check has been skipped, ✅ 10 checks were successful Pull Request URL: #3032
1 parent c9cfba3 commit 9201e18

File tree

4 files changed

+37
-9
lines changed

4 files changed

+37
-9
lines changed

.changeset/beige-spiders-knock.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@khanacademy/perseus-core": minor
3+
"@khanacademy/perseus": patch
4+
---
5+
6+
[Error Boundary] Add stack trace to error payload to aid in troubleshooting rendering errors

packages/perseus-core/src/analytics.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type PerseusAnalyticsEvent =
2323
widgetType: string;
2424
widgetId: string;
2525
message: string;
26+
stack: string | undefined;
2627
userAgent: string;
2728
};
2829
}

packages/perseus/src/__tests__/widget-container.test.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,35 @@ describe("widget-container", () => {
123123
);
124124

125125
// Assert
126-
expect(onAnalyticsEventSpy).toHaveBeenCalledWith({
126+
const expectedPayload = {
127+
widgetSubType: "null",
128+
widgetType: "mock-widget",
129+
widgetId: "mock-widget 1",
130+
message: "MockWidget failed to render",
131+
stack: "Error: MockWidget failed to render\n at MockWidgetComponent",
132+
userAgent: "userAgent",
133+
};
134+
const expectedEventInfo = {
127135
type: "perseus:widget-rendering-error:ti",
128-
payload: {
129-
widgetSubType: "null",
130-
widgetType: "mock-widget",
131-
widgetId: "mock-widget 1",
132-
message: "MockWidget failed to render",
133-
userAgent: "userAgent",
134-
},
135-
});
136+
payload: expectedPayload,
137+
};
138+
expect(onAnalyticsEventSpy).toHaveBeenCalledTimes(1);
139+
// NOTE: We do a partial match on the stack trace since it may vary across
140+
// environments/runs.
141+
const analyticsEventArgument = onAnalyticsEventSpy.mock.calls[0][0];
142+
expect(Object.keys(analyticsEventArgument)).toEqual(
143+
Object.keys(expectedEventInfo),
144+
);
145+
expect(analyticsEventArgument.type).toEqual(expectedEventInfo.type);
146+
expect(Object.keys(analyticsEventArgument.payload)).toEqual(
147+
Object.keys(expectedPayload),
148+
);
149+
// Checking that only the beginning of the stack trace matches so that
150+
// running this locally won't fail. Plus, the stack trace is frickin' long!
151+
expect(
152+
analyticsEventArgument.payload.stack.startsWith(
153+
expectedPayload.stack,
154+
),
155+
).toEqual(true);
136156
});
137157
});

packages/perseus/src/widget-container.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class WidgetContainer extends React.Component<Props, State> {
176176
widgetType: type,
177177
widgetId: this.props.id,
178178
message: error.message,
179+
stack: error.stack,
179180
userAgent: userAgent,
180181
},
181182
});

0 commit comments

Comments
 (0)