@oneteme/inspect-ng-collector 1.3.0 → 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 +577 -766
- 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 -16
- 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 -4
- 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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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);
|
|
61
|
+
}
|
|
62
|
+
function addReloadListener(fn) {
|
|
63
|
+
eventTarget.addEventListener(RELOAD, fn);
|
|
92
64
|
}
|
|
93
|
-
function
|
|
94
|
-
|
|
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: getStringOrCall(conf?.monitoring?.user),
|
|
186
|
-
queueCapacity: requirePostitiveValue(getNumberOrCall(conf?.tracing?.queueCapacity), "queueCapacity", 1000),
|
|
187
|
-
interval: requirePostitiveValue(getNumberOrCall(conf?.scheduling?.interval), "interval", 60000),
|
|
188
|
-
delayIfPending: requirePostitiveValue(getNumberOrCall(conf?.tracing?.delayIfPending), "delayIfPending", 30),
|
|
189
|
-
instanceApi: sessionApiURL(host, instanceApi),
|
|
190
|
-
sessionApi: instanceApiURL(host, sessionApi).replace(':id', instanceId),
|
|
191
|
-
exclude: getRegArrOrCall(conf?.monitoring?.httpRoute?.excludes?.path) || [],
|
|
192
|
-
hostExcludes: conf?.monitoring?.httpRequest?.excludes?.host || [],
|
|
193
|
-
debugMode: conf.debugMode ?? false,
|
|
194
|
-
analytics: conf?.monitoring?.analytics?.enabled ?? false,
|
|
195
|
-
resources: conf?.monitoring?.resources?.enabled ?? false,
|
|
196
|
-
storage: conf?.monitoring?.storage?.enabled ?? false,
|
|
197
|
-
enabled: conf.enabled ?? false
|
|
198
|
-
};
|
|
199
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: 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,208 +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
|
-
|
|
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.
|
|
521
|
-
.
|
|
522
|
-
.
|
|
531
|
+
if (!this.dispatching && !this.wasDestroyed && this.instance) {
|
|
532
|
+
this.dispatching = true;
|
|
533
|
+
dispatchExport();
|
|
534
|
+
this.dispatch()
|
|
535
|
+
.then(arr => this.revertQueueSize(arr))
|
|
536
|
+
.catch(err => dispatchReport('EventTraceScheduledDispatcher.dispatch', err))
|
|
537
|
+
.finally(() => { this.dispatching = false; });
|
|
523
538
|
}
|
|
524
539
|
}))
|
|
525
540
|
.subscribe();
|
|
526
|
-
|
|
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
|
+
}
|
|
548
|
+
}
|
|
549
|
+
trace(instance) {
|
|
550
|
+
this.instance = instance;
|
|
533
551
|
}
|
|
534
|
-
|
|
535
|
-
if (this.
|
|
536
|
-
return this.
|
|
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
|
-
|
|
549
|
-
if (instanceComplete) {
|
|
550
|
-
uri += "&end=" + new Date().toISOString();
|
|
551
|
-
}
|
|
552
|
-
let sessions = this.traceQueue;
|
|
553
|
-
this.traceQueue = new Set();
|
|
554
|
-
return fetch(uri, this.getRequestInit(sessions))
|
|
555
|
-
.then(res => {
|
|
556
|
-
if (res.ok) {
|
|
557
|
-
this.sessionSendAttempts = 0;
|
|
558
|
-
return sessions.size;
|
|
559
|
-
}
|
|
560
|
-
return this.handleEventTraceSavingError(sessions);
|
|
561
|
-
})
|
|
562
|
-
.catch(() => this.handleEventTraceSavingError(sessions));
|
|
565
|
+
dispatchTraces(destroy) {
|
|
566
|
+
if (this.traceQueue.length === 0) {
|
|
567
|
+
return Promise.resolve(EMPTY_ARRAY);
|
|
563
568
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
this.
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
getRequestInit(sessionList) {
|
|
572
|
-
return {
|
|
569
|
+
let uri = this._techConfig.sessionApi + "?attempts=" + ++this.dispatchAttempts;
|
|
570
|
+
if (destroy) {
|
|
571
|
+
uri += "&end=" + new Date().toISOString();
|
|
572
|
+
}
|
|
573
|
+
const traces = [...this.traceQueue];
|
|
574
|
+
this.traceQueue.length = 0;
|
|
575
|
+
return fetch(uri, {
|
|
573
576
|
method: 'PUT',
|
|
574
577
|
headers: { 'Content-Type': 'application/json' },
|
|
575
578
|
mode: 'cors',
|
|
576
579
|
keepalive: true,
|
|
577
|
-
body: JSON.stringify(
|
|
578
|
-
}
|
|
580
|
+
body: JSON.stringify(traces)
|
|
581
|
+
})
|
|
582
|
+
.then(res => {
|
|
583
|
+
if (res.ok) {
|
|
584
|
+
this.dispatchAttempts = 0;
|
|
585
|
+
return EMPTY_ARRAY;
|
|
586
|
+
}
|
|
587
|
+
console.warn(`Error while attempting to send sessions, attempts: ${this.dispatchAttempts}`);
|
|
588
|
+
if (res.status >= 400 && res.status < 500) {
|
|
589
|
+
return traces; //retry on bad request !?
|
|
590
|
+
}
|
|
591
|
+
return res.json()
|
|
592
|
+
.then(body => body?.retry ? traces : EMPTY_ARRAY)
|
|
593
|
+
.catch(() => EMPTY_ARRAY);
|
|
594
|
+
})
|
|
595
|
+
.catch(() => {
|
|
596
|
+
console.warn(`Error while attempting to send sessions, attempts: ${this.dispatchAttempts}`); //no cnx !
|
|
597
|
+
return traces;
|
|
598
|
+
});
|
|
579
599
|
}
|
|
580
|
-
|
|
581
|
-
this.
|
|
582
|
-
return fetch(
|
|
600
|
+
dispatchInstance() {
|
|
601
|
+
this.dispatchAttempts++;
|
|
602
|
+
return fetch(this._techConfig.instanceApi, {
|
|
583
603
|
method: 'POST',
|
|
584
604
|
headers: { 'Content-Type': 'application/json' },
|
|
585
605
|
mode: 'cors',
|
|
586
606
|
keepalive: true,
|
|
587
|
-
body: JSON.stringify(
|
|
607
|
+
body: JSON.stringify(this.instance)
|
|
588
608
|
})
|
|
589
609
|
.then(res => res.ok ? res.text().then(id => {
|
|
590
|
-
this.
|
|
591
|
-
return
|
|
610
|
+
this.dispatchAttempts = 0;
|
|
611
|
+
return true;
|
|
592
612
|
}) : false)
|
|
593
613
|
.catch(err => false);
|
|
594
614
|
}
|
|
595
|
-
revertQueueSize(
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
async addtoQueue(event) {
|
|
603
|
-
try {
|
|
604
|
-
if (event) {
|
|
605
|
-
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);
|
|
606
620
|
}
|
|
607
621
|
}
|
|
608
|
-
catch (e) {
|
|
609
|
-
this.addtoQueue(createReport(String(e)));
|
|
610
|
-
}
|
|
611
622
|
}
|
|
612
|
-
|
|
613
|
-
this.
|
|
614
|
-
this.
|
|
615
|
-
|
|
616
|
-
this.
|
|
623
|
+
destroy() {
|
|
624
|
+
this.subscription?.unsubscribe();
|
|
625
|
+
this.wasDestroyed = true;
|
|
626
|
+
dispatchExport(); //last metric ??
|
|
627
|
+
this.dispatchTraces(true);
|
|
617
628
|
}
|
|
618
629
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
if (event instanceof NavigationStart) {
|
|
622
|
-
SessionManager.instance.navigate(event.url);
|
|
623
|
-
}
|
|
624
|
-
if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
|
|
625
|
-
setTimeout(() => SessionManager.instance.updateSession(), 0);
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
function windowUnloadHandler(event) {
|
|
629
|
-
SessionManager.instance.navigate();
|
|
630
|
-
}
|
|
631
|
-
function bfCacheHandler(event) {
|
|
632
|
-
if (event.persisted) { // if the page was restored from bfcache
|
|
633
|
-
ContextManager.init(NgCollectorModule.configuration);
|
|
634
|
-
SessionManager.instance.navigate(document.URL);
|
|
635
|
-
setTimeout(() => SessionManager.instance.updateSession(), 0);
|
|
636
|
-
}
|
|
630
|
+
function eventTraceScheduledDispatcher(tech) {
|
|
631
|
+
return EventTraceScheduledDispatcherService._instance = new EventTraceScheduledDispatcherService(tech);
|
|
637
632
|
}
|
|
638
633
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
}
|
|
642
|
-
function
|
|
634
|
+
const eventHandlers = {
|
|
635
|
+
'click': (target) => lookUpChild(target, 1),
|
|
636
|
+
};
|
|
637
|
+
function initUserActionMonitor() {
|
|
643
638
|
try {
|
|
644
|
-
const
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
};
|
|
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);
|
|
651
645
|
}
|
|
652
646
|
catch (e) {
|
|
653
|
-
|
|
647
|
+
dispatchReport("initUserActionMonitor", e);
|
|
654
648
|
}
|
|
655
|
-
return null;
|
|
656
649
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
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
|
+
}
|
|
663
662
|
}
|
|
664
|
-
function
|
|
665
|
-
if (
|
|
666
|
-
|
|
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);
|
|
667
669
|
}
|
|
670
|
+
return true;
|
|
668
671
|
}
|
|
669
|
-
function
|
|
670
|
-
|
|
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
|
+
});
|
|
671
681
|
}
|
|
672
|
-
|
|
673
|
-
const genericMap = [
|
|
674
|
-
t => t.getAttribute('placeholder'),
|
|
675
|
-
t => t.getAttribute('title'),
|
|
676
|
-
t => t.innerText,
|
|
677
|
-
t => t.getAttribute('name'),
|
|
678
|
-
t => t.getAttribute('id'),
|
|
679
|
-
];
|
|
680
|
-
const MAP = {
|
|
681
|
-
'img': [
|
|
682
|
-
t => t.getAttribute('alt'),
|
|
683
|
-
t => t.getAttribute('src'),
|
|
684
|
-
],
|
|
685
|
-
'input': [
|
|
686
|
-
t => t.getAttribute('name'),
|
|
687
|
-
],
|
|
688
|
-
'a': [
|
|
689
|
-
t => t.getAttribute('href'),
|
|
690
|
-
],
|
|
691
|
-
'label': [
|
|
692
|
-
t => t.getAttribute('for'),
|
|
693
|
-
],
|
|
694
|
-
};
|
|
695
682
|
function getFirst(c, t) {
|
|
696
683
|
for (const o of c) {
|
|
697
684
|
let r = o(t)?.trim();
|
|
@@ -718,378 +705,202 @@ function extractName(t) {
|
|
|
718
705
|
}
|
|
719
706
|
return null;
|
|
720
707
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
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
|
+
],
|
|
724
729
|
};
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
try {
|
|
728
|
-
const body = window.document.body;
|
|
729
|
-
body.addEventListener('click', globalHandler, true);
|
|
730
|
-
body.addEventListener('change', (event) => globalHandler(event), true);
|
|
731
|
-
body.addEventListener('scrollend', (event) => globalHandler(event), true);
|
|
732
|
-
body.addEventListener('dragend', (event) => globalHandler(event), true);
|
|
733
|
-
window.document.addEventListener('DOMContentLoaded', (event) => globalHandler(event), true);
|
|
734
|
-
}
|
|
735
|
-
catch (e) {
|
|
736
|
-
window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("Error while subscribing to analytics user events: " + JSON.stringify(e)) } }));
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
function globalHandler(event) {
|
|
741
|
-
let target = event.target;
|
|
742
|
-
let eventType = event.type;
|
|
730
|
+
|
|
731
|
+
function initNavigationMonitor(router) {
|
|
743
732
|
try {
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
addActionUser(eventType, target);
|
|
733
|
+
router.events.subscribe(routeHandler);
|
|
734
|
+
window.addEventListener('pageshow', bfCacheHandler);
|
|
735
|
+
window.addEventListener("beforeunload", windowUnloadHandler);
|
|
748
736
|
}
|
|
749
|
-
catch (
|
|
750
|
-
|
|
737
|
+
catch (e) {
|
|
738
|
+
dispatchReport('initNavigationMonitor', e);
|
|
751
739
|
}
|
|
752
740
|
}
|
|
753
|
-
function
|
|
754
|
-
if (
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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);
|
|
759
747
|
}
|
|
760
|
-
return true;
|
|
761
|
-
}
|
|
762
|
-
function addActionUser(eventType, target) {
|
|
763
|
-
const ua = {
|
|
764
|
-
'@type': "300",
|
|
765
|
-
type: eventType,
|
|
766
|
-
start: dateNow(),
|
|
767
|
-
name: extractName(target),
|
|
768
|
-
nodeName: target.tagName?.toLowerCase(),
|
|
769
|
-
sessionId: SessionManager.instance?.currentSessionID()
|
|
770
|
-
};
|
|
771
|
-
window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: ua } }));
|
|
772
748
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
749
|
+
function windowUnloadHandler(event) {
|
|
750
|
+
SessionManager.instance.navigate();
|
|
751
|
+
dispatchShutown();
|
|
776
752
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
this.userActions = [];
|
|
783
|
-
this.logEntries = [];
|
|
784
|
-
try {
|
|
785
|
-
if (ContextManager.instance.techConfig.debugMode || WIN['inspect']) {
|
|
786
|
-
window.addEventListener(DISPATCH, this.handleTraces.bind(this));
|
|
787
|
-
}
|
|
788
|
-
WIN["inspect-setup"] = {
|
|
789
|
-
init: () => {
|
|
790
|
-
WIN['inspect'] = true;
|
|
791
|
-
EventTraceDebugger.init();
|
|
792
|
-
},
|
|
793
|
-
printConfig: () => console.log(ContextManager.instance.techConfig),
|
|
794
|
-
printInstance: () => console.log(ContextManager.instance)
|
|
795
|
-
};
|
|
796
|
-
}
|
|
797
|
-
catch (e) {
|
|
798
|
-
console.warn(e);
|
|
799
|
-
window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createReport("Error while setting up debug mode: " + JSON.stringify(e)) } }));
|
|
800
|
-
}
|
|
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);
|
|
801
758
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
console.log(this.prettySessionFormat(SessionManager.instance.currentSession));
|
|
809
|
-
}
|
|
810
|
-
break;
|
|
811
|
-
case 'http-req':
|
|
812
|
-
this.restRequests.push(trace);
|
|
813
|
-
break;
|
|
814
|
-
case 'http-stg':
|
|
815
|
-
this.httpRequestStages.push(trace);
|
|
816
|
-
break;
|
|
817
|
-
case 'user-act':
|
|
818
|
-
this.userActions.push(trace);
|
|
819
|
-
break;
|
|
820
|
-
case 'locl-req':
|
|
821
|
-
this.localRequests.push(trace);
|
|
822
|
-
break;
|
|
823
|
-
case 'log':
|
|
824
|
-
trace.sessionId ? this.logEntries.push(trace) : console.warn(this.prettyLogEntryFormat(trace));
|
|
825
|
-
break;
|
|
826
|
-
case 'rsrc-usg':
|
|
827
|
-
console.log(this.prettyMachineResourceUsageFormat(trace));
|
|
828
|
-
break;
|
|
829
|
-
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function initResourceUsageMonitor() {
|
|
762
|
+
try {
|
|
763
|
+
if ('memory' in performance) {
|
|
764
|
+
addExportListener(ressourceUsageHandler);
|
|
830
765
|
}
|
|
831
766
|
}
|
|
832
|
-
|
|
833
|
-
|
|
767
|
+
catch (e) {
|
|
768
|
+
dispatchReport('initResourceUsageMonitor', e);
|
|
834
769
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
s += this.getChildPrint(this.restRequests, this.prettyRestRequestFormat.bind(this));
|
|
845
|
-
s += this.getChildPrint(this.localRequests, this.prettyLocalRequestFormat.bind(this));
|
|
846
|
-
s += this.getChildPrint(this.userActions, this.prettyActionUserFormat.bind(this));
|
|
847
|
-
s += this.getChildPrint(this.logEntries, this.prettyLogEntryFormat.bind(this));
|
|
848
|
-
this.resetList();
|
|
849
|
-
return s;
|
|
850
|
-
}
|
|
851
|
-
prettyRestRequestFormat(rest) {
|
|
852
|
-
let s = ` - [${rest.method}]`;
|
|
853
|
-
if (rest.protocol) {
|
|
854
|
-
s += `${rest.protocol}://`;
|
|
855
|
-
}
|
|
856
|
-
if (rest.host) {
|
|
857
|
-
s += rest.host;
|
|
858
|
-
}
|
|
859
|
-
if (rest.port > 0) {
|
|
860
|
-
s += `:${rest.port}`;
|
|
861
|
-
}
|
|
862
|
-
if (rest.path) {
|
|
863
|
-
if (!rest.path.startsWith("/") && !s.endsWith("/")) {
|
|
864
|
-
s += '/';
|
|
865
|
-
}
|
|
866
|
-
s += rest.path;
|
|
867
|
-
}
|
|
868
|
-
if (rest.query) {
|
|
869
|
-
s += rest.query;
|
|
870
|
-
}
|
|
871
|
-
// s+= ` >> ${rest.status} `
|
|
872
|
-
// s+= this.prettyDurationFormat(rest.start,rest.end);
|
|
873
|
-
s += '\n';
|
|
874
|
-
this.httpRequestStages.filter((s) => s.requestId == rest.id).forEach((stage) => {
|
|
875
|
-
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),
|
|
876
779
|
});
|
|
877
|
-
return s;
|
|
878
|
-
}
|
|
879
|
-
prettyHttpRequestStageFormat(stage) {
|
|
880
|
-
let s = ` - [${stage.name}]`;
|
|
881
|
-
s += " >> ";
|
|
882
|
-
if (stage.exception?.type) {
|
|
883
|
-
s += ` ${stage.exception?.type}:`;
|
|
884
|
-
}
|
|
885
|
-
if (stage.exception?.message) {
|
|
886
|
-
s += ` ${stage.exception.message}`;
|
|
887
|
-
}
|
|
888
|
-
s += ` ${this.prettyDurationFormat(stage.start, stage.end)}`;
|
|
889
|
-
return s;
|
|
890
|
-
}
|
|
891
|
-
prettyLocalRequestFormat(local) {
|
|
892
|
-
let s = ` - [${local.name}]`;
|
|
893
|
-
if (local.location) {
|
|
894
|
-
s += `(${local.location})`;
|
|
895
|
-
}
|
|
896
|
-
/*s+= " >> ";
|
|
897
|
-
if(local.exception?.type){
|
|
898
|
-
s+= ` ${local.exception?.type}:`;
|
|
899
|
-
}
|
|
900
|
-
if(local.exception?.message){
|
|
901
|
-
s+= ` ${local.exception.message}`
|
|
902
|
-
}
|
|
903
|
-
s+= ` ${this.prettyDurationFormat(local.start, local.end)}`;*/
|
|
904
|
-
return s;
|
|
905
|
-
}
|
|
906
|
-
prettyLogEntryFormat(log) {
|
|
907
|
-
let s = ` - [${log.level}]`;
|
|
908
|
-
if (log.message) {
|
|
909
|
-
s += ` ${log.message}`;
|
|
910
|
-
}
|
|
911
|
-
s += ` >> ${new Date(log.instant * 1000).toISOString()}`;
|
|
912
|
-
return s;
|
|
913
|
-
}
|
|
914
|
-
prettyMachineResourceUsageFormat(resource) {
|
|
915
|
-
return ` - [METRIC] heap :${resource.usedHeap.toFixed(2)}/${resource.commitedHeap.toFixed(2)} >> ${new Date(resource.instant * 1000).toISOString()}`;
|
|
916
|
-
}
|
|
917
|
-
prettyActionUserFormat(userAction) {
|
|
918
|
-
let s = ` - `;
|
|
919
|
-
if (userAction.type) {
|
|
920
|
-
s += `[${userAction.type}]`;
|
|
921
|
-
}
|
|
922
|
-
if (userAction.nodeName) {
|
|
923
|
-
s += `<${userAction.nodeName}>`;
|
|
924
|
-
}
|
|
925
|
-
if (userAction.name) {
|
|
926
|
-
s += `(${userAction.name}) `;
|
|
927
|
-
}
|
|
928
|
-
s += ` >> ${new Date(userAction.start * 1000).toISOString()}`;
|
|
929
|
-
return s;
|
|
930
|
-
}
|
|
931
|
-
getChildPrint(o, print) {
|
|
932
|
-
let s = "";
|
|
933
|
-
if (o.length) {
|
|
934
|
-
o = o.filter((r) => {
|
|
935
|
-
if (r.sessionId === SessionManager.instance.currentSessionID()) {
|
|
936
|
-
s += print(r) + '\n';
|
|
937
|
-
return false;
|
|
938
|
-
}
|
|
939
|
-
return true;
|
|
940
|
-
});
|
|
941
|
-
const remainingRequests = o.map((r) => print(r)).join('\n');
|
|
942
|
-
if (remainingRequests) {
|
|
943
|
-
console.warn(remainingRequests);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
return s;
|
|
947
|
-
}
|
|
948
|
-
prettyDurationFormat(start, end) {
|
|
949
|
-
return start && end ? `(in ${(end - start).toFixed(2)} s)` : '';
|
|
950
780
|
}
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
this.httpRequestStages = [];
|
|
954
|
-
this.localRequests = [];
|
|
955
|
-
this.userActions = [];
|
|
781
|
+
catch (e) {
|
|
782
|
+
dispatchReport('ressourceUsageHandler', e);
|
|
956
783
|
}
|
|
957
784
|
}
|
|
958
785
|
|
|
786
|
+
const COLLECTOR_CONFIG = new InjectionToken('COLLECTOR_CONFIG');
|
|
959
787
|
class NgCollectorModule {
|
|
960
|
-
static { this.forRootCalled = false; }
|
|
961
788
|
static forRoot(configuration) {
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
if (configuration?.enabled && !NgCollectorModule.forRootCalled) {
|
|
965
|
-
NgCollectorModule.forRootCalled = true;
|
|
789
|
+
const providers = [];
|
|
790
|
+
if (configuration?.enabled) {
|
|
966
791
|
try {
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
ngModule: NgCollectorModule,
|
|
970
|
-
providers: [
|
|
971
|
-
//provideAppInitializer(initializeEvents),
|
|
972
|
-
{ provide: APP_INITIALIZER, useFactory: initializeEvents, deps: [Router], multi: true },
|
|
973
|
-
{ provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true },
|
|
974
|
-
{ provide: ErrorHandler, useClass: GlobalErrorHandlerService }
|
|
975
|
-
]
|
|
976
|
-
};
|
|
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 });
|
|
977
794
|
}
|
|
978
795
|
catch (e) {
|
|
979
796
|
console.warn(`invalid Configuration, Ng-collector is disabled because of this ${e.message}`);
|
|
980
797
|
}
|
|
981
798
|
}
|
|
982
|
-
return {
|
|
983
|
-
ngModule: NgCollectorModule
|
|
984
|
-
};
|
|
799
|
+
return { ngModule: NgCollectorModule, providers: providers };
|
|
985
800
|
}
|
|
986
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.
|
|
987
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.
|
|
988
|
-
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 }); }
|
|
989
804
|
}
|
|
990
|
-
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: [{
|
|
991
806
|
type: NgModule
|
|
992
807
|
}] });
|
|
993
|
-
function
|
|
808
|
+
function initializeEventsFactory(config, router) {
|
|
994
809
|
return () => {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
810
|
+
if (config.tech.analytics) {
|
|
811
|
+
initUserActionMonitor();
|
|
812
|
+
}
|
|
813
|
+
if (config.tech.resources) {
|
|
814
|
+
initResourceUsageMonitor();
|
|
815
|
+
}
|
|
816
|
+
initNavigationMonitor(router);
|
|
999
817
|
//storageEventListener();
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
818
|
+
//eventTraceDebugger
|
|
819
|
+
addReloadListener(e => {
|
|
820
|
+
reloadCollector(config);
|
|
821
|
+
});
|
|
1004
822
|
};
|
|
1005
823
|
}
|
|
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
|
+
}
|
|
866
|
+
}
|
|
1006
867
|
|
|
1007
868
|
function TraceableStage() {
|
|
1008
869
|
return function (target, propertyKey, descriptor) {
|
|
1009
870
|
const originalMethod = descriptor.value;
|
|
1010
871
|
descriptor.value = function (...args) {
|
|
872
|
+
const monitor = new LocalRequestMonitor();
|
|
1011
873
|
let exception;
|
|
1012
|
-
let start, end;
|
|
1013
|
-
start = Date.now();
|
|
1014
874
|
try {
|
|
875
|
+
monitor.preProcess(propertyKey, target);
|
|
1015
876
|
return originalMethod.apply(this, args);
|
|
1016
877
|
}
|
|
1017
878
|
catch (e) {
|
|
1018
|
-
|
|
1019
|
-
if (e) {
|
|
1020
|
-
if (typeof e === "string") {
|
|
1021
|
-
message = e;
|
|
1022
|
-
}
|
|
1023
|
-
else if (e instanceof Error) {
|
|
1024
|
-
type = e.name;
|
|
1025
|
-
message = e.message;
|
|
1026
|
-
}
|
|
1027
|
-
else {
|
|
1028
|
-
message = JSON.stringify(e);
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
exception = {
|
|
1032
|
-
type: type,
|
|
1033
|
-
message: message
|
|
1034
|
-
};
|
|
879
|
+
exception = resolveException(e);
|
|
1035
880
|
throw e;
|
|
1036
881
|
}
|
|
1037
882
|
finally {
|
|
1038
|
-
|
|
1039
|
-
let id = crypto.randomUUID();
|
|
1040
|
-
if (WIN["inspect-session-manager"]?.currentSessionID() != null) {
|
|
1041
|
-
let doUpdateMask = WIN["inspect-session-manager"]?.updateMask(RequestMask.LOCAL);
|
|
1042
|
-
doUpdateMask && window.dispatchEvent(new CustomEvent(DISPATCH, { detail: {
|
|
1043
|
-
traces: {
|
|
1044
|
-
"@type": "03",
|
|
1045
|
-
id: WIN["inspect-session-manager"]?.currentSessionID(),
|
|
1046
|
-
main: true,
|
|
1047
|
-
mask: WIN["inspect-session-manager"]?.getCurrentSessionCallBack((s) => s.requestMask)
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
}));
|
|
1051
|
-
}
|
|
1052
|
-
window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: {
|
|
1053
|
-
"@type": "110",
|
|
1054
|
-
id: id,
|
|
1055
|
-
name: propertyKey,
|
|
1056
|
-
location: target.constructor.name,
|
|
1057
|
-
user: WIN["inspect-session-manager"]?.currentSession?.user,
|
|
1058
|
-
start: start,
|
|
1059
|
-
sessionId: WIN["inspect-session-manager"]?.currentSession?.id
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
}));
|
|
1063
|
-
window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: {
|
|
1064
|
-
"@type": "111",
|
|
1065
|
-
id: id,
|
|
1066
|
-
exception: exception,
|
|
1067
|
-
end: end
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
}));
|
|
883
|
+
monitor.postProcess(exception);
|
|
1071
884
|
}
|
|
1072
885
|
};
|
|
1073
886
|
return descriptor;
|
|
1074
887
|
};
|
|
1075
888
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
if (
|
|
1080
|
-
|
|
889
|
+
function resolveException(e) {
|
|
890
|
+
let type = null, message = null;
|
|
891
|
+
if (e) {
|
|
892
|
+
if (typeof e === "string") {
|
|
893
|
+
message = e;
|
|
1081
894
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
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;
|
|
1086
898
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
if (message) {
|
|
1090
|
-
window.dispatchEvent(new CustomEvent(DISPATCH, { detail: { traces: createLogEntry("ERROR", message, SessionManager.instance?.currentSessionID()) } }));
|
|
899
|
+
else {
|
|
900
|
+
message = JSON.stringify(e);
|
|
1091
901
|
}
|
|
1092
902
|
}
|
|
903
|
+
return { type, message };
|
|
1093
904
|
}
|
|
1094
905
|
|
|
1095
906
|
/*
|
|
@@ -1100,5 +911,5 @@ class LogService {
|
|
|
1100
911
|
* Generated bundle index. Do not edit.
|
|
1101
912
|
*/
|
|
1102
913
|
|
|
1103
|
-
export {
|
|
914
|
+
export { NgCollectorModule, TraceableStage, initializeCollector, initializeEventsFactory, reloadCollector, resolveException, sessionlogger };
|
|
1104
915
|
//# sourceMappingURL=oneteme-inspect-ng-collector.mjs.map
|