@oneteme/inspect-ng-collector 1.3.0-beta.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core';
3
- import { HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
3
+ import { HttpErrorResponse, HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
4
4
  import { finalize, interval, startWith, tap as tap$1 } from 'rxjs';
5
5
  import { tap } from 'rxjs/operators';
6
6
  import { NavigationStart, NavigationEnd, NavigationCancel, Router } from '@angular/router';
@@ -19,7 +19,7 @@ const PRE_DISPATCH = 'pre-dispatch';
19
19
  const BEFOREUNLOAD = 'beforeunload';
20
20
  function createLogEntry(level, message, sessionId) {
21
21
  return {
22
- "@type": "log",
22
+ "@type": "00",
23
23
  level: level,
24
24
  message: message,
25
25
  instant: dateNow(),
@@ -28,7 +28,7 @@ function createLogEntry(level, message, sessionId) {
28
28
  }
29
29
  function createReport(message) {
30
30
  return {
31
- "@type": "log",
31
+ "@type": "00",
32
32
  level: "ERROR",
33
33
  message: message,
34
34
  instant: dateNow(),
@@ -147,7 +147,7 @@ function adaptedConfig(conf) {
147
147
  ...conf.tracing,
148
148
  remote: {
149
149
  ...conf.tracing?.remote,
150
- '@type': "rest-rmt",
150
+ '@type': "02",
151
151
  retentionMaxAge: (conf.tracing?.remote?.retentionMaxAge ?? 10) * 60 * 60 * 24
152
152
  }
153
153
  }
@@ -202,7 +202,7 @@ class ContextManager {
202
202
  id: instanceId,
203
203
  name: require(getStringOrCall(conf?.monitoring?.name), 'name'),
204
204
  version: getStringOrCall(conf?.monitoring?.version),
205
- address: undefined, //server side
205
+ address: getSessionAddress(), //server side
206
206
  env: require(getStringOrCall(conf?.monitoring?.env), 'env'),
207
207
  os: detectOs(),
208
208
  re: detectBrowser(),
@@ -216,6 +216,14 @@ class ContextManager {
216
216
  };
217
217
  }
218
218
  }
219
+ function getSessionAddress() {
220
+ let inspectId = localStorage.getItem("inspect-id");
221
+ if (!inspectId) {
222
+ inspectId = crypto.randomUUID();
223
+ localStorage.setItem("inspect-id", inspectId);
224
+ }
225
+ return inspectId;
226
+ }
219
227
  function instanceApiURL(host, path) {
220
228
  return toURL(host, path);
221
229
  }
@@ -227,6 +235,9 @@ function toURL(host, path) {
227
235
  }
228
236
 
229
237
  class SessionManager {
238
+ constructor() {
239
+ this.initialized = false;
240
+ }
230
241
  static get instance() {
231
242
  if (!SessionManager._instance) {
232
243
  SessionManager._instance = new SessionManager();
@@ -237,24 +248,28 @@ class SessionManager {
237
248
  navigate(url) {
238
249
  this.getCurrentSession(s => {
239
250
  if (s) {
240
- s.end = dateNow();
241
- window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { force: !url } }));
251
+ this.getCurrentSessionCallBack(cb => cb.end = dateNow());
252
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { force: !url, traces: this.currentSessionCallBack } }));
242
253
  }
243
254
  this.currentSession = null;
244
255
  });
245
256
  if (url) {
257
+ let id = crypto.randomUUID();
246
258
  this.currentSession = {
247
- '@type': "main-ses",
248
- id: crypto.randomUUID(),
259
+ '@type': "10",
260
+ id: id,
249
261
  user: ContextManager.instance.techConfig.user,
250
262
  start: dateNow(),
251
263
  type: "VIEW",
252
264
  location: url,
253
265
  loading: true,
254
- exceptions: [],
255
- requestsMask: 0,
256
- end: null,
257
- address: this.getSessionAddress()
266
+ requestMask: 0,
267
+ };
268
+ this.initialized = true;
269
+ this.currentSessionCallBack = {
270
+ '@type': "11",
271
+ id: id,
272
+ requestMask: 0,
258
273
  };
259
274
  }
260
275
  }
@@ -267,18 +282,17 @@ class SessionManager {
267
282
  }
268
283
  });
269
284
  }
270
- getSessionAddress() {
271
- let inspectId = localStorage.getItem("inspect-id");
272
- if (!inspectId) {
273
- inspectId = crypto.randomUUID();
274
- localStorage.setItem("inspect-id", inspectId);
275
- }
276
- return inspectId;
277
- }
278
285
  getCurrentSession(fn) {
279
286
  if (this.currentSession) {
280
287
  return fn(this.currentSession);
281
288
  }
289
+ this.initialized && window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("no active session found ") } }));
290
+ return undefined;
291
+ }
292
+ getCurrentSessionCallBack(fn) {
293
+ if (this.currentSessionCallBack) {
294
+ return fn(this.currentSessionCallBack);
295
+ }
282
296
  window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("no active session found ") } }));
283
297
  return undefined;
284
298
  }
@@ -286,10 +300,14 @@ class SessionManager {
286
300
  return this.getCurrentSession(s => s.id);
287
301
  }
288
302
  updateMask(requestMask) {
289
- this.getCurrentSession(s => s.requestsMask |= requestMask);
303
+ return this.getCurrentSessionCallBack(s => {
304
+ let before = s.requestMask;
305
+ s.requestMask |= requestMask;
306
+ return s.requestMask !== before;
307
+ });
290
308
  }
291
309
  addException(exception) {
292
- this.getCurrentSession(s => s.exceptions.push(exception));
310
+ this.getCurrentSessionCallBack(s => s.exception = exception);
293
311
  }
294
312
  }
295
313
 
@@ -299,7 +317,7 @@ class RestRequestMonitor {
299
317
  const url = toHref(restRequest.urlWithParams);
300
318
  const auth_user = extractAuthSchemeAnduser(restRequest.headers);
301
319
  this.restRequest = {
302
- "@type": "http-req",
320
+ "@type": "120",
303
321
  id: crypto.randomUUID(),
304
322
  method: restRequest.method,
305
323
  protocol: url.protocol.slice(0, -1),
@@ -310,40 +328,59 @@ class RestRequestMonitor {
310
328
  contentType: restRequest.responseType,
311
329
  authScheme: auth_user.authScheme,
312
330
  user: auth_user.user,
313
- ouDataSize: sizeOf(restRequest.body),
331
+ dataSize: sizeOf(restRequest.body),
314
332
  start: start,
315
- linked: false,
316
- end: undefined,
317
333
  sessionId: SessionManager.instance.currentSessionID()
318
334
  };
319
- SessionManager.instance.updateMask(RequestMask.REST);
335
+ this.restRequestCallBack = {
336
+ "@type": "121",
337
+ id: this.restRequest.id,
338
+ dataSize: -1,
339
+ linked: false
340
+ };
341
+ if (SessionManager.instance.currentSessionID() != null) {
342
+ let doUpdateMask = SessionManager.instance.updateMask(RequestMask.REST);
343
+ doUpdateMask && window.dispatchEvent(new CustomEvent(DISPATCH, { detail: {
344
+ traces: {
345
+ "@type": "03",
346
+ id: SessionManager.instance.currentSessionID(),
347
+ main: true,
348
+ mask: SessionManager.instance.getCurrentSessionCallBack(s => s.requestMask)
349
+ }
350
+ }
351
+ }));
352
+ }
320
353
  }
321
354
  postProcess(event, error) {
322
355
  let status = 0, exception = null;
323
356
  if (event) {
324
357
  status = +event.status;
325
- this.restRequest.inDataSize = sizeOf(event.body);
326
- this.restRequest.linked = this.assertSessionID(this.restRequest.id, event.headers);
358
+ this.restRequestCallBack.dataSize = sizeOf(event.body);
359
+ this.restRequestCallBack.linked = this.assertSessionID(this.restRequest.id, event.headers);
327
360
  }
328
361
  if (error) {
329
- this.restRequest.linked = error?.headers && this.assertSessionID(this.restRequest.id, error.headers);
362
+ this.restRequestCallBack.linked = error?.headers && this.assertSessionID(this.restRequest.id, error.headers);
330
363
  status = +error.status;
331
364
  exception = {
332
365
  type: error.name,
333
366
  message: error.error && error.status ? JSON.stringify(error.error) : error.message
334
367
  };
368
+ this.restRequestCallBack.bodyContent = error instanceof HttpErrorResponse ? JSON.stringify(error.error) : undefined;
369
+ this.restRequestCallBack.dataSize = sizeOf(error.error);
335
370
  }
336
- this.restRequest.end = dateNow();
337
- this.restRequest.status = +status;
371
+ this.restRequestCallBack.contentType = extractContentType(event?.headers);
372
+ this.restRequestCallBack.end = dateNow();
373
+ this.restRequestCallBack.status = +status;
338
374
  let stage = {
339
- "@type": "http-stg",
375
+ "@type": "220",
340
376
  name: "PROCESS",
341
- start: this.restRequest.start,
377
+ start: this.restRequest.start, // use request
342
378
  end: dateNow(),
343
379
  order: 0,
344
380
  exception: exception,
345
- requestId: this.restRequest.id
381
+ requestId: this.restRequestCallBack.id
346
382
  };
383
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: this.restRequestCallBack } }));
347
384
  window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: stage } }));
348
385
  }
349
386
  assertSessionID(id, headers) {
@@ -351,9 +388,6 @@ class RestRequestMonitor {
351
388
  if (id == headers.get('x-tracert')) {
352
389
  return true;
353
390
  }
354
- window.dispatchEvent(new CustomEvent(DISPATCH, {
355
- detail: { traces: createReport("The received x-tracert header (" + headers.get('x-tracert') + ") does not match the request id (" + id + ")") }
356
- }));
357
391
  }
358
392
  return false;
359
393
  }
@@ -391,6 +425,17 @@ function extractAuthSchemeAnduser(headers) {
391
425
  }
392
426
  return auth_user;
393
427
  }
428
+ function extractContentType(headers) {
429
+ try {
430
+ if (headers?.has('Content-Type')) {
431
+ return headers.get('Content-Type');
432
+ }
433
+ }
434
+ catch (err) {
435
+ createReport(JSON.stringify(err));
436
+ }
437
+ return undefined;
438
+ }
394
439
  function sizeOf(body) {
395
440
  return body ? JSON.stringify(body).length : 0;
396
441
  }
@@ -428,10 +473,10 @@ class HttpInterceptorService {
428
473
  });
429
474
  }));
430
475
  }
431
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpInterceptorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
432
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpInterceptorService, providedIn: 'root' }); }
476
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpInterceptorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
477
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpInterceptorService, providedIn: 'root' }); }
433
478
  }
434
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: HttpInterceptorService, decorators: [{
479
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpInterceptorService, decorators: [{
435
480
  type: Injectable,
436
481
  args: [{ providedIn: 'root' }]
437
482
  }], ctorParameters: () => [] });
@@ -449,10 +494,10 @@ class GlobalErrorHandlerService {
449
494
  }
450
495
  throw error;
451
496
  }
452
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: GlobalErrorHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
453
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: GlobalErrorHandlerService, providedIn: 'root' }); }
497
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: GlobalErrorHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
498
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: GlobalErrorHandlerService, providedIn: 'root' }); }
454
499
  }
455
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: GlobalErrorHandlerService, decorators: [{
500
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: GlobalErrorHandlerService, decorators: [{
456
501
  type: Injectable,
457
502
  args: [{ providedIn: 'root' }]
458
503
  }] });
@@ -472,7 +517,9 @@ class EventTraceScheduledDispatcherService {
472
517
  if (this.sendSessionfinished) {
473
518
  this.sendSessionfinished = false;
474
519
  window.dispatchEvent(new CustomEvent(PRE_DISPATCH));
475
- setTimeout(() => this.Dispatch().finally(() => { this.sendSessionfinished = true; }), 5);
520
+ this.Dispatch()
521
+ .catch(err => { })
522
+ .finally(() => { this.sendSessionfinished = true; });
476
523
  }
477
524
  }))
478
525
  .subscribe();
@@ -502,7 +549,8 @@ class EventTraceScheduledDispatcherService {
502
549
  if (instanceComplete) {
503
550
  uri += "&end=" + new Date().toISOString();
504
551
  }
505
- let sessions = this.extractEventTrace();
552
+ let sessions = this.traceQueue;
553
+ this.traceQueue = new Set();
506
554
  return fetch(uri, this.getRequestInit(sessions))
507
555
  .then(res => {
508
556
  if (res.ok) {
@@ -515,27 +563,6 @@ class EventTraceScheduledDispatcherService {
515
563
  }
516
564
  return Promise.resolve(0);
517
565
  }
518
- extractEventTrace() {
519
- let trc = this.traceQueue;
520
- this.traceQueue = new Set();
521
- let ses = new Set();
522
- trc.forEach(((e) => {
523
- if (e.hasOwnProperty("end")) {
524
- const copy = { ...e };
525
- if (!copy.end) {
526
- ses.add(copy);
527
- this.traceQueue.add(e);
528
- }
529
- else {
530
- ses.add(e);
531
- }
532
- }
533
- else {
534
- ses.add(e);
535
- }
536
- }));
537
- return ses;
538
- }
539
566
  handleEventTraceSavingError(sessions) {
540
567
  this.sessionSendAttempts % 5 == 0 && console.warn(`Error while attempting to send sessions, attempts: ${this.sessionSendAttempts}`);
541
568
  this.revertQueueSize(sessions);
@@ -546,6 +573,7 @@ class EventTraceScheduledDispatcherService {
546
573
  method: 'PUT',
547
574
  headers: { 'Content-Type': 'application/json' },
548
575
  mode: 'cors',
576
+ keepalive: true,
549
577
  body: JSON.stringify(Array.from(sessionList))
550
578
  };
551
579
  }
@@ -555,6 +583,7 @@ class EventTraceScheduledDispatcherService {
555
583
  method: 'POST',
556
584
  headers: { 'Content-Type': 'application/json' },
557
585
  mode: 'cors',
586
+ keepalive: true,
558
587
  body: JSON.stringify(ContextManager.instance.instanceEnv)
559
588
  })
560
589
  .then(res => res.ok ? res.text().then(id => {
@@ -593,7 +622,7 @@ function routeHandler(event) {
593
622
  SessionManager.instance.navigate(event.url);
594
623
  }
595
624
  if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
596
- SessionManager.instance.updateSession();
625
+ setTimeout(() => SessionManager.instance.updateSession(), 0);
597
626
  }
598
627
  }
599
628
  function windowUnloadHandler(event) {
@@ -603,7 +632,7 @@ function bfCacheHandler(event) {
603
632
  if (event.persisted) { // if the page was restored from bfcache
604
633
  ContextManager.init(NgCollectorModule.configuration);
605
634
  SessionManager.instance.navigate(document.URL);
606
- SessionManager.instance.updateSession();
635
+ setTimeout(() => SessionManager.instance.updateSession(), 0);
607
636
  }
608
637
  }
609
638
 
@@ -614,7 +643,7 @@ function getMemoryInfo() {
614
643
  try {
615
644
  const memory = performance.memory;
616
645
  return {
617
- '@type': 'rsrc-usg',
646
+ '@type': '01',
618
647
  instant: dateNow(),
619
648
  usedHeap: memory.usedJSHeapSize / (1024 * 1024),
620
649
  commitedHeap: memory.totalJSHeapSize / (1024 * 1024),
@@ -732,14 +761,14 @@ function lookUpChild(t, depth) {
732
761
  }
733
762
  function addActionUser(eventType, target) {
734
763
  const ua = {
735
- '@type': "user-act",
764
+ '@type': "300",
736
765
  type: eventType,
737
766
  start: dateNow(),
738
767
  name: extractName(target),
739
768
  nodeName: target.tagName?.toLowerCase(),
740
769
  sessionId: SessionManager.instance?.currentSessionID()
741
770
  };
742
- // window.dispatchEvent(new CustomEvent( DISPATCH ,{ detail : { traces:ua }}));
771
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: ua } }));
743
772
  }
744
773
 
745
774
  function eventTraceDebugger() {
@@ -811,7 +840,7 @@ class EventTraceDebugger {
811
840
  if (session.location) {
812
841
  s += `(${session.location}) `;
813
842
  }
814
- s += this.prettyDurationFormat(session.start, session.end) + '\n';
843
+ //s+= this.prettyDurationFormat(session.start, session.end)+'\n';
815
844
  s += this.getChildPrint(this.restRequests, this.prettyRestRequestFormat.bind(this));
816
845
  s += this.getChildPrint(this.localRequests, this.prettyLocalRequestFormat.bind(this));
817
846
  s += this.getChildPrint(this.userActions, this.prettyActionUserFormat.bind(this));
@@ -839,8 +868,9 @@ class EventTraceDebugger {
839
868
  if (rest.query) {
840
869
  s += rest.query;
841
870
  }
842
- s += ` >> ${rest.status} `;
843
- s += this.prettyDurationFormat(rest.start, rest.end) + '\n';
871
+ // s+= ` >> ${rest.status} `
872
+ // s+= this.prettyDurationFormat(rest.start,rest.end);
873
+ s += '\n';
844
874
  this.httpRequestStages.filter((s) => s.requestId == rest.id).forEach((stage) => {
845
875
  s += this.prettyHttpRequestStageFormat(stage);
846
876
  });
@@ -863,14 +893,14 @@ class EventTraceDebugger {
863
893
  if (local.location) {
864
894
  s += `(${local.location})`;
865
895
  }
866
- s += " >> ";
867
- if (local.exception?.type) {
868
- s += ` ${local.exception?.type}:`;
869
- }
870
- if (local.exception?.message) {
871
- s += ` ${local.exception.message}`;
872
- }
873
- s += ` ${this.prettyDurationFormat(local.start, local.end)}`;
896
+ /*s+= " >> ";
897
+ if(local.exception?.type){
898
+ s+= ` ${local.exception?.type}:`;
899
+ }
900
+ if(local.exception?.message){
901
+ s+= ` ${local.exception.message}`
902
+ }
903
+ s+= ` ${this.prettyDurationFormat(local.start, local.end)}`;*/
874
904
  return s;
875
905
  }
876
906
  prettyLogEntryFormat(log) {
@@ -953,11 +983,11 @@ class NgCollectorModule {
953
983
  ngModule: NgCollectorModule
954
984
  };
955
985
  }
956
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: NgCollectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
957
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.11", ngImport: i0, type: NgCollectorModule }); }
958
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: NgCollectorModule }); }
986
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
987
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule }); }
988
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule }); }
959
989
  }
960
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.11", ngImport: i0, type: NgCollectorModule, decorators: [{
990
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule, decorators: [{
961
991
  type: NgModule
962
992
  }] });
963
993
  function initializeEvents(router) {
@@ -982,7 +1012,6 @@ function TraceableStage() {
982
1012
  let start, end;
983
1013
  start = Date.now();
984
1014
  try {
985
- WIN["inspect-session-manager"]?.updateMask(RequestMask.LOCAL);
986
1015
  return originalMethod.apply(this, args);
987
1016
  }
988
1017
  catch (e) {
@@ -1007,19 +1036,38 @@ function TraceableStage() {
1007
1036
  }
1008
1037
  finally {
1009
1038
  end = Date.now();
1039
+ let id = crypto.randomUUID();
1040
+ if (WIN["inspect-session-manager"]?.currentSessionID() != null) {
1041
+ let doUpdateMask = WIN["inspect-session-manager"]?.updateMask(RequestMask.LOCAL);
1042
+ doUpdateMask && window.dispatchEvent(new CustomEvent(DISPATCH, { detail: {
1043
+ traces: {
1044
+ "@type": "03",
1045
+ id: WIN["inspect-session-manager"]?.currentSessionID(),
1046
+ main: true,
1047
+ mask: WIN["inspect-session-manager"]?.getCurrentSessionCallBack((s) => s.requestMask)
1048
+ }
1049
+ }
1050
+ }));
1051
+ }
1010
1052
  window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: {
1011
- "@type": "locl-req",
1012
- id: crypto.randomUUID(),
1053
+ "@type": "110",
1054
+ id: id,
1013
1055
  name: propertyKey,
1014
1056
  location: target.constructor.name,
1015
1057
  user: WIN["inspect-session-manager"]?.currentSession?.user,
1016
1058
  start: start,
1017
- end: end,
1018
- exception: exception,
1019
1059
  sessionId: WIN["inspect-session-manager"]?.currentSession?.id
1020
1060
  }
1021
1061
  }
1022
1062
  }));
1063
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: {
1064
+ "@type": "111",
1065
+ id: id,
1066
+ exception: exception,
1067
+ end: end
1068
+ }
1069
+ }
1070
+ }));
1023
1071
  }
1024
1072
  };
1025
1073
  return descriptor;