@oneteme/inspect-ng-collector 1.2.3 → 1.3.0-beta.10

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,145 +1,41 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Inject, Injectable, APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core';
3
- import { HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
4
- import { Router, NavigationStart, NavigationEnd } from '@angular/router';
5
- import { tap as tap$1, finalize } from 'rxjs/operators';
6
- import { interval, startWith, tap } from 'rxjs';
7
- import { DOCUMENT } from '@angular/common';
2
+ import { Injectable, APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core';
3
+ import { HttpErrorResponse, HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
4
+ import { finalize, interval, startWith, tap as tap$1 } from 'rxjs';
5
+ import { tap } from 'rxjs/operators';
6
+ import { NavigationStart, NavigationEnd, NavigationCancel, Router } from '@angular/router';
8
7
 
9
8
  const WIN = window;
10
9
  function dateNow() {
11
10
  return Date.now() / 1_000;
12
11
  }
13
- function initDebug(value) {
14
- WIN["inspect"] = { app: value.app, user: value.user };
15
- }
16
- function logInspect(level, ...args) {
17
- if (WIN["inspect"][level]) {
18
- if (args.length == 1 && typeof args[0] == 'function') {
19
- args = args[0]();
20
- if (!Array.isArray(args)) {
21
- args = [args];
22
- }
23
- }
24
- console.log(`[INSPECT]-(${level})`, ...args);
25
- }
26
- }
27
- function prettyActionUserFormat(session, userAction) {
28
- let s = "";
29
- if (session) {
30
- s += `(${session.location}) `;
31
- }
32
- if (userAction.type) {
33
- s += `[${userAction.type}]`;
34
- }
35
- if (userAction.nodeName) {
36
- s += `<${userAction.nodeName}>`;
37
- }
38
- if (userAction.name) {
39
- s += `(${userAction.name}) `;
40
- }
41
- s += ` >> ${new Date(userAction.start * 1000).toISOString()}`;
42
- return s;
43
- }
44
- function prettySessionFormat(session) {
45
- let s = `[${session.name}]`;
46
- if (session.user) {
47
- s += `<${session.user}>`;
48
- }
49
- if (session.location) {
50
- s += `(${session.location}) `;
51
- }
52
- s += prettyDurationFormat(session.start, session.end) + '\n';
53
- session.restRequests.forEach(r => {
54
- s += prettyRestRequestFormat(r) + '\n';
55
- });
56
- session.localRequests.forEach(r => {
57
- s += prettyLocalRequestFormat(r) + '\n';
58
- });
59
- return s;
60
- }
61
- function prettyRestRequestFormat(rest) {
62
- let s = ` - [${rest.method}]`;
63
- if (rest.protocol) {
64
- s += `${rest.protocol}://`;
65
- }
66
- if (rest.host) {
67
- s += rest.host;
68
- }
69
- if (rest.port > 0) {
70
- s += `:${rest.port}`;
71
- }
72
- if (rest.path) {
73
- if (!rest.path.startsWith("/") && !s.endsWith("/")) {
74
- s += '/';
75
- }
76
- s += rest.path;
77
- }
78
- if (rest.query) {
79
- s += rest.query;
80
- }
81
- if (rest.exception?.type) {
82
- s += ` ${rest.exception?.type}:`;
83
- }
84
- if (rest.exception?.message) {
85
- s += ` ${rest.exception.message}`;
86
- }
87
- s += ` >> ${rest.status}`;
88
- s += prettyDurationFormat(rest.start, rest.end);
89
- return s;
90
- }
91
- function prettyLocalRequestFormat(local) {
92
- let s = ` - [${local.name}]`;
93
- if (local.location) {
94
- s += `(${local.location})`;
95
- }
96
- if (local.exception?.type) {
97
- s += ` ${local.exception?.type}:`;
98
- }
99
- if (local.exception?.message) {
100
- s += ` ${local.exception.message}`;
101
- }
102
- s += ` >> ${prettyDurationFormat(local.start, local.end)}`;
103
- return s;
104
- }
105
- function prettyDurationFormat(start, end) {
106
- return start && end ? `(in ${(end - start).toFixed(2)} s)` : '';
107
- }
108
-
109
- const SLASH = '/';
110
- const HOST_PATERN = /https?:\/\/[\w\-.]+(:\d{2,5})?\/?/;
111
- const PATH_PATERN = /[\w-]+(\/[\w-]+)*/;
112
- function validateAndGetConfig(conf) {
113
- let host = matchRegex(getStringOrCall(conf.host), "host", HOST_PATERN);
114
- let sessionApi = matchRegex(getStringOrCall(conf.sessionApi), "sessionApi", PATH_PATERN, "v3/trace/instance/:id/session");
115
- let instanceApi = matchRegex(getStringOrCall(conf.instanceApi), "intanceApi", PATH_PATERN, "v3/trace/instance");
116
- initDebug(conf.debug ?? { app: false, user: false });
12
+ var RequestMask;
13
+ (function (RequestMask) {
14
+ RequestMask[RequestMask["LOCAL"] = 1] = "LOCAL";
15
+ RequestMask[RequestMask["REST"] = 4] = "REST";
16
+ })(RequestMask || (RequestMask = {}));
17
+ const DISPATCH = 'dispatch';
18
+ const PRE_DISPATCH = 'pre-dispatch';
19
+ const BEFOREUNLOAD = 'beforeunload';
20
+ function createLogEntry(level, message, sessionId) {
117
21
  return {
118
- user: typeof conf.user == 'function' ? conf.user : () => conf.user,
119
- bufferMaxSize: requirePostitiveValue(getNumberOrCall(conf.bufferMaxSize), "bufferMaxSize", 1000),
120
- delay: requirePostitiveValue(getNumberOrCall(conf.delay), "delay", 60000),
121
- instanceApi: sessionApiURL(host, instanceApi),
122
- sessionApi: instanceApiURL(host, sessionApi),
123
- exclude: getRegArrOrCall(conf.exclude) || [],
124
- debug: conf.debug ?? { app: false, user: false },
125
- analytics: conf.analytics ?? false,
126
- enabled: conf.enabled ?? false
22
+ "@type": "00",
23
+ level: level,
24
+ message: message,
25
+ instant: dateNow(),
26
+ sessionId: sessionId
127
27
  };
128
28
  }
129
- function GetInstanceEnvironement(conf) {
29
+ function createReport(message) {
130
30
  return {
131
- name: require(getStringOrCall(conf.name), 'name'),
132
- version: getStringOrCall(conf.version),
133
- address: undefined, //server side
134
- env: require(getStringOrCall(conf.env), 'env'),
135
- os: detectOs(),
136
- re: detectBrowser(),
137
- user: undefined, // cannot get user
138
- type: "CLIENT",
31
+ "@type": "00",
32
+ level: "ERROR",
33
+ message: message,
139
34
  instant: dateNow(),
140
- collector: "inspect-ng-collector-0.0.1"
141
35
  };
142
36
  }
37
+
38
+ const SLASH$1 = '/';
143
39
  function getNumberOrCall(o) {
144
40
  return typeof o === "function" ? o() : o;
145
41
  }
@@ -194,14 +90,8 @@ function detectOs() {
194
90
  }
195
91
  return undefined;
196
92
  }
197
- function instanceApiURL(host, path) {
198
- return toURL(host, path);
199
- }
200
- function sessionApiURL(host, path) {
201
- return toURL(host, path);
202
- }
203
- function toURL(host, path) {
204
- return host.endsWith(SLASH) || path.startsWith(SLASH) ? host + path : [host, path].join(SLASH);
93
+ function toURL$1(host, path) {
94
+ return host.endsWith(SLASH$1) || path.startsWith(SLASH$1) ? host + path : [host, path].join(SLASH$1);
205
95
  }
206
96
  function matchRegex(v, name, pattern, defaultValue) {
207
97
  if (v && pattern.exec(v)) {
@@ -232,219 +122,275 @@ function require(v, name) {
232
122
  }
233
123
  throw new Error(`${name} property is required`);
234
124
  }
235
-
236
- class SessionManager {
237
- constructor(config, instance) {
238
- this.sessionQueue = [];
239
- this.sessionSendAttempts = 0;
240
- this.sendSessionfinished = true;
241
- this.config = config;
242
- this.instanceEnvironment = instance;
243
- SessionManager._instance = this;
244
- this.scheduledSessionSender = interval(config.delay)
245
- .pipe(startWith(0))
246
- .pipe(tap(() => {
247
- if (this.sendSessionfinished) {
248
- this.sendSessionfinished = false;
249
- this.manageCache().finally(() => { this.sendSessionfinished = true; });
125
+ function adaptedConfig(conf) {
126
+ return {
127
+ ...conf,
128
+ scheduling: {
129
+ ...conf.scheduling,
130
+ interval: conf.scheduling?.interval && conf.scheduling.interval / 1000
131
+ },
132
+ monitoring: {
133
+ ...conf.monitoring,
134
+ additionalProperties: String(conf.monitoring?.additionalProperties),
135
+ name: String(conf.monitoring?.name),
136
+ version: String(conf.monitoring?.version),
137
+ env: String(conf.monitoring?.env),
138
+ user: String(conf.monitoring?.user),
139
+ httpRoute: {
140
+ ...conf.monitoring?.httpRoute,
141
+ excludes: {
142
+ path: (conf?.monitoring?.httpRoute?.excludes?.path).map(r => r.source)
143
+ }
250
144
  }
251
- }))
252
- .subscribe();
253
- logInspect('app', 'SessionManager initialized');
145
+ },
146
+ tracing: {
147
+ ...conf.tracing,
148
+ remote: {
149
+ ...conf.tracing?.remote,
150
+ '@type': "02",
151
+ retentionMaxAge: (conf.tracing?.remote?.retentionMaxAge ?? 10) * 60 * 60 * 24
152
+ }
153
+ }
154
+ };
155
+ }
156
+
157
+ const SLASH = '/';
158
+ const HOST_PATERN = /https?:\/\/[\w\-.]+(:\d{2,5})?\/?/;
159
+ class ContextManager {
160
+ constructor(_instanceEnv, _techConfig) {
161
+ this._instanceEnv = _instanceEnv;
162
+ this._techConfig = _techConfig;
163
+ }
164
+ get techConfig() {
165
+ return this._techConfig;
166
+ }
167
+ get instanceEnv() {
168
+ return this._instanceEnv;
169
+ }
170
+ static get instance() {
171
+ if (!ContextManager._instance) {
172
+ console.warn("[Inspect-ng-collector] Error while initializing ContextManager");
173
+ }
174
+ return ContextManager._instance;
175
+ }
176
+ static init(conf) {
177
+ let id = crypto.randomUUID();
178
+ return ContextManager._instance = new ContextManager(ContextManager.createInstance(conf, id), ContextManager.validateAndGetConfig(conf, id));
179
+ }
180
+ static validateAndGetConfig(conf, instanceId) {
181
+ let host = matchRegex(getStringOrCall(conf?.tracing?.remote?.host), "host", HOST_PATERN);
182
+ let sessionApi = "v4/trace/instance/:id/session";
183
+ let instanceApi = "v4/trace/instance";
184
+ return {
185
+ user: getStringOrCall(conf?.monitoring?.user),
186
+ queueCapacity: requirePostitiveValue(getNumberOrCall(conf?.tracing?.queueCapacity), "queueCapacity", 1000),
187
+ interval: requirePostitiveValue(getNumberOrCall(conf?.scheduling?.interval), "interval", 60000),
188
+ delayIfPending: requirePostitiveValue(getNumberOrCall(conf?.tracing?.delayIfPending), "delayIfPending", 30),
189
+ instanceApi: sessionApiURL(host, instanceApi),
190
+ sessionApi: instanceApiURL(host, sessionApi).replace(':id', instanceId),
191
+ exclude: getRegArrOrCall(conf?.monitoring?.httpRoute?.excludes?.path) || [],
192
+ hostExcludes: conf?.monitoring?.httpRequest?.excludes?.host || [],
193
+ debugMode: conf.debugMode ?? false,
194
+ analytics: conf?.monitoring?.analytics?.enabled ?? false,
195
+ resources: conf?.monitoring?.resources?.enabled ?? false,
196
+ storage: conf?.monitoring?.storage?.enabled ?? false,
197
+ enabled: conf.enabled ?? false
198
+ };
199
+ }
200
+ static createInstance(conf, instanceId) {
201
+ return {
202
+ id: instanceId,
203
+ name: require(getStringOrCall(conf?.monitoring?.name), 'name'),
204
+ version: getStringOrCall(conf?.monitoring?.version),
205
+ address: getSessionAddress(), //server side
206
+ env: require(getStringOrCall(conf?.monitoring?.env), 'env'),
207
+ os: detectOs(),
208
+ re: detectBrowser(),
209
+ user: undefined, // cannot get user
210
+ type: "CLIENT",
211
+ instant: dateNow(),
212
+ collector: "inspect-ng-collector-0.0.1",
213
+ resource: { maxHeap: (('memory' in performance) && performance.memory.jsHeapSizeLimit / (1024 * 1024)) || undefined },
214
+ additionalProperties: conf?.monitoring?.additionalProperties(),
215
+ configuration: adaptedConfig(conf)
216
+ };
217
+ }
218
+ }
219
+ function getSessionAddress() {
220
+ let inspectId = localStorage.getItem("inspect-id");
221
+ if (!inspectId) {
222
+ inspectId = crypto.randomUUID();
223
+ localStorage.setItem("inspect-id", inspectId);
254
224
  }
225
+ return inspectId;
226
+ }
227
+ function instanceApiURL(host, path) {
228
+ return toURL(host, path);
229
+ }
230
+ function sessionApiURL(host, path) {
231
+ return toURL(host, path);
232
+ }
233
+ function toURL(host, path) {
234
+ return host.endsWith(SLASH) || path.startsWith(SLASH) ? host + path : [host, path].join(SLASH);
235
+ }
236
+
237
+ class SessionManager {
255
238
  static get instance() {
239
+ if (!SessionManager._instance) {
240
+ SessionManager._instance = new SessionManager();
241
+ WIN["inspect-session-manager"] = SessionManager._instance;
242
+ }
256
243
  return SessionManager._instance;
257
244
  }
258
- newSession(url) {
259
- if (this.currentSession) {
260
- this.currentSession.end = dateNow();
261
- this.currentSession.name = document.title;
262
- this.currentSession.location = document.URL;
263
- if (this.config.exclude.every((e) => !e.test(this.currentSession.location))) {
264
- this.sessionQueue.push(this.currentSession);
265
- logInspect('app', `added element to session queue, new size is:${this.sessionQueue.length}`);
245
+ navigate(url) {
246
+ this.getCurrentSession(s => {
247
+ if (s) {
248
+ this.getCurrentSessionCallBack(cb => cb.end = dateNow());
249
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { force: !url, traces: this.currentSessionCallBack } }));
266
250
  }
267
- logInspect('app', () => prettySessionFormat(this.currentSession));
268
- }
251
+ this.currentSession = null;
252
+ });
269
253
  if (url) {
254
+ let id = crypto.randomUUID();
270
255
  this.currentSession = {
271
- '@type': "main",
272
- user: this.config.user(),
256
+ '@type': "10",
257
+ id: id,
258
+ user: ContextManager.instance.techConfig.user,
273
259
  start: dateNow(),
274
260
  type: "VIEW",
275
261
  location: url,
276
262
  loading: true,
277
- restRequests: [],
278
- localRequests: [],
279
- userActions: [],
280
- exceptions: []
263
+ requestMask: 0,
264
+ };
265
+ this.currentSessionCallBack = {
266
+ '@type': "11",
267
+ id: id,
268
+ requestMask: 0,
281
269
  };
282
270
  }
283
271
  }
284
- manageCache() {
285
- if (this.instanceEnvironment.id) {
286
- return this.sendSessions();
287
- }
288
- return this.postInstanceEnv().then((id) => {
289
- if (id) {
290
- return this.sendSessions();
272
+ updateSession() {
273
+ this.getCurrentSession(s => {
274
+ s.name = document.title;
275
+ s.location = document.URL;
276
+ if (!ContextManager.instance.techConfig.exclude?.some((e) => e.test(s.location))) {
277
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: s } }));
291
278
  }
292
- console.warn(`Error while attempting to send Environement instance, attempts ${this.sessionSendAttempts}`);
293
- return Promise.reject(new Error('No instance id'));
294
279
  });
295
280
  }
296
- sendSessions(instanceComplete) {
297
- if (this.sessionQueue.length > 0) {
298
- let uri = this.config.sessionApi;
299
- if (instanceComplete) {
300
- uri += "?end=" + new Date().toISOString();
301
- }
302
- this.sessionSendAttempts++;
303
- let sessions = [...this.sessionQueue];
304
- this.sessionQueue.splice(0, sessions.length); // add rest of sessions
305
- logInspect('app', `sending sessions, attempts:${this.sessionSendAttempts}, queue size : ${sessions.length}`);
306
- return this.putSessions(sessions, uri)
307
- .then(ok => {
308
- if (ok) {
309
- logInspect('app', `sessions sent successfully, queue size reset, new size is: ${this.sessionQueue.length}`);
310
- this.sessionSendAttempts = 0;
311
- return sessions.length;
312
- }
313
- else {
314
- console.warn(`Error while attempting to send sessions, attempts: ${this.sessionSendAttempts}`); //
315
- this.revertQueueSize(sessions);
316
- return -1;
317
- }
318
- });
281
+ getCurrentSession(fn) {
282
+ if (this.currentSession) {
283
+ return fn(this.currentSession);
319
284
  }
320
- return Promise.resolve(0);
321
- }
322
- putSessions(sessionList, uri) {
323
- return fetch(uri, {
324
- method: 'PUT',
325
- headers: { 'Content-Type': 'application/json' },
326
- mode: 'cors',
327
- body: JSON.stringify(sessionList)
328
- })
329
- .then(res => res.ok)
330
- .catch(err => false);
331
- }
332
- postInstanceEnv() {
333
- this.sessionSendAttempts++;
334
- return fetch(this.config.instanceApi, {
335
- method: 'POST',
336
- headers: { 'Content-Type': 'application/json' },
337
- mode: 'cors',
338
- body: JSON.stringify(this.instanceEnvironment)
339
- })
340
- .then(res => res.ok ? res.text().then(id => {
341
- this.config.sessionApi = this.config.sessionApi.replace(':id', id);
342
- logInspect('app', 'Environement instance sent successfully', id);
343
- this.sessionSendAttempts = 0;
344
- return this.instanceEnvironment.id = id;
345
- }) : null)
346
- .catch(err => null);
285
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("no active session found ") } }));
286
+ return undefined;
347
287
  }
348
- revertQueueSize(sessions) {
349
- this.sessionQueue.unshift(...sessions);
350
- if (this.sessionQueue.length > this.config.bufferMaxSize) {
351
- let diff = this.sessionQueue.length - this.config.bufferMaxSize;
352
- this.sessionQueue = this.sessionQueue.slice(0, this.config.bufferMaxSize);
353
- logInspect('app', `Buffer size exeeded the max size,last sessions have been removed from buffer, (number of sessions removed):${diff}`);
288
+ getCurrentSessionCallBack(fn) {
289
+ if (this.currentSessionCallBack) {
290
+ return fn(this.currentSessionCallBack);
354
291
  }
292
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("no active session found ") } }));
293
+ return undefined;
355
294
  }
356
- ngOnDestroy() {
357
- if (this.scheduledSessionSender) {
358
- this.scheduledSessionSender.unsubscribe();
359
- }
295
+ currentSessionID() {
296
+ return this.getCurrentSession(s => s.id);
360
297
  }
361
- getCurrentSession() {
362
- return this.currentSession;
298
+ updateMask(requestMask) {
299
+ return this.getCurrentSessionCallBack(s => {
300
+ let before = s.requestMask;
301
+ s.requestMask |= requestMask;
302
+ return s.requestMask !== before;
303
+ });
363
304
  }
364
- resetCurrentSession() {
365
- this.currentSession = null;
305
+ addException(exception) {
306
+ this.getCurrentSessionCallBack(s => s.exception = exception);
366
307
  }
367
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: SessionManager, deps: [{ token: 'config' }, { token: 'instance' }], target: i0.ɵɵFactoryTarget.Injectable }); }
368
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: SessionManager, providedIn: 'root' }); }
369
308
  }
370
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: SessionManager, decorators: [{
371
- type: Injectable,
372
- args: [{ providedIn: 'root' }]
373
- }], ctorParameters: () => [{ type: undefined, decorators: [{
374
- type: Inject,
375
- args: ['config']
376
- }] }, { type: undefined, decorators: [{
377
- type: Inject,
378
- args: ['instance']
379
- }] }] });
380
309
 
381
- class HttpInterceptorService {
382
- constructor(SessionManager) {
383
- this.SessionManager = SessionManager;
384
- } // change this to session manager
385
- intercept(req, next) {
310
+ class RestRequestMonitor {
311
+ constructor(restRequest) {
386
312
  const start = dateNow();
387
- let status, responseBody = '', exception;
388
- let id;
389
- return next.handle(req).pipe(tap$1((event) => {
390
- if (event instanceof HttpResponse) {
391
- status = +event.status;
392
- responseBody = event.body;
393
- id = getReqid(event?.headers);
394
- }
395
- }, error => {
396
- id = getReqid(error?.headers);
397
- if (error) {
398
- status = +error?.status || 0;
399
- exception = {
400
- type: error?.name,
401
- message: error.error && error.status ? JSON.stringify(error.error) : error?.message
402
- };
403
- }
404
- else {
405
- status = 0;
406
- exception = {
407
- type: "IOException",
408
- message: "The remote server is unavailable.",
409
- };
410
- }
411
- }), finalize(() => {
412
- try {
413
- if (this.SessionManager.getCurrentSession()) {
414
- const url = toHref(req.urlWithParams);
415
- const auth_user = extractAuthSchemeAnduser(req.headers);
416
- this.SessionManager.getCurrentSession()?.restRequests.push({
417
- id: id,
418
- method: req.method,
419
- protocol: url.protocol.slice(0, -1),
420
- host: exctractHost(url.host),
421
- port: +url.port || -1,
422
- path: url.pathname,
423
- query: url.search.slice(1, url.search.length),
424
- contentType: req.responseType,
425
- authScheme: auth_user.authScheme,
426
- user: auth_user.user,
427
- status: +status,
428
- inDataSize: sizeOf(responseBody),
429
- ouDataSize: sizeOf(req.body),
430
- start: start,
431
- end: dateNow(),
432
- exception: exception
433
- });
313
+ const url = toHref(restRequest.urlWithParams);
314
+ const auth_user = extractAuthSchemeAnduser(restRequest.headers);
315
+ this.restRequest = {
316
+ "@type": "120",
317
+ id: crypto.randomUUID(),
318
+ method: restRequest.method,
319
+ protocol: url.protocol.slice(0, -1),
320
+ host: exctractHost(url.host),
321
+ port: +url.port || -1,
322
+ path: url.pathname,
323
+ query: url.search.slice(1, url.search.length),
324
+ contentType: restRequest.responseType,
325
+ authScheme: auth_user.authScheme,
326
+ user: auth_user.user,
327
+ dataSize: sizeOf(restRequest.body),
328
+ start: start,
329
+ sessionId: SessionManager.instance.currentSessionID()
330
+ };
331
+ this.restRequestCallBack = {
332
+ "@type": "121",
333
+ id: this.restRequest.id,
334
+ dataSize: -1,
335
+ linked: false
336
+ };
337
+ if (SessionManager.instance.currentSessionID() != null) {
338
+ let doUpdateMask = SessionManager.instance.updateMask(RequestMask.REST);
339
+ doUpdateMask && window.dispatchEvent(new CustomEvent(DISPATCH, { detail: {
340
+ traces: {
341
+ "@type": "03",
342
+ id: SessionManager.instance.currentSessionID(),
343
+ main: true,
344
+ mask: SessionManager.instance.getCurrentSessionCallBack(s => s.requestMask)
345
+ }
434
346
  }
347
+ }));
348
+ }
349
+ }
350
+ postProcess(event, error) {
351
+ let status = 0, exception = null;
352
+ if (event) {
353
+ status = +event.status;
354
+ this.restRequestCallBack.dataSize = sizeOf(event.body);
355
+ this.restRequestCallBack.linked = this.assertSessionID(this.restRequest.id, event.headers);
356
+ }
357
+ if (error) {
358
+ this.restRequestCallBack.linked = error?.headers && this.assertSessionID(this.restRequest.id, error.headers);
359
+ status = +error.status;
360
+ exception = {
361
+ type: error.name,
362
+ message: error.error && error.status ? JSON.stringify(error.error) : error.message
363
+ };
364
+ this.restRequestCallBack.bodyContent = error instanceof HttpErrorResponse ? JSON.stringify(error.error) : undefined;
365
+ this.restRequestCallBack.dataSize = sizeOf(error.error);
366
+ }
367
+ this.restRequestCallBack.contentType = extractContentType(event?.headers);
368
+ this.restRequestCallBack.end = dateNow();
369
+ this.restRequestCallBack.status = +status;
370
+ let stage = {
371
+ "@type": "220",
372
+ name: "PROCESS",
373
+ start: this.restRequest.start, // use request
374
+ end: dateNow(),
375
+ order: 0,
376
+ exception: exception,
377
+ requestId: this.restRequestCallBack.id
378
+ };
379
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: this.restRequestCallBack } }));
380
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: stage } }));
381
+ }
382
+ assertSessionID(id, headers) {
383
+ if (headers?.has('x-tracert')) {
384
+ if (id == headers.get('x-tracert')) {
385
+ return true;
435
386
  }
436
- catch (err) {
437
- console.warn(err);
438
- }
439
- }));
387
+ window.dispatchEvent(new CustomEvent(DISPATCH, {
388
+ detail: { traces: createReport("The received x-tracert header (" + headers.get('x-tracert') + ") does not match the request id (" + id + ")") }
389
+ }));
390
+ }
391
+ return false;
440
392
  }
441
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: HttpInterceptorService, deps: [{ token: SessionManager }], target: i0.ɵɵFactoryTarget.Injectable }); }
442
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: HttpInterceptorService, providedIn: 'root' }); }
443
393
  }
444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: HttpInterceptorService, decorators: [{
445
- type: Injectable,
446
- args: [{ providedIn: 'root' }]
447
- }], ctorParameters: () => [{ type: SessionManager }] });
448
394
  function toHref(url) {
449
395
  const href = document.createElement('a');
450
396
  href.setAttribute('href', url);
@@ -460,7 +406,7 @@ function extractAuthSchemeAnduser(headers) {
460
406
  authScheme: undefined
461
407
  };
462
408
  try {
463
- auth_user.authScheme = headers.get('authorization').match(/^(\w+) /)?.at(1);
409
+ auth_user.authScheme = headers.has('authorization') && headers.get('authorization').match(/^(\w+) /)?.at(1);
464
410
  switch (auth_user.authScheme) {
465
411
  case "Basic":
466
412
  auth_user.user = atob(headers.get('authorization').split(" ")[1]).toString().split(':')[0];
@@ -473,18 +419,254 @@ function extractAuthSchemeAnduser(headers) {
473
419
  }
474
420
  }
475
421
  }
476
- catch (err) { }
422
+ catch (err) {
423
+ createReport(JSON.stringify(err));
424
+ }
477
425
  return auth_user;
478
426
  }
479
- function getReqid(headers) {
480
- return headers?.has('x-tracert')
481
- ? headers.get('x-tracert')
482
- : undefined;
427
+ function extractContentType(headers) {
428
+ try {
429
+ if (headers?.has('Content-Type')) {
430
+ return headers.get('Content-Type');
431
+ }
432
+ }
433
+ catch (err) {
434
+ createReport(JSON.stringify(err));
435
+ }
436
+ return undefined;
483
437
  }
484
438
  function sizeOf(body) {
485
439
  return body ? JSON.stringify(body).length : 0;
486
440
  }
487
441
 
442
+ class HttpInterceptorService {
443
+ constructor() { }
444
+ intercept(req, next) {
445
+ let restRequestMonitor = new RestRequestMonitor(req);
446
+ let e;
447
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: restRequestMonitor.restRequest } }));
448
+ const host = new URL(req.url, window.location.origin).host;
449
+ if (!ContextManager.instance.techConfig.hostExcludes?.some((e) => e == host)) {
450
+ req = req.clone({ headers: req.headers.set('x-tracert', restRequestMonitor.restRequest.id) });
451
+ }
452
+ return next.handle(req).pipe(tap({
453
+ next: (event) => {
454
+ if (event instanceof HttpResponse) {
455
+ e = event;
456
+ }
457
+ },
458
+ error: (error) => {
459
+ e = error;
460
+ },
461
+ unsubscribe: () => {
462
+ e = { status: 0,
463
+ name: "Unsubscribed",
464
+ message: "The request was cancelled before completion."
465
+ };
466
+ }
467
+ }), finalize(() => {
468
+ e instanceof HttpResponse ? restRequestMonitor.postProcess(e, null) : restRequestMonitor.postProcess(null, e ?? {
469
+ status: 0,
470
+ name: "IOException",
471
+ message: "The remote server is unavailable.",
472
+ });
473
+ }));
474
+ }
475
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpInterceptorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
476
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpInterceptorService, providedIn: 'root' }); }
477
+ }
478
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: HttpInterceptorService, decorators: [{
479
+ type: Injectable,
480
+ args: [{ providedIn: 'root' }]
481
+ }], ctorParameters: () => [] });
482
+
483
+ class GlobalErrorHandlerService {
484
+ handleError(error) {
485
+ try {
486
+ SessionManager.instance.addException({
487
+ type: error?.name,
488
+ message: error?.message
489
+ });
490
+ }
491
+ catch (e) {
492
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("Erreur dans GlobalErrorHandlerService: " + JSON.stringify(e)) } }));
493
+ }
494
+ throw error;
495
+ }
496
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: GlobalErrorHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
497
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: GlobalErrorHandlerService, providedIn: 'root' }); }
498
+ }
499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: GlobalErrorHandlerService, decorators: [{
500
+ type: Injectable,
501
+ args: [{ providedIn: 'root' }]
502
+ }] });
503
+
504
+ function eventTraceScheduledDispatcher() {
505
+ return EventTraceScheduledDispatcherService._instance = new EventTraceScheduledDispatcherService();
506
+ }
507
+ class EventTraceScheduledDispatcherService {
508
+ constructor() {
509
+ this.traceQueue = new Set();
510
+ this.sessionSendAttempts = 0;
511
+ this.sendSessionfinished = true;
512
+ this.instanceSaved = false;
513
+ interval(ContextManager.instance.techConfig.interval)
514
+ .pipe(startWith(0))
515
+ .pipe(tap$1(() => {
516
+ if (this.sendSessionfinished) {
517
+ this.sendSessionfinished = false;
518
+ window.dispatchEvent(new CustomEvent(PRE_DISPATCH));
519
+ this.Dispatch()
520
+ .catch(err => { })
521
+ .finally(() => { this.sendSessionfinished = true; });
522
+ }
523
+ }))
524
+ .subscribe();
525
+ window.addEventListener(DISPATCH, (e) => {
526
+ e.detail.traces && this.addtoQueue(e.detail.traces);
527
+ if (e.detail.force) {
528
+ this.sendSessions(true);
529
+ this.onDestroy();
530
+ }
531
+ });
532
+ }
533
+ Dispatch() {
534
+ if (this.instanceSaved) {
535
+ return this.sendSessions();
536
+ }
537
+ return this.postInstanceEnv().then((ok) => {
538
+ if (ok) {
539
+ return this.sendSessions();
540
+ }
541
+ this.sessionSendAttempts % 5 == 0 && console.warn(`Error while attempting to send Environement instance, attempts ${this.sessionSendAttempts}`);
542
+ return Promise.reject(new Error('No instance id'));
543
+ });
544
+ }
545
+ sendSessions(instanceComplete) {
546
+ if (this.traceQueue.size > 0) {
547
+ let uri = ContextManager.instance.techConfig.sessionApi + "?attempts=" + ++this.sessionSendAttempts;
548
+ if (instanceComplete) {
549
+ uri += "&end=" + new Date().toISOString();
550
+ }
551
+ let sessions = this.traceQueue;
552
+ this.traceQueue = new Set();
553
+ return fetch(uri, this.getRequestInit(sessions))
554
+ .then(res => {
555
+ if (res.ok) {
556
+ this.sessionSendAttempts = 0;
557
+ return sessions.size;
558
+ }
559
+ return this.handleEventTraceSavingError(sessions);
560
+ })
561
+ .catch(() => this.handleEventTraceSavingError(sessions));
562
+ }
563
+ return Promise.resolve(0);
564
+ }
565
+ handleEventTraceSavingError(sessions) {
566
+ this.sessionSendAttempts % 5 == 0 && console.warn(`Error while attempting to send sessions, attempts: ${this.sessionSendAttempts}`);
567
+ this.revertQueueSize(sessions);
568
+ return -1;
569
+ }
570
+ getRequestInit(sessionList) {
571
+ return {
572
+ method: 'PUT',
573
+ headers: { 'Content-Type': 'application/json' },
574
+ mode: 'cors',
575
+ body: JSON.stringify(Array.from(sessionList))
576
+ };
577
+ }
578
+ postInstanceEnv() {
579
+ this.sessionSendAttempts++;
580
+ return fetch(ContextManager.instance.techConfig.instanceApi, {
581
+ method: 'POST',
582
+ headers: { 'Content-Type': 'application/json' },
583
+ mode: 'cors',
584
+ body: JSON.stringify(ContextManager.instance.instanceEnv)
585
+ })
586
+ .then(res => res.ok ? res.text().then(id => {
587
+ this.sessionSendAttempts = 0;
588
+ return this.instanceSaved = true;
589
+ }) : false)
590
+ .catch(err => false);
591
+ }
592
+ revertQueueSize(sessions) {
593
+ sessions.forEach(session => this.traceQueue.add(session));
594
+ if (this.traceQueue.size > ContextManager.instance.techConfig.queueCapacity) {
595
+ const items = Array.from(this.traceQueue).slice(0, ContextManager.instance.techConfig.queueCapacity);
596
+ this.traceQueue = new Set(items);
597
+ }
598
+ }
599
+ async addtoQueue(event) {
600
+ try {
601
+ if (event) {
602
+ this.traceQueue.add(event);
603
+ }
604
+ }
605
+ catch (e) {
606
+ this.addtoQueue(createReport(String(e)));
607
+ }
608
+ }
609
+ onDestroy() {
610
+ this.traceQueue.clear();
611
+ this.sendSessionfinished = true;
612
+ this.instanceSaved = false;
613
+ this.sessionSendAttempts = 0;
614
+ }
615
+ }
616
+
617
+ function routeHandler(event) {
618
+ if (event instanceof NavigationStart) {
619
+ SessionManager.instance.navigate(event.url);
620
+ }
621
+ if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
622
+ setTimeout(() => SessionManager.instance.updateSession(), 0);
623
+ }
624
+ }
625
+ function windowUnloadHandler(event) {
626
+ SessionManager.instance.navigate();
627
+ }
628
+ function bfCacheHandler(event) {
629
+ if (event.persisted) { // if the page was restored from bfcache
630
+ ContextManager.init(NgCollectorModule.configuration);
631
+ SessionManager.instance.navigate(document.URL);
632
+ setTimeout(() => SessionManager.instance.updateSession(), 0);
633
+ }
634
+ }
635
+
636
+ function machineRessourceUsageHandler(event) {
637
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: getMemoryInfo() } }));
638
+ }
639
+ function getMemoryInfo() {
640
+ try {
641
+ const memory = performance.memory;
642
+ return {
643
+ '@type': '01',
644
+ instant: dateNow(),
645
+ usedHeap: memory.usedJSHeapSize / (1024 * 1024),
646
+ commitedHeap: memory.totalJSHeapSize / (1024 * 1024),
647
+ };
648
+ }
649
+ catch (e) {
650
+ createReport(JSON.stringify(e));
651
+ }
652
+ return null;
653
+ }
654
+
655
+ function routerEventsListener(router) {
656
+ router.events.subscribe(routeHandler);
657
+ }
658
+ function beforeUnloadListener() {
659
+ window.addEventListener(BEFOREUNLOAD, windowUnloadHandler);
660
+ }
661
+ function beforeDispatchListener() {
662
+ if (ContextManager.instance.techConfig.resources && 'memory' in performance) {
663
+ window.addEventListener(PRE_DISPATCH, machineRessourceUsageHandler);
664
+ }
665
+ }
666
+ function bfCacheListener() {
667
+ window.addEventListener('pageshow', bfCacheHandler);
668
+ }
669
+
488
670
  const genericMap = [
489
671
  t => t.getAttribute('placeholder'),
490
672
  t => t.getAttribute('title'),
@@ -534,125 +716,258 @@ function extractName(t) {
534
716
  return null;
535
717
  }
536
718
 
537
- class AnalyticsCollector {
538
- constructor(document, sessionManager) {
539
- this.document = document;
540
- this.sessionManager = sessionManager;
541
- this.eventHandlers = {
542
- 'click': (target) => this.lookUpChild(target, 1),
543
- };
544
- this.patchedEvent = {};
545
- this.elementsWithClickListeners = new WeakSet();
546
- }
547
- subscribeToEvents() {
548
- const body = this.document.body;
549
- body.addEventListener('click', (event) => this.globalHandler(event), true);
550
- body.addEventListener('change', (event) => this.globalHandler(event), true);
551
- body.addEventListener('scrollend', (event) => this.globalHandler(event), true);
552
- body.addEventListener('dragend', (event) => this.globalHandler(event), true);
553
- this.document.addEventListener('DOMContentLoaded', (event) => this.globalHandler(event), true);
554
- /* let that =this;
555
-
556
- const originalAddEventListener = EventTarget.prototype.addEventListener;
557
- EventTarget.prototype.addEventListener = function(type: string, listener: any, options?: boolean | AddEventListenerOptions) {
558
- if(type === "click"){
559
- that.elementsWithClickListeners.add(this);
560
- const wrapperListener = (event: any) => {
561
- if(that.elementsWithClickListeners.has(event.currentTarget)){
562
- console.log('click event',event);
563
- that.GlobalHandler(event);
564
- }
565
- return listener.apply(this, arguments);
566
- };
567
- return originalAddEventListener.apply(this,[type,wrapperListener,options])
568
- }
569
- return originalAddEventListener.call(this, type, listener, options);
570
- }*/
571
- }
572
- globalHandler(event) {
573
- // event.stopPropagation()
574
- // event.preventDefault()
575
- let target = event.target;
576
- let eventType = event.type;
719
+ let eventHandlers = {
720
+ 'click': (target) => lookUpChild(target, 1),
721
+ };
722
+ function analyticsEventsListener() {
723
+ if (ContextManager.instance.techConfig.analytics) {
577
724
  try {
578
- if (this.eventHandlers.hasOwnProperty(eventType) && !this.eventHandlers[eventType](target)) {
579
- return;
580
- }
581
- this.addActionUser(eventType, target);
725
+ const body = window.document.body;
726
+ body.addEventListener('click', globalHandler, true);
727
+ body.addEventListener('change', (event) => globalHandler(event), true);
728
+ body.addEventListener('scrollend', (event) => globalHandler(event), true);
729
+ body.addEventListener('dragend', (event) => globalHandler(event), true);
730
+ window.document.addEventListener('DOMContentLoaded', (event) => globalHandler(event), true);
582
731
  }
583
- catch (err) {
584
- console.warn(err);
732
+ catch (e) {
733
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("Error while subscribing to analytics user events: " + JSON.stringify(e)) } }));
585
734
  }
586
735
  }
587
- lookUpChild(t, depth) {
588
- if (t.hasChildNodes() && t.children.length <= 5) {
589
- if (++depth > 5) {
590
- return false;
591
- }
592
- return Array.from(t.childNodes).reduce((acc, c) => acc && this.lookUpChild(c, depth), true);
736
+ }
737
+ function globalHandler(event) {
738
+ let target = event.target;
739
+ let eventType = event.type;
740
+ try {
741
+ if (eventHandlers.hasOwnProperty(eventType) && !eventHandlers[eventType](target)) {
742
+ return;
593
743
  }
594
- return true;
744
+ addActionUser(eventType, target);
595
745
  }
596
- addActionUser(eventType, target) {
597
- const ua = {
598
- type: eventType,
599
- start: dateNow(),
600
- name: extractName(target),
601
- nodeName: target.tagName?.toLowerCase(),
602
- };
603
- logInspect('user', () => prettyActionUserFormat(this.sessionManager.getCurrentSession(), ua));
604
- this.sessionManager.getCurrentSession()?.userActions.push(ua);
746
+ catch (err) {
747
+ console.warn(err);
605
748
  }
606
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AnalyticsCollector, deps: [{ token: DOCUMENT }, { token: SessionManager }], target: i0.ɵɵFactoryTarget.Injectable }); }
607
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AnalyticsCollector, providedIn: 'root' }); }
608
749
  }
609
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AnalyticsCollector, decorators: [{
610
- type: Injectable,
611
- args: [{
612
- providedIn: 'root'
613
- }]
614
- }], ctorParameters: () => [{ type: Document, decorators: [{
615
- type: Inject,
616
- args: [DOCUMENT]
617
- }] }, { type: SessionManager }] });
750
+ function lookUpChild(t, depth) {
751
+ if (t.hasChildNodes() && t.children.length <= 5) {
752
+ if (++depth > 5) {
753
+ return false;
754
+ }
755
+ return Array.from(t.childNodes).reduce((acc, c) => acc && lookUpChild(c, depth), true);
756
+ }
757
+ return true;
758
+ }
759
+ function addActionUser(eventType, target) {
760
+ const ua = {
761
+ '@type': "300",
762
+ type: eventType,
763
+ start: dateNow(),
764
+ name: extractName(target),
765
+ nodeName: target.tagName?.toLowerCase(),
766
+ sessionId: SessionManager.instance?.currentSessionID()
767
+ };
768
+ // window.dispatchEvent(new CustomEvent( DISPATCH ,{ detail : { traces:ua }}));
769
+ }
618
770
 
619
- class GlobalErrorHandlerService {
620
- constructor(sessionManager) {
621
- this.sessionManager = sessionManager;
771
+ function eventTraceDebugger() {
772
+ EventTraceDebugger._instance = new EventTraceDebugger();
773
+ }
774
+ class EventTraceDebugger {
775
+ constructor() {
776
+ this.restRequests = [];
777
+ this.httpRequestStages = [];
778
+ this.localRequests = [];
779
+ this.userActions = [];
780
+ this.logEntries = [];
781
+ try {
782
+ if (ContextManager.instance.techConfig.debugMode || WIN['inspect']) {
783
+ window.addEventListener(DISPATCH, this.handleTraces.bind(this));
784
+ }
785
+ WIN["inspect-setup"] = {
786
+ init: () => {
787
+ WIN['inspect'] = true;
788
+ EventTraceDebugger.init();
789
+ },
790
+ printConfig: () => console.log(ContextManager.instance.techConfig),
791
+ printInstance: () => console.log(ContextManager.instance)
792
+ };
793
+ }
794
+ catch (e) {
795
+ console.warn(e);
796
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("Error while setting up debug mode: " + JSON.stringify(e)) } }));
797
+ }
622
798
  }
623
- handleError(error) {
624
- this.sessionManager.getCurrentSession()?.exceptions.push({
625
- type: error?.name,
626
- message: error?.message
799
+ handleTraces(e) {
800
+ let trace = e.detail.traces;
801
+ if (trace && !e.detail.force) {
802
+ switch (trace['@type']) {
803
+ case 'main-ses':
804
+ if (trace.end) {
805
+ console.log(this.prettySessionFormat(SessionManager.instance.currentSession));
806
+ }
807
+ break;
808
+ case 'http-req':
809
+ this.restRequests.push(trace);
810
+ break;
811
+ case 'http-stg':
812
+ this.httpRequestStages.push(trace);
813
+ break;
814
+ case 'user-act':
815
+ this.userActions.push(trace);
816
+ break;
817
+ case 'locl-req':
818
+ this.localRequests.push(trace);
819
+ break;
820
+ case 'log':
821
+ trace.sessionId ? this.logEntries.push(trace) : console.warn(this.prettyLogEntryFormat(trace));
822
+ break;
823
+ case 'rsrc-usg':
824
+ console.log(this.prettyMachineResourceUsageFormat(trace));
825
+ break;
826
+ }
827
+ }
828
+ }
829
+ static init() {
830
+ return EventTraceDebugger._instance = new EventTraceDebugger();
831
+ }
832
+ prettySessionFormat(session) {
833
+ let s = `[${session.name}]`;
834
+ if (session.user) {
835
+ s += `<${session.user}>`;
836
+ }
837
+ if (session.location) {
838
+ s += `(${session.location}) `;
839
+ }
840
+ //s+= this.prettyDurationFormat(session.start, session.end)+'\n';
841
+ s += this.getChildPrint(this.restRequests, this.prettyRestRequestFormat.bind(this));
842
+ s += this.getChildPrint(this.localRequests, this.prettyLocalRequestFormat.bind(this));
843
+ s += this.getChildPrint(this.userActions, this.prettyActionUserFormat.bind(this));
844
+ s += this.getChildPrint(this.logEntries, this.prettyLogEntryFormat.bind(this));
845
+ this.resetList();
846
+ return s;
847
+ }
848
+ prettyRestRequestFormat(rest) {
849
+ let s = ` - [${rest.method}]`;
850
+ if (rest.protocol) {
851
+ s += `${rest.protocol}://`;
852
+ }
853
+ if (rest.host) {
854
+ s += rest.host;
855
+ }
856
+ if (rest.port > 0) {
857
+ s += `:${rest.port}`;
858
+ }
859
+ if (rest.path) {
860
+ if (!rest.path.startsWith("/") && !s.endsWith("/")) {
861
+ s += '/';
862
+ }
863
+ s += rest.path;
864
+ }
865
+ if (rest.query) {
866
+ s += rest.query;
867
+ }
868
+ // s+= ` >> ${rest.status} `
869
+ // s+= this.prettyDurationFormat(rest.start,rest.end);
870
+ s += '\n';
871
+ this.httpRequestStages.filter((s) => s.requestId == rest.id).forEach((stage) => {
872
+ s += this.prettyHttpRequestStageFormat(stage);
627
873
  });
628
- throw error;
874
+ return s;
875
+ }
876
+ prettyHttpRequestStageFormat(stage) {
877
+ let s = ` - [${stage.name}]`;
878
+ s += " >> ";
879
+ if (stage.exception?.type) {
880
+ s += ` ${stage.exception?.type}:`;
881
+ }
882
+ if (stage.exception?.message) {
883
+ s += ` ${stage.exception.message}`;
884
+ }
885
+ s += ` ${this.prettyDurationFormat(stage.start, stage.end)}`;
886
+ return s;
887
+ }
888
+ prettyLocalRequestFormat(local) {
889
+ let s = ` - [${local.name}]`;
890
+ if (local.location) {
891
+ s += `(${local.location})`;
892
+ }
893
+ /*s+= " >> ";
894
+ if(local.exception?.type){
895
+ s+= ` ${local.exception?.type}:`;
896
+ }
897
+ if(local.exception?.message){
898
+ s+= ` ${local.exception.message}`
899
+ }
900
+ s+= ` ${this.prettyDurationFormat(local.start, local.end)}`;*/
901
+ return s;
902
+ }
903
+ prettyLogEntryFormat(log) {
904
+ let s = ` - [${log.level}]`;
905
+ if (log.message) {
906
+ s += ` ${log.message}`;
907
+ }
908
+ s += ` >> ${new Date(log.instant * 1000).toISOString()}`;
909
+ return s;
910
+ }
911
+ prettyMachineResourceUsageFormat(resource) {
912
+ return ` - [METRIC] heap :${resource.usedHeap.toFixed(2)}/${resource.commitedHeap.toFixed(2)} >> ${new Date(resource.instant * 1000).toISOString()}`;
913
+ }
914
+ prettyActionUserFormat(userAction) {
915
+ let s = ` - `;
916
+ if (userAction.type) {
917
+ s += `[${userAction.type}]`;
918
+ }
919
+ if (userAction.nodeName) {
920
+ s += `<${userAction.nodeName}>`;
921
+ }
922
+ if (userAction.name) {
923
+ s += `(${userAction.name}) `;
924
+ }
925
+ s += ` >> ${new Date(userAction.start * 1000).toISOString()}`;
926
+ return s;
927
+ }
928
+ getChildPrint(o, print) {
929
+ let s = "";
930
+ if (o.length) {
931
+ o = o.filter((r) => {
932
+ if (r.sessionId === SessionManager.instance.currentSessionID()) {
933
+ s += print(r) + '\n';
934
+ return false;
935
+ }
936
+ return true;
937
+ });
938
+ const remainingRequests = o.map((r) => print(r)).join('\n');
939
+ if (remainingRequests) {
940
+ console.warn(remainingRequests);
941
+ }
942
+ }
943
+ return s;
944
+ }
945
+ prettyDurationFormat(start, end) {
946
+ return start && end ? `(in ${(end - start).toFixed(2)} s)` : '';
947
+ }
948
+ resetList() {
949
+ this.restRequests = [];
950
+ this.httpRequestStages = [];
951
+ this.localRequests = [];
952
+ this.userActions = [];
629
953
  }
630
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GlobalErrorHandlerService, deps: [{ token: SessionManager }], target: i0.ɵɵFactoryTarget.Injectable }); }
631
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GlobalErrorHandlerService, providedIn: 'root' }); }
632
954
  }
633
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GlobalErrorHandlerService, decorators: [{
634
- type: Injectable,
635
- args: [{ providedIn: 'root' }]
636
- }], ctorParameters: () => [{ type: SessionManager }] });
637
955
 
638
956
  class NgCollectorModule {
957
+ static { this.forRootCalled = false; }
639
958
  static forRoot(configuration) {
640
- if (configuration?.enabled) {
959
+ console.log("forRootCalled");
960
+ this.configuration = configuration;
961
+ if (configuration?.enabled && !NgCollectorModule.forRootCalled) {
962
+ NgCollectorModule.forRootCalled = true;
641
963
  try {
642
- let config = validateAndGetConfig(configuration);
643
- let instance = GetInstanceEnvironement(configuration);
644
- let deps = [Router, SessionManager];
645
- logInspect('app', JSON.stringify(config));
646
- logInspect('app', JSON.stringify(instance));
647
- config.analytics && deps.push(AnalyticsCollector);
964
+ ContextManager.init(configuration);
648
965
  return {
649
966
  ngModule: NgCollectorModule,
650
967
  providers: [
651
- SessionManager,
652
- { provide: APP_INITIALIZER, useFactory: initializeEvents, deps: deps, multi: true },
968
+ //provideAppInitializer(initializeEvents),
969
+ { provide: APP_INITIALIZER, useFactory: initializeEvents, deps: [Router], multi: true },
653
970
  { provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true },
654
- { provide: 'instance', useValue: instance },
655
- { provide: 'config', useValue: config },
656
971
  { provide: ErrorHandler, useClass: GlobalErrorHandlerService }
657
972
  ]
658
973
  };
@@ -665,37 +980,24 @@ class NgCollectorModule {
665
980
  ngModule: NgCollectorModule
666
981
  };
667
982
  }
668
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgCollectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
669
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.9", ngImport: i0, type: NgCollectorModule }); }
670
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgCollectorModule }); }
983
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
984
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule }); }
985
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule }); }
671
986
  }
672
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgCollectorModule, decorators: [{
987
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: NgCollectorModule, decorators: [{
673
988
  type: NgModule
674
989
  }] });
675
- function initializeEvents(router, sessionManager, analyticsCollector) {
990
+ function initializeEvents(router) {
676
991
  return () => {
677
- logInspect('app', 'initialize routing events listeners');
678
- window.addEventListener('beforeunload', event => {
679
- if (!sessionManager.getCurrentSession()?.loading) {
680
- sessionManager.newSession();
681
- }
682
- if (sessionManager.sendSessionfinished) {
683
- sessionManager.sendSessions(true);
684
- sessionManager.resetCurrentSession();
685
- }
686
- });
687
- router.events.subscribe(event => {
688
- if (event instanceof NavigationStart) {
689
- logInspect('app', sessionManager.currentSession);
690
- sessionManager.newSession(event.url);
691
- }
692
- if (event instanceof NavigationEnd) {
693
- delete sessionManager.getCurrentSession()?.loading;
694
- }
695
- });
696
- if (analyticsCollector) {
697
- analyticsCollector.subscribeToEvents();
698
- }
992
+ ContextManager.init(NgCollectorModule.configuration);
993
+ eventTraceScheduledDispatcher();
994
+ eventTraceDebugger();
995
+ analyticsEventsListener();
996
+ //storageEventListener();
997
+ beforeDispatchListener();
998
+ beforeUnloadListener();
999
+ routerEventsListener(router);
1000
+ bfCacheListener();
699
1001
  };
700
1002
  }
701
1003
 
@@ -703,51 +1005,90 @@ function TraceableStage() {
703
1005
  return function (target, propertyKey, descriptor) {
704
1006
  const originalMethod = descriptor.value;
705
1007
  descriptor.value = function (...args) {
706
- if (SessionManager.instance) {
707
- let session = SessionManager.instance.getCurrentSession();
708
- let exception;
709
- let start, end;
710
- start = Date.now();
711
- try {
712
- return originalMethod.apply(this, args);
1008
+ let exception;
1009
+ let start, end;
1010
+ start = Date.now();
1011
+ try {
1012
+ return originalMethod.apply(this, args);
1013
+ }
1014
+ catch (e) {
1015
+ let type = null, message = null;
1016
+ if (e) {
1017
+ if (typeof e === "string") {
1018
+ message = e;
1019
+ }
1020
+ else if (e instanceof Error) {
1021
+ type = e.name;
1022
+ message = e.message;
1023
+ }
1024
+ else {
1025
+ message = JSON.stringify(e);
1026
+ }
713
1027
  }
714
- catch (e) {
715
- let type = null, message = null;
716
- if (e) {
717
- if (typeof e === "string") {
718
- message = e;
1028
+ exception = {
1029
+ type: type,
1030
+ message: message
1031
+ };
1032
+ throw e;
1033
+ }
1034
+ finally {
1035
+ end = Date.now();
1036
+ let id = crypto.randomUUID();
1037
+ if (WIN["inspect-session-manager"]?.currentSessionID() != null) {
1038
+ let doUpdateMask = WIN["inspect-session-manager"]?.updateMask(RequestMask.LOCAL);
1039
+ doUpdateMask && window.dispatchEvent(new CustomEvent(DISPATCH, { detail: {
1040
+ traces: {
1041
+ "@type": "03",
1042
+ id: WIN["inspect-session-manager"]?.currentSessionID(),
1043
+ main: true,
1044
+ mask: WIN["inspect-session-manager"]?.getCurrentSessionCallBack((s) => s.requestMask)
1045
+ }
719
1046
  }
720
- else if (e instanceof Error) {
721
- type = e.name;
722
- message = e.message;
1047
+ }));
1048
+ }
1049
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: {
1050
+ "@type": "110",
1051
+ id: id,
1052
+ name: propertyKey,
1053
+ location: target.constructor.name,
1054
+ user: WIN["inspect-session-manager"]?.currentSession?.user,
1055
+ start: start,
1056
+ sessionId: WIN["inspect-session-manager"]?.currentSession?.id
723
1057
  }
724
- else {
725
- message = JSON.stringify(e);
1058
+ }
1059
+ }));
1060
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: {
1061
+ "@type": "111",
1062
+ id: id,
1063
+ exception: exception,
1064
+ end: end
726
1065
  }
727
1066
  }
728
- exception = {
729
- type: type,
730
- message: message
731
- };
732
- throw e;
733
- }
734
- finally {
735
- end = Date.now();
736
- SessionManager.instance.getCurrentSession()?.localRequests.push({
737
- name: propertyKey,
738
- location: target.constructor.name,
739
- user: session?.user,
740
- start: start,
741
- end: end,
742
- exception: exception
743
- });
744
- }
1067
+ }));
745
1068
  }
746
1069
  };
747
1070
  return descriptor;
748
1071
  };
749
1072
  }
750
1073
 
1074
+ class LogService {
1075
+ static info(message) {
1076
+ if (message) {
1077
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createLogEntry("INFO", message, SessionManager.instance?.currentSessionID()) } }));
1078
+ }
1079
+ }
1080
+ static warn(message) {
1081
+ if (message) {
1082
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createLogEntry("WARN", message, SessionManager.instance?.currentSessionID()) } }));
1083
+ }
1084
+ }
1085
+ static error(message) {
1086
+ if (message) {
1087
+ window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createLogEntry("ERROR", message, SessionManager.instance?.currentSessionID()) } }));
1088
+ }
1089
+ }
1090
+ }
1091
+
751
1092
  /*
752
1093
  * Public API Surface of inspect-ng-collector
753
1094
  */
@@ -756,5 +1097,5 @@ function TraceableStage() {
756
1097
  * Generated bundle index. Do not edit.
757
1098
  */
758
1099
 
759
- export { NgCollectorModule, TraceableStage, initializeEvents };
1100
+ export { LogService, NgCollectorModule, TraceableStage, initializeEvents };
760
1101
  //# sourceMappingURL=oneteme-inspect-ng-collector.mjs.map