Skip to content

Commit 1380511

Browse files
authored
fix: XhrPlugin cleans cache on every record (#454)
* fix: XhrPlugin cleans cache on every record * fix: rename vars
1 parent 8d1e715 commit 1380511

File tree

2 files changed

+118
-74
lines changed

2 files changed

+118
-74
lines changed

src/plugins/event-plugins/XhrPlugin.ts

Lines changed: 91 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,13 @@ 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
private isSyntheticsUA: boolean;
100100

101101
constructor(config?: PartialHttpPluginConfig) {
102102
super(XHR_PLUGIN_ID);
103103
this.config = { ...defaultConfig, ...config };
104-
this.xhrMap = new Map<XMLHttpRequest, XhrDetails>();
104+
this.map = new Map<XMLHttpRequest, XhrDetails>();
105105
this.isSyntheticsUA = navigator.userAgent.includes(
106106
'CloudWatchSynthetics'
107107
);
@@ -111,6 +111,10 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
111111
this.enable();
112112
}
113113

114+
get cacheSize() {
115+
return this.map.size;
116+
}
117+
114118
protected get patches() {
115119
return [
116120
{
@@ -139,103 +143,110 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
139143
};
140144

141145
private handleXhrLoadEvent = (e: Event) => {
142-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
143-
const xhrDetails: XhrDetails = this.xhrMap.get(xhr) as XhrDetails;
144-
if (xhrDetails) {
145-
const endTimee = epochTime();
146-
xhrDetails.trace!.end_time = endTimee;
147-
xhrDetails.trace!.subsegments![0].end_time = endTimee;
148-
xhrDetails.trace!.subsegments![0].http!.response = {
149-
status: xhr.status
146+
const request = e.target as XMLHttpRequest;
147+
const details = this.map.get(request);
148+
if (details) {
149+
const endTime = epochTime();
150+
details.trace!.end_time = endTime;
151+
details.trace!.subsegments![0].end_time = endTime;
152+
details.trace!.subsegments![0].http!.response = {
153+
status: request.status
150154
};
151155

152-
if (is429(xhr.status)) {
153-
xhrDetails.trace!.subsegments![0].throttle = true;
154-
xhrDetails.trace!.throttle = true;
155-
} else if (is4xx(xhr.status)) {
156-
xhrDetails.trace!.subsegments![0].error = true;
157-
xhrDetails.trace!.error = true;
158-
} else if (is5xx(xhr.status)) {
159-
xhrDetails.trace!.subsegments![0].fault = true;
160-
xhrDetails.trace!.fault = true;
156+
if (is429(request.status)) {
157+
details.trace!.subsegments![0].throttle = true;
158+
details.trace!.throttle = true;
159+
} else if (is4xx(request.status)) {
160+
details.trace!.subsegments![0].error = true;
161+
details.trace!.error = true;
162+
} else if (is5xx(request.status)) {
163+
details.trace!.subsegments![0].fault = true;
164+
details.trace!.fault = true;
161165
}
162166

163-
const clStr = xhr.getResponseHeader('Content-Length');
167+
const clStr = request.getResponseHeader('Content-Length');
164168
const cl = clStr ? parseInt(clStr, 10) : NaN;
165169
if (!isNaN(cl)) {
166-
xhrDetails.trace!.subsegments![0].http!.response.content_length =
170+
details.trace!.subsegments![0].http!.response.content_length =
167171
cl;
168172
}
169-
this.recordTraceEvent(xhrDetails.trace!);
170-
this.recordHttpEventWithResponse(xhrDetails, xhr);
173+
this.recordTraceEvent(details.trace!);
174+
this.recordHttpEventWithResponse(details, request);
171175
}
172176
};
173177

174178
private handleXhrErrorEvent = (e: Event) => {
175-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
176-
const xhrDetails = this.xhrMap.get(xhr);
179+
const request = e.target as XMLHttpRequest;
180+
const details = this.map.get(request);
177181
const errorName = 'XMLHttpRequest error';
178-
const errorMessage: string = xhr.statusText
179-
? xhr.status.toString() + ': ' + xhr.statusText
180-
: xhr.status.toString();
181-
if (xhrDetails) {
182+
const errorMessage: string = request.statusText
183+
? request.status.toString() + ': ' + request.statusText
184+
: request.status.toString();
185+
if (details) {
182186
const endTime = epochTime();
183187
// Guidance from X-Ray documentation:
184188
// > Record errors in segments when your application returns an
185189
// > error to the user, and in subsegments when a downstream call
186190
// > returns an error.
187-
xhrDetails.trace!.fault = true;
188-
xhrDetails.trace!.end_time = endTime;
189-
xhrDetails.trace!.subsegments![0].end_time = endTime;
190-
xhrDetails.trace!.subsegments![0].fault = true;
191-
xhrDetails.trace!.subsegments![0].cause = {
191+
details.trace!.fault = true;
192+
details.trace!.end_time = endTime;
193+
details.trace!.subsegments![0].end_time = endTime;
194+
details.trace!.subsegments![0].fault = true;
195+
details.trace!.subsegments![0].cause = {
192196
exceptions: [
193197
{
194198
type: errorName,
195199
message: errorMessage
196200
}
197201
]
198202
};
199-
this.recordTraceEvent(xhrDetails.trace!);
203+
this.recordTraceEvent(details.trace!);
200204
this.recordHttpEventWithError(
201-
xhrDetails,
205+
details,
206+
request,
202207
new XhrError(errorMessage)
203208
);
204209
}
205210
};
206211

207212
private handleXhrAbortEvent = (e: Event) => {
208-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
209-
const xhrDetails = this.xhrMap.get(xhr);
210-
const errorName = 'XMLHttpRequest abort';
211-
this.handleXhrDetailsOnError(xhrDetails, errorName);
213+
const request = e.target as XMLHttpRequest;
214+
const details = this.map.get(request);
215+
if (details) {
216+
this.handleXhrDetailsOnError(
217+
details,
218+
request,
219+
'XMLHttpRequest abort'
220+
);
221+
}
212222
};
213223

214224
private handleXhrTimeoutEvent = (e: Event) => {
215-
const xhr: XMLHttpRequest = e.target as XMLHttpRequest;
216-
const xhrDetails = this.xhrMap.get(xhr);
225+
const request = e.target as XMLHttpRequest;
226+
const details = this.map.get(request);
217227
const errorName = 'XMLHttpRequest timeout';
218-
this.handleXhrDetailsOnError(xhrDetails, errorName);
228+
this.handleXhrDetailsOnError(details, request, errorName);
219229
};
220230

221231
private handleXhrDetailsOnError(
222-
xhrDetails: XhrDetails | undefined,
232+
details: XhrDetails | undefined,
233+
request: XMLHttpRequest,
223234
errorName: string
224235
) {
225-
if (xhrDetails) {
236+
if (details) {
226237
const endTime = epochTime();
227-
xhrDetails.trace!.end_time = endTime;
228-
xhrDetails.trace!.subsegments![0].end_time = endTime;
229-
xhrDetails.trace!.subsegments![0].error = true;
230-
xhrDetails.trace!.subsegments![0].cause = {
238+
details.trace!.end_time = endTime;
239+
details.trace!.subsegments![0].end_time = endTime;
240+
details.trace!.subsegments![0].error = true;
241+
details.trace!.subsegments![0].cause = {
231242
exceptions: [
232243
{
233244
type: errorName
234245
}
235246
]
236247
};
237-
this.recordTraceEvent(xhrDetails.trace!);
238-
this.recordHttpEventWithError(xhrDetails, errorName);
248+
this.recordTraceEvent(details.trace!);
249+
this.recordHttpEventWithError(details, request, errorName);
239250
}
240251
}
241252

@@ -244,30 +255,36 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
244255
}
245256

246257
private recordHttpEventWithResponse(
247-
xhrDetails: XhrDetails,
248-
xhr: XMLHttpRequest
258+
details: XhrDetails,
259+
request: XMLHttpRequest
249260
) {
261+
this.map.delete(request);
250262
const httpEvent: HttpEvent = {
251263
version: '1.0.0',
252-
request: { method: xhrDetails.method, url: xhrDetails.url },
253-
response: { status: xhr.status, statusText: xhr.statusText }
264+
request: { method: details.method, url: details.url },
265+
response: {
266+
status: request.status,
267+
statusText: request.statusText
268+
}
254269
};
255270
if (this.isTracingEnabled()) {
256-
httpEvent.trace_id = xhrDetails.trace!.trace_id;
257-
httpEvent.segment_id = xhrDetails.trace!.subsegments![0].id;
271+
httpEvent.trace_id = details.trace!.trace_id;
272+
httpEvent.segment_id = details.trace!.subsegments![0].id;
258273
}
259-
if (this.config.recordAllRequests || !this.statusOk(xhr.status)) {
274+
if (this.config.recordAllRequests || !this.statusOk(request.status)) {
260275
this.context.record(HTTP_EVENT_TYPE, httpEvent);
261276
}
262277
}
263278

264279
private recordHttpEventWithError(
265-
xhrDetails: XhrDetails,
280+
details: XhrDetails,
281+
request: XMLHttpRequest,
266282
error: Error | string | number | boolean | undefined | null
267283
) {
284+
this.map.delete(request);
268285
const httpEvent: HttpEvent = {
269286
version: '1.0.0',
270-
request: { method: xhrDetails.method, url: xhrDetails.url },
287+
request: { method: details.method, url: details.url },
271288
error: errorEventToJsErrorEvent(
272289
{
273290
type: 'error',
@@ -277,8 +294,8 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
277294
)
278295
};
279296
if (this.isTracingEnabled()) {
280-
httpEvent.trace_id = xhrDetails.trace!.trace_id;
281-
httpEvent.segment_id = xhrDetails.trace!.subsegments![0].id;
297+
httpEvent.trace_id = details.trace!.trace_id;
298+
httpEvent.segment_id = details.trace!.subsegments![0].id;
282299
}
283300
this.context.record(HTTP_EVENT_TYPE, httpEvent);
284301
}
@@ -293,20 +310,20 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
293310
}
294311
}
295312

296-
private initializeTrace = (xhrDetails: XhrDetails) => {
313+
private initializeTrace = (details: XhrDetails) => {
297314
const startTime = epochTime();
298-
xhrDetails.trace = createXRayTraceEvent(
315+
details.trace = createXRayTraceEvent(
299316
this.config.logicalServiceName,
300317
startTime
301318
);
302-
xhrDetails.trace.subsegments!.push(
319+
details.trace.subsegments!.push(
303320
createXRaySubsegment(
304-
requestInfoToHostname(xhrDetails.url),
321+
requestInfoToHostname(details.url),
305322
startTime,
306323
{
307324
request: {
308-
method: xhrDetails.method,
309-
url: xhrDetails.url,
325+
method: details.method,
326+
url: details.url,
310327
traced: true
311328
}
312329
}
@@ -318,8 +335,8 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
318335
const self = this;
319336
return (original: any) => {
320337
return function (this: XMLHttpRequest): void {
321-
const xhrDetails = self.xhrMap.get(this);
322-
if (xhrDetails) {
338+
const details = self.map.get(this);
339+
if (details) {
323340
this.addEventListener('load', self.handleXhrLoadEvent);
324341
this.addEventListener('error', self.handleXhrErrorEvent);
325342
this.addEventListener('abort', self.handleXhrAbortEvent);
@@ -328,7 +345,7 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
328345
self.handleXhrTimeoutEvent
329346
);
330347

331-
self.initializeTrace(xhrDetails);
348+
self.initializeTrace(details);
332349

333350
if (
334351
!self.isSyntheticsUA &&
@@ -339,8 +356,8 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
339356
this.setRequestHeader(
340357
X_AMZN_TRACE_ID,
341358
getAmznTraceIdHeaderValue(
342-
xhrDetails.trace!.trace_id,
343-
xhrDetails.trace!.subsegments![0].id
359+
details.trace!.trace_id,
360+
details.trace!.subsegments![0].id
344361
)
345362
);
346363
}
@@ -360,7 +377,7 @@ export class XhrPlugin extends MonkeyPatched<XMLHttpRequest, 'send' | 'open'> {
360377
async: boolean
361378
): void {
362379
if (isUrlAllowed(url, self.config)) {
363-
self.xhrMap.set(this, { url, method, async });
380+
self.map.set(this, { url, method, async });
364381
}
365382
return original.apply(this, arguments);
366383
};

0 commit comments

Comments
 (0)