Skip to content

Commit 423801e

Browse files
committed
fix: XhrPlugin cleans cache on every record (#454)
* fix: XhrPlugin cleans cache on every record * fix: rename vars
1 parent ac47136 commit 423801e

File tree

2 files changed

+120
-80
lines changed

2 files changed

+120
-80
lines changed

src/plugins/event-plugins/XhrPlugin.ts

Lines changed: 98 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,22 @@ export const XHR_PLUGIN_ID = 'xhr';
9595
*/
9696
export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
9797
private config: HttpPluginConfig;
98-
private xhrMap: Map<XMLHttpRequest, XhrDetails>;
98+
private map: Map<XMLHttpRequest, XhrDetails>;
9999

100100
constructor(config?: PartialHttpPluginConfig) {
101101
super(XHR_PLUGIN_ID);
102102
this.config = { ...defaultConfig, ...config };
103-
this.xhrMap = new Map<XMLHttpRequest, XhrDetails>();
103+
this.map = new Map<XMLHttpRequest, XhrDetails>();
104104
}
105105

106106
protected onload(): void {
107107
this.enable();
108108
}
109109

110+
get cacheSize() {
111+
return this.map.size;
112+
}
113+
110114
protected get patches() {
111115
return [
112116
{
@@ -135,103 +139,110 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
135139
};
136140

137141
private handleXhrLoadEvent = (e: Event) => {
138-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
139-
const xhrDetails: XhrDetails = this.xhrMap.get(xhr) as XhrDetails;
140-
if (xhrDetails) {
141-
const endTimee = epochTime();
142-
xhrDetails.trace!.end_time = endTimee;
143-
xhrDetails.trace!.subsegments![0].end_time = endTimee;
144-
xhrDetails.trace!.subsegments![0].http!.response = {
145-
status: xhr.status
142+
const request = e.target as XMLHttpRequest;
143+
const details = this.map.get(request);
144+
if (details) {
145+
const endTime = epochTime();
146+
details.trace!.end_time = endTime;
147+
details.trace!.subsegments![0].end_time = endTime;
148+
details.trace!.subsegments![0].http!.response = {
149+
status: request.status
146150
};
147151

148-
if (is429(xhr.status)) {
149-
xhrDetails.trace!.subsegments![0].throttle = true;
150-
xhrDetails.trace!.throttle = true;
151-
} else if (is4xx(xhr.status)) {
152-
xhrDetails.trace!.subsegments![0].error = true;
153-
xhrDetails.trace!.error = true;
154-
} else if (is5xx(xhr.status)) {
155-
xhrDetails.trace!.subsegments![0].fault = true;
156-
xhrDetails.trace!.fault = true;
152+
if (is429(request.status)) {
153+
details.trace!.subsegments![0].throttle = true;
154+
details.trace!.throttle = true;
155+
} else if (is4xx(request.status)) {
156+
details.trace!.subsegments![0].error = true;
157+
details.trace!.error = true;
158+
} else if (is5xx(request.status)) {
159+
details.trace!.subsegments![0].fault = true;
160+
details.trace!.fault = true;
157161
}
158162

159-
const clStr = xhr.getResponseHeader('Content-Length');
163+
const clStr = request.getResponseHeader('Content-Length');
160164
const cl = clStr ? parseInt(clStr, 10) : NaN;
161165
if (!isNaN(cl)) {
162-
xhrDetails.trace!.subsegments![0].http!.response.content_length =
166+
details.trace!.subsegments![0].http!.response.content_length =
163167
cl;
164168
}
165-
this.recordTraceEvent(xhrDetails.trace!);
166-
this.recordHttpEventWithResponse(xhrDetails, xhr);
169+
this.recordTraceEvent(details.trace!);
170+
this.recordHttpEventWithResponse(details, request);
167171
}
168172
};
169173

170174
private handleXhrErrorEvent = (e: Event) => {
171-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
172-
const xhrDetails = this.xhrMap.get(xhr);
175+
const request = e.target as XMLHttpRequest;
176+
const details = this.map.get(request);
173177
const errorName = 'XMLHttpRequest error';
174-
const errorMessage: string = xhr.statusText
175-
? xhr.status.toString() + ': ' + xhr.statusText
176-
: xhr.status.toString();
177-
if (xhrDetails) {
178+
const errorMessage: string = request.statusText
179+
? request.status.toString() + ': ' + request.statusText
180+
: request.status.toString();
181+
if (details) {
178182
const endTime = epochTime();
179183
// Guidance from X-Ray documentation:
180184
// > Record errors in segments when your application returns an
181185
// > error to the user, and in subsegments when a downstream call
182186
// > returns an error.
183-
xhrDetails.trace!.fault = true;
184-
xhrDetails.trace!.end_time = endTime;
185-
xhrDetails.trace!.subsegments![0].end_time = endTime;
186-
xhrDetails.trace!.subsegments![0].fault = true;
187-
xhrDetails.trace!.subsegments![0].cause = {
187+
details.trace!.fault = true;
188+
details.trace!.end_time = endTime;
189+
details.trace!.subsegments![0].end_time = endTime;
190+
details.trace!.subsegments![0].fault = true;
191+
details.trace!.subsegments![0].cause = {
188192
exceptions: [
189193
{
190194
type: errorName,
191195
message: errorMessage
192196
}
193197
]
194198
};
195-
this.recordTraceEvent(xhrDetails.trace!);
199+
this.recordTraceEvent(details.trace!);
196200
this.recordHttpEventWithError(
197-
xhrDetails,
201+
details,
202+
request,
198203
new XhrError(errorMessage)
199204
);
200205
}
201206
};
202207

203208
private handleXhrAbortEvent = (e: Event) => {
204-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
205-
const xhrDetails = this.xhrMap.get(xhr);
206-
const errorName = 'XMLHttpRequest abort';
207-
this.handleXhrDetailsOnError(xhrDetails, errorName);
209+
const request = e.target as XMLHttpRequest;
210+
const details = this.map.get(request);
211+
if (details) {
212+
this.handleXhrDetailsOnError(
213+
details,
214+
request,
215+
'XMLHttpRequest abort'
216+
);
217+
}
208218
};
209219

210220
private handleXhrTimeoutEvent = (e: Event) => {
211-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
212-
const xhrDetails = this.xhrMap.get(xhr);
221+
const request = e.target as XMLHttpRequest;
222+
const details = this.map.get(request);
213223
const errorName = 'XMLHttpRequest timeout';
214-
this.handleXhrDetailsOnError(xhrDetails, errorName);
224+
this.handleXhrDetailsOnError(details, request, errorName);
215225
};
216226

217227
private handleXhrDetailsOnError(
218-
xhrDetails: XhrDetails | undefined,
228+
details: XhrDetails | undefined,
229+
request: XMLHttpRequest,
219230
errorName: string
220231
) {
221-
if (xhrDetails) {
232+
if (details) {
222233
const endTime = epochTime();
223-
xhrDetails.trace!.end_time = endTime;
224-
xhrDetails.trace!.subsegments![0].end_time = endTime;
225-
xhrDetails.trace!.subsegments![0].error = true;
226-
xhrDetails.trace!.subsegments![0].cause = {
234+
details.trace!.end_time = endTime;
235+
details.trace!.subsegments![0].end_time = endTime;
236+
details.trace!.subsegments![0].error = true;
237+
details.trace!.subsegments![0].cause = {
227238
exceptions: [
228239
{
229240
type: errorName
230241
}
231242
]
232243
};
233-
this.recordTraceEvent(xhrDetails.trace!);
234-
this.recordHttpEventWithError(xhrDetails, errorName);
244+
this.recordTraceEvent(details.trace!);
245+
this.recordHttpEventWithError(details, request, errorName);
235246
}
236247
}
237248

@@ -240,33 +251,40 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
240251
}
241252

242253
private recordHttpEventWithResponse(
243-
xhrDetails: XhrDetails,
244-
xhr: XMLHttpRequest
254+
details: XhrDetails,
255+
request: XMLHttpRequest
245256
) {
246-
if (this.config.recordAllRequests || !this.statusOk(xhr.status)) {
247-
this.context.record(HTTP_EVENT_TYPE, {
248-
version: '1.0.0',
249-
request: { method: xhrDetails.method, url: xhrDetails.url },
250-
response: { status: xhr.status, statusText: xhr.statusText }
251-
});
257+
this.map.delete(request);
258+
const httpEvent: HttpEvent = {
259+
version: '1.0.0',
260+
request: { method: details.method, url: details.url },
261+
response: {
262+
status: request.status,
263+
statusText: request.statusText
264+
}
265+
};
266+
if (this.config.recordAllRequests || !this.statusOk(request.status)) {
267+
this.context.record(HTTP_EVENT_TYPE, httpEvent);
252268
}
253269
}
254270

255271
private recordHttpEventWithError(
256-
xhrDetails: XhrDetails,
272+
details: XhrDetails,
273+
request: XMLHttpRequest,
257274
error: Error | string | number | boolean | undefined | null
258275
) {
276+
this.map.delete(request);
259277
const httpEvent: HttpEvent = {
260278
version: '1.0.0',
261-
request: { method: xhrDetails.method, url: xhrDetails.url }
279+
request: { method: details.method, url: details.url },
280+
error: errorEventToJsErrorEvent(
281+
{
282+
type: 'error',
283+
error
284+
} as ErrorEvent,
285+
this.config.stackTraceLength
286+
)
262287
};
263-
httpEvent.error = errorEventToJsErrorEvent(
264-
{
265-
type: 'error',
266-
error
267-
} as ErrorEvent,
268-
this.config.stackTraceLength
269-
);
270288
this.context.record(HTTP_EVENT_TYPE, httpEvent);
271289
}
272290

@@ -276,20 +294,20 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
276294
}
277295
}
278296

279-
private initializeTrace = (xhrDetails: XhrDetails) => {
297+
private initializeTrace = (details: XhrDetails) => {
280298
const startTime = epochTime();
281-
xhrDetails.trace = createXRayTraceEvent(
299+
details.trace = createXRayTraceEvent(
282300
this.config.logicalServiceName,
283301
startTime
284302
);
285-
xhrDetails.trace.subsegments!.push(
303+
details.trace.subsegments!.push(
286304
createXRaySubsegment(
287-
requestInfoToHostname(xhrDetails.url),
305+
requestInfoToHostname(details.url),
288306
startTime,
289307
{
290308
request: {
291-
method: xhrDetails.method,
292-
url: xhrDetails.url,
309+
method: details.method,
310+
url: details.url,
293311
traced: true
294312
}
295313
}
@@ -301,8 +319,8 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
301319
const self = this;
302320
return (original: any) => {
303321
return function (this: XMLHttpRequest): void {
304-
const xhrDetails = self.xhrMap.get(this);
305-
if (xhrDetails) {
322+
const details = self.map.get(this);
323+
if (details) {
306324
this.addEventListener('load', self.handleXhrLoadEvent);
307325
this.addEventListener('error', self.handleXhrErrorEvent);
308326
this.addEventListener('abort', self.handleXhrAbortEvent);
@@ -311,7 +329,7 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
311329
self.handleXhrTimeoutEvent
312330
);
313331

314-
self.initializeTrace(xhrDetails);
332+
self.initializeTrace(details);
315333

316334
if (
317335
self.isTracingEnabled() &&
@@ -321,8 +339,8 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
321339
this.setRequestHeader(
322340
X_AMZN_TRACE_ID,
323341
getAmznTraceIdHeaderValue(
324-
xhrDetails.trace!.trace_id,
325-
xhrDetails.trace!.subsegments![0].id
342+
details.trace!.trace_id,
343+
details.trace!.subsegments![0].id
326344
)
327345
);
328346
}
@@ -342,7 +360,7 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
342360
async: boolean
343361
): void {
344362
if (isUrlAllowed(url, self.config)) {
345-
self.xhrMap.set(this, { url, method, async });
363+
self.map.set(this, { url, method, async });
346364
}
347365
return original.apply(this, arguments);
348366
};

0 commit comments

Comments
 (0)