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