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