@module-federation/observability-plugin 0.0.0-alpha.0 → 0.0.0-chore-bump-node-22-20260710161714
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/LICENSE +21 -0
- package/README.md +219 -39
- package/dist/CHANGELOG.md +43 -0
- package/dist/README.md +219 -39
- package/dist/browser.d.ts +6 -0
- package/dist/browser.js +11 -0
- package/dist/build.js +2 -1
- package/dist/chrome-devtool.d.ts +6 -0
- package/dist/chrome-devtool.js +20 -0
- package/dist/core--1ofIHU9.js +2042 -0
- package/dist/core-Db-z5jD3.d.ts +335 -0
- package/dist/esm/browser.js +9 -0
- package/dist/esm/build.js +1 -1
- package/dist/esm/chrome-devtool.js +18 -0
- package/dist/esm/core-4ykFjWWj.js +2036 -0
- package/dist/esm/index.js +4 -1441
- package/dist/esm/node.js +8 -5
- package/dist/index.d.ts +4 -269
- package/dist/index.js +8 -1443
- package/dist/node.d.ts +4 -3
- package/dist/node.js +10 -5
- package/package.json +22 -7
- package/AI_TROUBLESHOOTING.md +0 -498
- package/dist/AI_TROUBLESHOOTING.md +0 -498
|
@@ -0,0 +1,2042 @@
|
|
|
1
|
+
const require_build = require('./build.js');
|
|
2
|
+
let _module_federation_sdk = require("@module-federation/sdk");
|
|
3
|
+
|
|
4
|
+
//#region src/core.ts
|
|
5
|
+
const DEFAULT_MAX_EVENTS = 100;
|
|
6
|
+
const HARD_MAX_EVENTS = 1e3;
|
|
7
|
+
const DEFAULT_COLLECTOR_PORT = 17891;
|
|
8
|
+
const COLLECTOR_PATH = "/__mf_observability";
|
|
9
|
+
const logger = (0, _module_federation_sdk.createLogger)("[ Module Federation Observability Plugin ]");
|
|
10
|
+
const DEFAULT_DEVTOOLS_SOURCE = "module-federation/observability";
|
|
11
|
+
const COMPONENT_BUSINESS_LOADED_EVENT = "component:business-loaded";
|
|
12
|
+
const ON_MF_REMOTE_LOADED_PROP = "onMFRemoteLoaded";
|
|
13
|
+
const SENSITIVE_PAIR_PATTERN = /\b(token|authorization|cookie|secret|password|session|access_token|refresh_token|api_key|apikey|key)\s*[:=]\s*([^&\s'",;<>]+)/gi;
|
|
14
|
+
const ERROR_CODE_PATTERN = /\b(?:RUNTIME|TYPE|BUILD)-\d{3}\b/;
|
|
15
|
+
const URL_PATTERN = /https?:\/\/[^\s'"<>]+/g;
|
|
16
|
+
const DIAGNOSTIC_DOC_LINK_PATTERN = /https?:\/\/module-federation\.io\/guide\/troubleshooting\/[^\s'"<>]+/i;
|
|
17
|
+
const RUNTIME_DOC_LINK = "https://module-federation.io/guide/troubleshooting/runtime";
|
|
18
|
+
const MAX_METADATA_KEYS = 20;
|
|
19
|
+
const MAX_FACT_KEYS = 50;
|
|
20
|
+
const MAX_MODULE_INFO_ENTRIES = 20;
|
|
21
|
+
const HARD_MAX_REPORT_QUERY_LIMIT = 1e3;
|
|
22
|
+
let traceCounter = 0;
|
|
23
|
+
function isRecord(value) {
|
|
24
|
+
return typeof value === "object" && value !== null;
|
|
25
|
+
}
|
|
26
|
+
function normalizeMaxEvents(value, fallback) {
|
|
27
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
28
|
+
return Math.max(1, Math.min(HARD_MAX_EVENTS, Math.floor(value)));
|
|
29
|
+
}
|
|
30
|
+
function normalizeQueryLimit(value) {
|
|
31
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return;
|
|
32
|
+
return Math.max(1, Math.min(HARD_MAX_REPORT_QUERY_LIMIT, Math.floor(value)));
|
|
33
|
+
}
|
|
34
|
+
function normalizeCollectorPort(value) {
|
|
35
|
+
if (!Number.isFinite(value) || !value) return DEFAULT_COLLECTOR_PORT;
|
|
36
|
+
const port = Math.floor(value);
|
|
37
|
+
return port > 0 && port <= 65535 ? port : DEFAULT_COLLECTOR_PORT;
|
|
38
|
+
}
|
|
39
|
+
function normalizeCollectorOptions(value) {
|
|
40
|
+
if (value === true) return {
|
|
41
|
+
enabled: true,
|
|
42
|
+
port: DEFAULT_COLLECTOR_PORT
|
|
43
|
+
};
|
|
44
|
+
if (!value || value === false || value.enabled === false) return;
|
|
45
|
+
return {
|
|
46
|
+
enabled: true,
|
|
47
|
+
port: normalizeCollectorPort(value.port)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function normalizeDevtoolsOptions(value) {
|
|
51
|
+
if (value === true) return {
|
|
52
|
+
enabled: true,
|
|
53
|
+
source: DEFAULT_DEVTOOLS_SOURCE
|
|
54
|
+
};
|
|
55
|
+
if (!value || value === false || value.enabled === false) return;
|
|
56
|
+
return {
|
|
57
|
+
enabled: true,
|
|
58
|
+
source: sanitizeText(value.source, 160) || DEFAULT_DEVTOOLS_SOURCE
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function getCollectorUrl(port) {
|
|
62
|
+
return `http://127.0.0.1:${port}${COLLECTOR_PATH}`;
|
|
63
|
+
}
|
|
64
|
+
function sanitizeText(value, maxLength = 800) {
|
|
65
|
+
if (value === void 0 || value === null) return;
|
|
66
|
+
const sanitized = String(value).replace(URL_PATTERN, (url) => sanitizeUrl(url) || "[redacted-url]").replace(SENSITIVE_PAIR_PATTERN, "[redacted]");
|
|
67
|
+
return sanitized.length > maxLength ? `${sanitized.slice(0, maxLength)}...` : sanitized;
|
|
68
|
+
}
|
|
69
|
+
function getRawText(value) {
|
|
70
|
+
if (value === void 0 || value === null) return;
|
|
71
|
+
return String(value);
|
|
72
|
+
}
|
|
73
|
+
function clipText(value, maxLength = 320) {
|
|
74
|
+
if (value === void 0 || value === null) return;
|
|
75
|
+
const sanitized = String(value);
|
|
76
|
+
return sanitized.length > maxLength ? `${sanitized.slice(0, maxLength)}...` : sanitized;
|
|
77
|
+
}
|
|
78
|
+
function clipObservabilityMetadata(metadata, maxKeys = MAX_METADATA_KEYS) {
|
|
79
|
+
if (!metadata || typeof metadata !== "object") return;
|
|
80
|
+
const clipped = {};
|
|
81
|
+
Object.entries(metadata).slice(0, maxKeys).forEach(([rawKey, rawValue]) => {
|
|
82
|
+
const key = clipText(rawKey, 80);
|
|
83
|
+
if (!key || rawValue === void 0 || rawValue === null) return;
|
|
84
|
+
if (typeof rawValue === "boolean") {
|
|
85
|
+
clipped[key] = rawValue;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (typeof rawValue === "number") {
|
|
89
|
+
if (Number.isFinite(rawValue)) clipped[key] = rawValue;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const value = clipText(rawValue, 240);
|
|
93
|
+
if (value) clipped[key] = value;
|
|
94
|
+
});
|
|
95
|
+
return Object.keys(clipped).length ? clipped : void 0;
|
|
96
|
+
}
|
|
97
|
+
function clipMetadata(metadata, maxKeys = MAX_METADATA_KEYS) {
|
|
98
|
+
if (!metadata || typeof metadata !== "object") return;
|
|
99
|
+
const clipped = {};
|
|
100
|
+
Object.entries(metadata).slice(0, maxKeys).forEach(([rawKey, rawValue]) => {
|
|
101
|
+
const key = sanitizeText(rawKey, 80);
|
|
102
|
+
if (!key || rawValue === void 0 || rawValue === null) return;
|
|
103
|
+
if (typeof rawValue === "boolean") {
|
|
104
|
+
clipped[key] = rawValue;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (typeof rawValue === "number") {
|
|
108
|
+
if (Number.isFinite(rawValue)) clipped[key] = rawValue;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const value = clipText(rawValue, 240);
|
|
112
|
+
if (value) clipped[key] = value;
|
|
113
|
+
});
|
|
114
|
+
return Object.keys(clipped).length ? clipped : void 0;
|
|
115
|
+
}
|
|
116
|
+
function sanitizeStack(stack, options) {
|
|
117
|
+
if (!stack || options?.enabled === false) return;
|
|
118
|
+
return stack;
|
|
119
|
+
}
|
|
120
|
+
function getRawStack(error) {
|
|
121
|
+
if (error instanceof Error) return error.stack || error.message;
|
|
122
|
+
}
|
|
123
|
+
function sanitizeRequestId(value) {
|
|
124
|
+
if (!value) return;
|
|
125
|
+
return clipText(value, 240);
|
|
126
|
+
}
|
|
127
|
+
function sanitizeUrl(value) {
|
|
128
|
+
if (!value) return;
|
|
129
|
+
try {
|
|
130
|
+
const base = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
|
|
131
|
+
const parsedUrl = new URL(value, base);
|
|
132
|
+
const sanitized = `${parsedUrl.origin}${parsedUrl.pathname}`;
|
|
133
|
+
return /^https?:\/\//i.test(value) ? sanitized : parsedUrl.pathname;
|
|
134
|
+
} catch {
|
|
135
|
+
const [withoutHash] = value.split("#");
|
|
136
|
+
const [withoutQuery] = withoutHash.split("?");
|
|
137
|
+
return sanitizeText(withoutQuery, 240);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function sanitizeRemote(remote) {
|
|
141
|
+
if (!remote || !remote.name) return;
|
|
142
|
+
return {
|
|
143
|
+
name: remote.name,
|
|
144
|
+
alias: sanitizeText(remote.alias, 120),
|
|
145
|
+
entry: clipText(remote.entry, 320),
|
|
146
|
+
entryGlobalName: sanitizeText(remote.entryGlobalName, 120),
|
|
147
|
+
type: sanitizeText(remote.type, 80)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function createRemoteInfo(remote) {
|
|
151
|
+
if (!remote?.name) return;
|
|
152
|
+
return {
|
|
153
|
+
name: remote.name,
|
|
154
|
+
alias: remote.alias,
|
|
155
|
+
entry: remote.entry,
|
|
156
|
+
entryGlobalName: remote.entryGlobalName,
|
|
157
|
+
type: remote.type
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function isManifestUrl(value) {
|
|
161
|
+
const sanitized = sanitizeUrl(value);
|
|
162
|
+
return Boolean(sanitized && /manifest.*\.json$/i.test(sanitized));
|
|
163
|
+
}
|
|
164
|
+
function normalizeSharedScope(value) {
|
|
165
|
+
if (!value) return [];
|
|
166
|
+
return (Array.isArray(value) ? value : [value]).map((scope) => sanitizeText(scope, 120)).filter((scope) => Boolean(scope));
|
|
167
|
+
}
|
|
168
|
+
function getSharedScopes(shareInfo) {
|
|
169
|
+
return normalizeSharedScope(shareInfo?.scope).length ? normalizeSharedScope(shareInfo?.scope) : ["default"];
|
|
170
|
+
}
|
|
171
|
+
function getAvailableSharedVersions(args) {
|
|
172
|
+
const versions = /* @__PURE__ */ new Set();
|
|
173
|
+
const shareScopeMap = args.shareScopeMap || {};
|
|
174
|
+
getSharedScopes(args.shareInfo).forEach((scope) => {
|
|
175
|
+
Object.keys(shareScopeMap[scope]?.[args.pkgName] || {}).forEach((version) => {
|
|
176
|
+
versions.add(version);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
return Array.from(versions);
|
|
180
|
+
}
|
|
181
|
+
function getSharedMissReason(args) {
|
|
182
|
+
if (!args.shareInfo) return "missing-config";
|
|
183
|
+
return getAvailableSharedVersions(args).length ? "version-mismatch" : "missing-provider";
|
|
184
|
+
}
|
|
185
|
+
function getSharedErrorReason(args) {
|
|
186
|
+
if (args.recovered) return getSharedMissReason(args);
|
|
187
|
+
const errorMessage = getErrorInfo(args.error, { enabled: false }).errorMessage || "";
|
|
188
|
+
if (!args.shareInfo || /Cannot find shared/i.test(errorMessage)) return "missing-config";
|
|
189
|
+
if (args.lifecycle === "loadShareSync" && typeof args.shareInfo.get === "function" && /RUNTIME-00[56]/.test(errorMessage)) return "sync-async-boundary";
|
|
190
|
+
if (args.lifecycle === "loadShareSync" && !args.shareInfo.get && /RUNTIME-006/.test(errorMessage)) return getSharedMissReason(args);
|
|
191
|
+
if (args.error) return "load-error";
|
|
192
|
+
}
|
|
193
|
+
function parseStableVersion(version) {
|
|
194
|
+
const matched = version?.match(/^(\d+)\.(\d+)\.(\d+)(?:\+[\w.-]+)?$/);
|
|
195
|
+
if (!matched) return;
|
|
196
|
+
return {
|
|
197
|
+
major: Number(matched[1]),
|
|
198
|
+
minor: Number(matched[2]),
|
|
199
|
+
patch: Number(matched[3])
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function isVersionAtLeast(version, target) {
|
|
203
|
+
if (version.major !== target.major) return version.major > target.major;
|
|
204
|
+
if (version.minor !== target.minor) return version.minor > target.minor;
|
|
205
|
+
return version.patch >= target.patch;
|
|
206
|
+
}
|
|
207
|
+
function supportsRuntimeObservability(origin) {
|
|
208
|
+
const version = parseStableVersion(origin?.version);
|
|
209
|
+
if (!version) return false;
|
|
210
|
+
return isVersionAtLeast(version, {
|
|
211
|
+
major: 2,
|
|
212
|
+
minor: 5,
|
|
213
|
+
patch: 0
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function createSharedInfo(args, reason) {
|
|
217
|
+
const shareConfig = args.shareInfo?.shareConfig;
|
|
218
|
+
return {
|
|
219
|
+
name: args.pkgName,
|
|
220
|
+
shareScope: getSharedScopes(args.shareInfo),
|
|
221
|
+
requiredVersion: shareConfig?.requiredVersion,
|
|
222
|
+
selectedVersion: args.selectedShared?.version,
|
|
223
|
+
availableVersions: getAvailableSharedVersions(args),
|
|
224
|
+
provider: args.selectedShared?.from,
|
|
225
|
+
from: args.shareInfo?.from,
|
|
226
|
+
singleton: shareConfig?.singleton,
|
|
227
|
+
strictVersion: shareConfig?.strictVersion,
|
|
228
|
+
eager: shareConfig?.eager,
|
|
229
|
+
strategy: args.shareInfo?.strategy,
|
|
230
|
+
loaded: args.selectedShared?.loaded,
|
|
231
|
+
loading: Boolean(args.selectedShared?.loading) || void 0,
|
|
232
|
+
reason
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function sanitizeShared(shared) {
|
|
236
|
+
if (!shared || !shared.name) return;
|
|
237
|
+
return {
|
|
238
|
+
name: sanitizeText(shared.name, 160) || "unknown",
|
|
239
|
+
shareScope: normalizeSharedScope(shared.shareScope),
|
|
240
|
+
requiredVersion: shared.requiredVersion === false ? false : sanitizeText(shared.requiredVersion, 120),
|
|
241
|
+
selectedVersion: sanitizeText(shared.selectedVersion, 120),
|
|
242
|
+
availableVersions: (shared.availableVersions || []).map((version) => sanitizeText(version, 120)).filter((version) => Boolean(version)).slice(0, 20),
|
|
243
|
+
provider: sanitizeText(shared.provider, 160),
|
|
244
|
+
from: sanitizeText(shared.from, 160),
|
|
245
|
+
singleton: shared.singleton,
|
|
246
|
+
strictVersion: shared.strictVersion,
|
|
247
|
+
eager: shared.eager,
|
|
248
|
+
strategy: sanitizeText(shared.strategy, 80),
|
|
249
|
+
loaded: shared.loaded,
|
|
250
|
+
loading: shared.loading,
|
|
251
|
+
reason: sanitizeText(shared.reason, 120)
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function getObjectValue(value, key) {
|
|
255
|
+
return value[key];
|
|
256
|
+
}
|
|
257
|
+
function isReactLike(value) {
|
|
258
|
+
if (!isRecord(value)) return false;
|
|
259
|
+
return typeof getObjectValue(value, "createElement") === "function";
|
|
260
|
+
}
|
|
261
|
+
function resolveReactLike(value) {
|
|
262
|
+
if (isReactLike(value)) return value;
|
|
263
|
+
if (isRecord(value)) {
|
|
264
|
+
const defaultExport = getObjectValue(value, "default");
|
|
265
|
+
if (isReactLike(defaultExport)) return defaultExport;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function getReactComponentName(component, fallback) {
|
|
269
|
+
if (typeof component === "function") return component.displayName || component.name || fallback;
|
|
270
|
+
if (!isRecord(component)) return fallback;
|
|
271
|
+
const displayName = getObjectValue(component, "displayName");
|
|
272
|
+
if (typeof displayName === "string" && displayName) return displayName;
|
|
273
|
+
const render = getObjectValue(component, "render");
|
|
274
|
+
if (typeof render === "function") return render.displayName || render.name || fallback;
|
|
275
|
+
return fallback;
|
|
276
|
+
}
|
|
277
|
+
function isLikelyReactFunctionComponent(component, allowAnonymousComponent = false) {
|
|
278
|
+
if (typeof component !== "function") return false;
|
|
279
|
+
const name = component.displayName || component.name || "";
|
|
280
|
+
if (/^use[A-Z0-9]/.test(name)) return false;
|
|
281
|
+
if (allowAnonymousComponent) return true;
|
|
282
|
+
if (!name) return false;
|
|
283
|
+
return /^[A-Z]/.test(name);
|
|
284
|
+
}
|
|
285
|
+
function copyComponentStatics(target, source) {
|
|
286
|
+
const reserved = new Set([
|
|
287
|
+
"arguments",
|
|
288
|
+
"caller",
|
|
289
|
+
"length",
|
|
290
|
+
"name",
|
|
291
|
+
"prototype",
|
|
292
|
+
"displayName"
|
|
293
|
+
]);
|
|
294
|
+
Object.getOwnPropertyNames(source).forEach((key) => {
|
|
295
|
+
if (reserved.has(key)) return;
|
|
296
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
297
|
+
if (!descriptor || !descriptor.configurable) return;
|
|
298
|
+
try {
|
|
299
|
+
Object.defineProperty(target, key, descriptor);
|
|
300
|
+
} catch {}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function cloneModuleWithDefaultExport(moduleExports, defaultExport) {
|
|
304
|
+
const descriptors = Object.getOwnPropertyDescriptors(moduleExports);
|
|
305
|
+
descriptors.default = {
|
|
306
|
+
configurable: true,
|
|
307
|
+
enumerable: descriptors.default?.enumerable ?? true,
|
|
308
|
+
writable: true,
|
|
309
|
+
value: defaultExport
|
|
310
|
+
};
|
|
311
|
+
return Object.defineProperties(Object.create(Object.getPrototypeOf(moduleExports)), descriptors);
|
|
312
|
+
}
|
|
313
|
+
function resolveReactComponentTarget(component, defaultExportMode = "preserve", allowAnonymousComponent = false) {
|
|
314
|
+
if (isLikelyReactFunctionComponent(component, allowAnonymousComponent)) return {
|
|
315
|
+
component,
|
|
316
|
+
createResult: (wrappedComponent) => wrappedComponent
|
|
317
|
+
};
|
|
318
|
+
if (!isRecord(component)) return;
|
|
319
|
+
const defaultExport = getObjectValue(component, "default");
|
|
320
|
+
if (!isLikelyReactFunctionComponent(defaultExport, allowAnonymousComponent)) return;
|
|
321
|
+
return {
|
|
322
|
+
component: defaultExport,
|
|
323
|
+
createResult: (wrappedComponent) => {
|
|
324
|
+
const descriptor = Object.getOwnPropertyDescriptor(component, "default");
|
|
325
|
+
let defaultExportReplaced = false;
|
|
326
|
+
try {
|
|
327
|
+
if (!descriptor || descriptor.writable || descriptor.set) {
|
|
328
|
+
component.default = wrappedComponent;
|
|
329
|
+
defaultExportReplaced = true;
|
|
330
|
+
} else if (descriptor.configurable) {
|
|
331
|
+
Object.defineProperty(component, "default", {
|
|
332
|
+
configurable: true,
|
|
333
|
+
enumerable: descriptor.enumerable,
|
|
334
|
+
writable: true,
|
|
335
|
+
value: wrappedComponent
|
|
336
|
+
});
|
|
337
|
+
defaultExportReplaced = true;
|
|
338
|
+
}
|
|
339
|
+
} catch {}
|
|
340
|
+
if (defaultExportMode === "component") return wrappedComponent;
|
|
341
|
+
return defaultExportReplaced ? void 0 : cloneModuleWithDefaultExport(component, wrappedComponent);
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function normalizeEventSource(value) {
|
|
346
|
+
return value === "runtime" || value === "business" || value === "react" ? value : void 0;
|
|
347
|
+
}
|
|
348
|
+
function extractErrorCode(value) {
|
|
349
|
+
const matched = String(value ?? "").match(ERROR_CODE_PATTERN)?.[0];
|
|
350
|
+
return matched ? sanitizeText(matched, 40) : void 0;
|
|
351
|
+
}
|
|
352
|
+
function getErrorInfo(error, stackTraceOptions) {
|
|
353
|
+
if (!error) return {};
|
|
354
|
+
if (error instanceof Error) return {
|
|
355
|
+
errorCode: extractErrorCode(`${error.name}\n${error.message}\n${error.stack || ""}`),
|
|
356
|
+
errorName: getRawText(error.name),
|
|
357
|
+
errorMessage: getRawText(error.message),
|
|
358
|
+
errorStack: sanitizeStack(error.stack, stackTraceOptions)
|
|
359
|
+
};
|
|
360
|
+
return {
|
|
361
|
+
errorCode: extractErrorCode(error),
|
|
362
|
+
errorMessage: getRawText(error)
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function omitUndefinedFields(value) {
|
|
366
|
+
if (Array.isArray(value)) return value.map((item) => omitUndefinedFields(item));
|
|
367
|
+
if (!value || typeof value !== "object") return value;
|
|
368
|
+
const cleanValue = {};
|
|
369
|
+
Object.entries(value).forEach(([key, item]) => {
|
|
370
|
+
if (item === void 0) return;
|
|
371
|
+
cleanValue[key] = omitUndefinedFields(item);
|
|
372
|
+
});
|
|
373
|
+
return cleanValue;
|
|
374
|
+
}
|
|
375
|
+
function copyEvent(event) {
|
|
376
|
+
return omitUndefinedFields({
|
|
377
|
+
...event,
|
|
378
|
+
remote: event.remote ? { ...event.remote } : void 0,
|
|
379
|
+
shared: event.shared ? {
|
|
380
|
+
...event.shared,
|
|
381
|
+
shareScope: event.shared.shareScope ? [...event.shared.shareScope] : void 0,
|
|
382
|
+
availableVersions: event.shared.availableVersions ? [...event.shared.availableVersions] : void 0
|
|
383
|
+
} : void 0,
|
|
384
|
+
errorContext: event.errorContext ? { ...event.errorContext } : void 0,
|
|
385
|
+
metadata: event.metadata ? { ...event.metadata } : void 0,
|
|
386
|
+
loadedBefore: copyLoadedBeforeInfo(event.loadedBefore)
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
function copySummary(summary) {
|
|
390
|
+
return {
|
|
391
|
+
...summary,
|
|
392
|
+
phases: Object.entries(summary.phases).reduce((memo, [phase, phaseSummary]) => {
|
|
393
|
+
memo[phase] = { ...phaseSummary };
|
|
394
|
+
return memo;
|
|
395
|
+
}, {}),
|
|
396
|
+
shared: summary.shared ? {
|
|
397
|
+
...summary.shared,
|
|
398
|
+
shareScope: summary.shared.shareScope ? [...summary.shared.shareScope] : void 0
|
|
399
|
+
} : void 0,
|
|
400
|
+
flags: { ...summary.flags },
|
|
401
|
+
error: summary.error ? {
|
|
402
|
+
...summary.error,
|
|
403
|
+
context: summary.error.context ? { ...summary.error.context } : void 0
|
|
404
|
+
} : void 0
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function copyFactReport(diagnosis) {
|
|
408
|
+
if (!diagnosis) return;
|
|
409
|
+
return {
|
|
410
|
+
...diagnosis,
|
|
411
|
+
facts: { ...diagnosis.facts },
|
|
412
|
+
completedPhases: [...diagnosis.completedPhases],
|
|
413
|
+
pendingPhases: [...diagnosis.pendingPhases],
|
|
414
|
+
warnings: diagnosis.warnings ? [...diagnosis.warnings] : void 0,
|
|
415
|
+
actions: diagnosis.actions.map((action) => ({ ...action }))
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
function copyModuleInfoSummary(moduleInfo) {
|
|
419
|
+
if (!moduleInfo) return;
|
|
420
|
+
return {
|
|
421
|
+
...moduleInfo,
|
|
422
|
+
entries: moduleInfo.entries.map((entry) => ({ ...entry })),
|
|
423
|
+
availableNames: moduleInfo.availableNames ? [...moduleInfo.availableNames] : void 0
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
function copyLoadedBeforeInfo(loadedBefore) {
|
|
427
|
+
if (!loadedBefore) return;
|
|
428
|
+
return {
|
|
429
|
+
producer: loadedBefore.producer,
|
|
430
|
+
expose: loadedBefore.expose,
|
|
431
|
+
consumers: loadedBefore.consumers.map((consumer) => ({
|
|
432
|
+
...consumer,
|
|
433
|
+
exposes: consumer.exposes ? [...consumer.exposes] : void 0
|
|
434
|
+
}))
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function copyReport(report) {
|
|
438
|
+
return omitUndefinedFields({
|
|
439
|
+
...report,
|
|
440
|
+
remote: report.remote ? { ...report.remote } : void 0,
|
|
441
|
+
shared: report.shared ? {
|
|
442
|
+
...report.shared,
|
|
443
|
+
shareScope: report.shared.shareScope ? [...report.shared.shareScope] : void 0,
|
|
444
|
+
availableVersions: report.shared.availableVersions ? [...report.shared.availableVersions] : void 0
|
|
445
|
+
} : void 0,
|
|
446
|
+
errorContext: report.errorContext ? { ...report.errorContext } : void 0,
|
|
447
|
+
moduleInfo: copyModuleInfoSummary(report.moduleInfo),
|
|
448
|
+
loadedBefore: copyLoadedBeforeInfo(report.loadedBefore),
|
|
449
|
+
events: report.events.map(copyEvent),
|
|
450
|
+
summary: copySummary(report.summary),
|
|
451
|
+
diagnosis: copyFactReport(report.diagnosis)
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
function getFederationGlobal() {
|
|
455
|
+
return globalThis.__FEDERATION__;
|
|
456
|
+
}
|
|
457
|
+
function normalizeExposeName(value) {
|
|
458
|
+
const sanitized = sanitizeText(value, 240);
|
|
459
|
+
if (!sanitized) return;
|
|
460
|
+
return sanitized.replace(/^\.\//, "");
|
|
461
|
+
}
|
|
462
|
+
function getModuleCacheEntries(moduleCache) {
|
|
463
|
+
if (!moduleCache) return [];
|
|
464
|
+
if (moduleCache instanceof Map) return Array.from(moduleCache.values());
|
|
465
|
+
const entries = typeof moduleCache.entries === "function" ? Array.from(moduleCache.entries()) : void 0;
|
|
466
|
+
if (entries) return entries.map(([, value]) => value);
|
|
467
|
+
if (isRecord(moduleCache)) return Object.values(moduleCache);
|
|
468
|
+
return [];
|
|
469
|
+
}
|
|
470
|
+
function getLoadedExposesForRemote(instance, remoteName) {
|
|
471
|
+
if (!remoteName) return [];
|
|
472
|
+
return Array.from(new Set(Object.values(instance.remoteHandler?.idToRemoteMap || {}).filter((item) => item?.name === remoteName).map((item) => sanitizeText(item.expose, 240)).filter((expose) => Boolean(expose))));
|
|
473
|
+
}
|
|
474
|
+
function collectLoadedBeforeInfo(remote, expose, origin) {
|
|
475
|
+
const entryGlobalName = remote?.entryGlobalName;
|
|
476
|
+
if (!entryGlobalName) return;
|
|
477
|
+
const federation = getFederationGlobal();
|
|
478
|
+
const instances = Array.isArray(federation?.__INSTANCES__) ? federation.__INSTANCES__ : [];
|
|
479
|
+
const targetExpose = normalizeExposeName(expose);
|
|
480
|
+
const consumers = [];
|
|
481
|
+
instances.forEach((instance) => {
|
|
482
|
+
if (instance === origin) return;
|
|
483
|
+
const matchedModule = getModuleCacheEntries(instance.moduleCache).find((item) => isRecord(item) && isRecord(item.remoteInfo) && item.remoteInfo.entryGlobalName === entryGlobalName);
|
|
484
|
+
if (!matchedModule) return;
|
|
485
|
+
const exposes = getLoadedExposesForRemote(instance, matchedModule.remoteInfo?.name);
|
|
486
|
+
const consumer = {
|
|
487
|
+
name: sanitizeText(instance.options?.name, 120) || sanitizeText(instance.name, 120),
|
|
488
|
+
remoteEntryExports: Boolean(matchedModule.remoteEntryExports),
|
|
489
|
+
containerInitialized: matchedModule.inited === true,
|
|
490
|
+
exposes: exposes.length ? exposes : void 0
|
|
491
|
+
};
|
|
492
|
+
consumers.push(omitUndefinedFields(consumer));
|
|
493
|
+
});
|
|
494
|
+
if (!consumers.length) return;
|
|
495
|
+
return {
|
|
496
|
+
producer: true,
|
|
497
|
+
expose: targetExpose ? consumers.some((consumer) => (consumer.exposes || []).some((loadedExpose) => normalizeExposeName(loadedExpose) === targetExpose)) : false,
|
|
498
|
+
consumers
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
function normalizeScope(value) {
|
|
502
|
+
return sanitizeText(value, 120)?.replace(/[^\w:@.-]+/g, "-") || "default";
|
|
503
|
+
}
|
|
504
|
+
function shouldRecordEvent(level, event) {
|
|
505
|
+
if (level === "verbose") return true;
|
|
506
|
+
if (level === "summary") return event.status !== "start";
|
|
507
|
+
return event.status === "error" || Boolean(event.error);
|
|
508
|
+
}
|
|
509
|
+
function createTraceId(event) {
|
|
510
|
+
traceCounter += 1;
|
|
511
|
+
return `mf-${(event.remote?.name || event.phase || "runtime").replace(/[^a-z0-9]+/gi, "-").slice(0, 80)}-${Date.now().toString(36)}-${traceCounter.toString(36)}`;
|
|
512
|
+
}
|
|
513
|
+
function getPhaseDurationKey(event) {
|
|
514
|
+
const exposeKey = event.phase === "expose" || event.phase === "moduleFactory" ? event.expose || "" : "";
|
|
515
|
+
return [
|
|
516
|
+
event.traceId,
|
|
517
|
+
event.phase,
|
|
518
|
+
event.requestId || event.remote?.name || event.shared?.name || "",
|
|
519
|
+
exposeKey
|
|
520
|
+
].join("|");
|
|
521
|
+
}
|
|
522
|
+
function getRemoteEntryKey(remote) {
|
|
523
|
+
if (!remote?.name) return;
|
|
524
|
+
return [
|
|
525
|
+
remote.name,
|
|
526
|
+
remote.entryGlobalName || "",
|
|
527
|
+
remote.entry || ""
|
|
528
|
+
].join("|");
|
|
529
|
+
}
|
|
530
|
+
function getHostRemotesSummary(options) {
|
|
531
|
+
const remotes = (options?.remotes || []).map((remote) => clipText(remote.alias || remote.name || remote.entry, 120)).filter((remote) => Boolean(remote)).slice(0, 20);
|
|
532
|
+
return remotes.length ? remotes.join(",") : void 0;
|
|
533
|
+
}
|
|
534
|
+
function resolveRemoteFromRequestId(id, options) {
|
|
535
|
+
if (!id) return;
|
|
536
|
+
const matchedRemote = (options?.remotes || []).filter((remote) => {
|
|
537
|
+
return [remote.alias, remote.name].filter((key) => Boolean(key)).some((key) => id === key || id.startsWith(`${key}/`));
|
|
538
|
+
}).sort((left, right) => {
|
|
539
|
+
const leftKey = left.alias || left.name || "";
|
|
540
|
+
return (right.alias || right.name || "").length - leftKey.length;
|
|
541
|
+
})[0];
|
|
542
|
+
return createRemoteInfo(matchedRemote);
|
|
543
|
+
}
|
|
544
|
+
function resolveAliasRequestId(requestId, remote) {
|
|
545
|
+
if (!requestId || !remote?.alias || remote.alias === remote.name) return;
|
|
546
|
+
if (requestId === remote.name) return remote.alias;
|
|
547
|
+
if (requestId.startsWith(`${remote.name}/`)) return `${remote.alias}/${requestId.slice(remote.name.length + 1)}`;
|
|
548
|
+
}
|
|
549
|
+
function sanitizeModuleInfoPath(value) {
|
|
550
|
+
if (typeof value !== "string") return;
|
|
551
|
+
return clipText(value, 320);
|
|
552
|
+
}
|
|
553
|
+
function sanitizeModuleInfoGetPublicPath(value) {
|
|
554
|
+
if (typeof value !== "string") return;
|
|
555
|
+
return clipText(value, 500);
|
|
556
|
+
}
|
|
557
|
+
function sanitizeModuleInfoRemoteEntry(value) {
|
|
558
|
+
if (typeof value !== "string") return;
|
|
559
|
+
return clipText(value, 320);
|
|
560
|
+
}
|
|
561
|
+
function createClippedModuleInfoEntry(rawName, rawValue) {
|
|
562
|
+
const name = clipText(rawName, 240);
|
|
563
|
+
if (!name) return;
|
|
564
|
+
const value = isRecord(rawValue) ? rawValue : {};
|
|
565
|
+
return {
|
|
566
|
+
name,
|
|
567
|
+
publicPath: sanitizeModuleInfoPath(value["publicPath"]),
|
|
568
|
+
getPublicPath: sanitizeModuleInfoGetPublicPath(value["getPublicPath"]),
|
|
569
|
+
remoteEntry: sanitizeModuleInfoRemoteEntry(value["remoteEntry"]),
|
|
570
|
+
globalName: sanitizeText(value["globalName"], 160)
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
function normalizeModuleInfoLookupValue(value) {
|
|
574
|
+
if (typeof value !== "string" || !value) return;
|
|
575
|
+
return (/^https?:\/\//i.test(value) || value.startsWith("/") ? sanitizeUrl(value) : sanitizeText(value, 240))?.toLowerCase();
|
|
576
|
+
}
|
|
577
|
+
function getModuleInfoLookupValues(report) {
|
|
578
|
+
return new Set([
|
|
579
|
+
report.requestId?.split("/")[0],
|
|
580
|
+
report.remote?.name,
|
|
581
|
+
report.remote?.alias,
|
|
582
|
+
report.remote?.entry,
|
|
583
|
+
report.remote?.entryGlobalName,
|
|
584
|
+
report.sanitizedUrl,
|
|
585
|
+
report.errorContext?.["remoteName"],
|
|
586
|
+
report.errorContext?.["remoteAlias"],
|
|
587
|
+
report.errorContext?.["url"],
|
|
588
|
+
report.summary.error?.context?.["remoteName"],
|
|
589
|
+
report.summary.error?.context?.["remoteAlias"],
|
|
590
|
+
report.summary.error?.context?.["url"]
|
|
591
|
+
].map(normalizeModuleInfoLookupValue).filter((value) => Boolean(value)));
|
|
592
|
+
}
|
|
593
|
+
function matchesModuleInfoLookup(entry, lookupValues) {
|
|
594
|
+
if (!lookupValues.size) return false;
|
|
595
|
+
return [
|
|
596
|
+
entry.name,
|
|
597
|
+
entry.publicPath,
|
|
598
|
+
entry.getPublicPath,
|
|
599
|
+
entry.remoteEntry,
|
|
600
|
+
entry.globalName
|
|
601
|
+
].map(normalizeModuleInfoLookupValue).filter((value) => Boolean(value)).some((entryValue) => Array.from(lookupValues).some((lookupValue) => entryValue === lookupValue || entryValue.startsWith(`${lookupValue}:`) || entryValue.includes(`:${lookupValue}`) || lookupValue.startsWith("http") && entryValue.includes(lookupValue)));
|
|
602
|
+
}
|
|
603
|
+
function getModuleInfoCaptureReason(report) {
|
|
604
|
+
const text = [
|
|
605
|
+
report.errorCode,
|
|
606
|
+
report.errorName,
|
|
607
|
+
report.errorMessage,
|
|
608
|
+
report.summary.error?.errorCode,
|
|
609
|
+
report.summary.error?.errorName,
|
|
610
|
+
report.summary.error?.errorMessage,
|
|
611
|
+
...report.events.flatMap((event) => [
|
|
612
|
+
event.errorCode,
|
|
613
|
+
event.errorName,
|
|
614
|
+
event.errorMessage,
|
|
615
|
+
event.message,
|
|
616
|
+
event.lifecycle
|
|
617
|
+
])
|
|
618
|
+
].join("\n");
|
|
619
|
+
if (/RUNTIME-007/.test(text)) return "remote-snapshot";
|
|
620
|
+
if (/RUNTIME-011/.test(text)) return "remote-entry-missing-in-snapshot";
|
|
621
|
+
if (/moduleInfo|module info/i.test(text)) return "module-info";
|
|
622
|
+
if (/remote snapshot|global snapshot|snapshot/i.test(text)) return "remote-snapshot";
|
|
623
|
+
}
|
|
624
|
+
function createModuleInfoSummary(report) {
|
|
625
|
+
const reason = getModuleInfoCaptureReason(report);
|
|
626
|
+
if (!reason) return;
|
|
627
|
+
const moduleInfo = getFederationGlobal()?.moduleInfo;
|
|
628
|
+
const rawEntries = isRecord(moduleInfo) ? Object.entries(moduleInfo) : [];
|
|
629
|
+
const clippedEntries = rawEntries.map(([name, value]) => createClippedModuleInfoEntry(name, value)).filter((entry) => Boolean(entry));
|
|
630
|
+
const lookupValues = getModuleInfoLookupValues(report);
|
|
631
|
+
const matchedEntries = clippedEntries.filter((entry) => matchesModuleInfoLookup(entry, lookupValues));
|
|
632
|
+
return {
|
|
633
|
+
reason,
|
|
634
|
+
clipped: true,
|
|
635
|
+
totalCount: rawEntries.length,
|
|
636
|
+
matchedCount: matchedEntries.length,
|
|
637
|
+
entries: matchedEntries.slice(0, MAX_MODULE_INFO_ENTRIES),
|
|
638
|
+
availableNames: matchedEntries.length ? void 0 : clippedEntries.map((entry) => entry.name).slice(0, MAX_MODULE_INFO_ENTRIES)
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
function getResourceErrorType(event) {
|
|
642
|
+
const text = `${event.errorMessage || ""}\n${event.message || ""}`;
|
|
643
|
+
if (!event.errorCode && !text) return;
|
|
644
|
+
if (/ScriptExecutionError/i.test(text)) return "script-execution";
|
|
645
|
+
if (/timeout|timed out/i.test(text)) return "timeout";
|
|
646
|
+
if (/ScriptNetworkError|NetworkError|Failed to fetch|Request failed|ERR_|404|CORS/i.test(text)) return "network";
|
|
647
|
+
return event.errorCode === "RUNTIME-008" ? "unknown" : void 0;
|
|
648
|
+
}
|
|
649
|
+
function getOwnerHint(event) {
|
|
650
|
+
const resourceErrorType = getResourceErrorType(event);
|
|
651
|
+
switch (event.errorCode) {
|
|
652
|
+
case "RUNTIME-001":
|
|
653
|
+
case "RUNTIME-002":
|
|
654
|
+
case "RUNTIME-011":
|
|
655
|
+
case "RUNTIME-013":
|
|
656
|
+
case "RUNTIME-014":
|
|
657
|
+
case "RUNTIME-015": return "remote";
|
|
658
|
+
case "RUNTIME-003":
|
|
659
|
+
case "RUNTIME-004":
|
|
660
|
+
case "RUNTIME-007": return "host";
|
|
661
|
+
case "RUNTIME-005":
|
|
662
|
+
case "RUNTIME-006":
|
|
663
|
+
case "RUNTIME-012": return "shared";
|
|
664
|
+
case "RUNTIME-008": return resourceErrorType === "network" || resourceErrorType === "timeout" ? "network" : "remote";
|
|
665
|
+
default:
|
|
666
|
+
if (event.shared) return "shared";
|
|
667
|
+
if (event.remote) return "remote";
|
|
668
|
+
if (event.phase === "manifest" || event.phase === "matchRemote") return "host";
|
|
669
|
+
return event.errorCode ? "runtime" : void 0;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
function getRetryable(event) {
|
|
673
|
+
const resourceErrorType = getResourceErrorType(event);
|
|
674
|
+
if (event.errorCode === "RUNTIME-008") return resourceErrorType === "network" || resourceErrorType === "timeout";
|
|
675
|
+
if (event.errorCode === "RUNTIME-003") {
|
|
676
|
+
const text = `${event.errorMessage || ""}\n${event.message || ""}`;
|
|
677
|
+
return /NetworkError|Failed to fetch|Request failed|timeout|timed out/i.test(text);
|
|
678
|
+
}
|
|
679
|
+
if (event.errorCode && [
|
|
680
|
+
"RUNTIME-001",
|
|
681
|
+
"RUNTIME-002",
|
|
682
|
+
"RUNTIME-004",
|
|
683
|
+
"RUNTIME-005",
|
|
684
|
+
"RUNTIME-006",
|
|
685
|
+
"RUNTIME-011",
|
|
686
|
+
"RUNTIME-012",
|
|
687
|
+
"RUNTIME-013",
|
|
688
|
+
"RUNTIME-014",
|
|
689
|
+
"RUNTIME-015"
|
|
690
|
+
].includes(event.errorCode)) return false;
|
|
691
|
+
}
|
|
692
|
+
function createErrorContext(event, inputContext) {
|
|
693
|
+
const context = { ...inputContext };
|
|
694
|
+
if (event.lifecycle) context.lifecycle = event.lifecycle;
|
|
695
|
+
if (event.requestId) context.requestId = event.requestId;
|
|
696
|
+
if (event.requestAlias) context.requestAlias = event.requestAlias;
|
|
697
|
+
if (event.remote?.name) context.remoteName = event.remote.name;
|
|
698
|
+
if (event.remote?.alias) context.remoteAlias = event.remote.alias;
|
|
699
|
+
if (event.remote?.type) context.remoteType = event.remote.type;
|
|
700
|
+
if (event.remote?.entryGlobalName) context.entryGlobalName = event.remote.entryGlobalName;
|
|
701
|
+
if (event.sanitizedUrl) context.url = event.sanitizedUrl;
|
|
702
|
+
if (event.expose) context.expose = event.expose;
|
|
703
|
+
if (event.shared?.name) context.shareName = event.shared.name;
|
|
704
|
+
if (event.shared?.requiredVersion) context.requiredVersion = event.shared.requiredVersion;
|
|
705
|
+
if (event.shared?.selectedVersion) context.selectedVersion = event.shared.selectedVersion;
|
|
706
|
+
if (event.shared?.provider) context.provider = event.shared.provider;
|
|
707
|
+
const resourceErrorType = getResourceErrorType(event);
|
|
708
|
+
if (resourceErrorType) context.resourceErrorType = resourceErrorType;
|
|
709
|
+
return clipObservabilityMetadata(context);
|
|
710
|
+
}
|
|
711
|
+
function createObservability(rawOptions = {}, adapterOptions = {}) {
|
|
712
|
+
const options = {
|
|
713
|
+
...rawOptions,
|
|
714
|
+
browser: adapterOptions.fixedBrowserScope ? {
|
|
715
|
+
...rawOptions.browser,
|
|
716
|
+
scope: adapterOptions.fixedBrowserScope
|
|
717
|
+
} : rawOptions.browser,
|
|
718
|
+
react: adapterOptions.disableReact ? {
|
|
719
|
+
...rawOptions.react,
|
|
720
|
+
enabled: false,
|
|
721
|
+
injectLoadedCallback: false
|
|
722
|
+
} : rawOptions.react
|
|
723
|
+
};
|
|
724
|
+
const pluginName = adapterOptions.pluginName || "observability-plugin";
|
|
725
|
+
const shouldAttachInstanceApi = adapterOptions.attachInstanceApi !== false;
|
|
726
|
+
const shouldGuardSharedHooksByRuntimeVersion = adapterOptions.guardSharedHooksByRuntimeVersion === true;
|
|
727
|
+
const shouldGuardRuntimeHooksByRuntimeVersion = adapterOptions.guardRuntimeHooksByRuntimeVersion === true;
|
|
728
|
+
const shouldDisablePreloadHooks = adapterOptions.disablePreloadHooks === true;
|
|
729
|
+
const shouldReturnHookArgs = adapterOptions.returnHookArgs === true;
|
|
730
|
+
const shouldForceDevelopmentChannels = adapterOptions.forceDevelopmentChannels === true;
|
|
731
|
+
const returnHookArgs = (args) => shouldReturnHookArgs ? args : void 0;
|
|
732
|
+
const level = options.level || "summary";
|
|
733
|
+
const configuredMaxEvents = normalizeMaxEvents(options.maxEvents, DEFAULT_MAX_EVENTS);
|
|
734
|
+
const events = [];
|
|
735
|
+
const reports = /* @__PURE__ */ new Map();
|
|
736
|
+
const traceByRequest = /* @__PURE__ */ new Map();
|
|
737
|
+
const traceByRemote = /* @__PURE__ */ new Map();
|
|
738
|
+
const phaseStartTimes = /* @__PURE__ */ new Map();
|
|
739
|
+
const collectorOptions = normalizeCollectorOptions(options.collector);
|
|
740
|
+
const devtoolsOptions = normalizeDevtoolsOptions(options.devtools);
|
|
741
|
+
const seenManifestUrls = /* @__PURE__ */ new Set();
|
|
742
|
+
const loadingManifestUrls = /* @__PURE__ */ new Set();
|
|
743
|
+
const seenRemoteEntryKeys = /* @__PURE__ */ new Set();
|
|
744
|
+
const consoleReportedTraceIds = /* @__PURE__ */ new Set();
|
|
745
|
+
const consoleReportedStartKeys = /* @__PURE__ */ new Set();
|
|
746
|
+
let latestTraceId;
|
|
747
|
+
let runtimeObservabilityEnabled = false;
|
|
748
|
+
let suppressRuntimeEvents = false;
|
|
749
|
+
let effectiveMaxEvents = configuredMaxEvents;
|
|
750
|
+
let browserGlobalScope;
|
|
751
|
+
let lastRuntimeOrigin;
|
|
752
|
+
let appliedRuntimeVersion;
|
|
753
|
+
const isEnabled = () => {
|
|
754
|
+
if (options.enabled === false) return false;
|
|
755
|
+
runtimeObservabilityEnabled = true;
|
|
756
|
+
return true;
|
|
757
|
+
};
|
|
758
|
+
const resolveTraceId = (event) => {
|
|
759
|
+
const sanitizedRequestId = sanitizeRequestId(event.requestId);
|
|
760
|
+
if (event.traceId && reports.has(event.traceId)) return event.traceId;
|
|
761
|
+
if (event.status === "start" && event.phase === "loadRemote") {
|
|
762
|
+
const traceId = event.traceId || createTraceId(event);
|
|
763
|
+
if (sanitizedRequestId) traceByRequest.set(sanitizedRequestId, traceId);
|
|
764
|
+
if (event.remote?.name) traceByRemote.set(event.remote.name, traceId);
|
|
765
|
+
return traceId;
|
|
766
|
+
}
|
|
767
|
+
if (sanitizedRequestId) {
|
|
768
|
+
const traceId = traceByRequest.get(sanitizedRequestId);
|
|
769
|
+
if (traceId) return traceId;
|
|
770
|
+
}
|
|
771
|
+
if (event.remote?.name) {
|
|
772
|
+
const traceId = traceByRemote.get(event.remote.name);
|
|
773
|
+
if (traceId) return traceId;
|
|
774
|
+
}
|
|
775
|
+
return event.traceId || createTraceId(event);
|
|
776
|
+
};
|
|
777
|
+
const normalizeEvent = (event, traceId, origin) => {
|
|
778
|
+
const errorInfo = getErrorInfo(event.error, options.stackTrace);
|
|
779
|
+
const sanitizedRemote = sanitizeRemote(event.remote);
|
|
780
|
+
const sanitizedShared = sanitizeShared(event.shared);
|
|
781
|
+
const requestAlias = sanitizeRequestId(event.requestAlias) || resolveAliasRequestId(event.requestId, sanitizedRemote);
|
|
782
|
+
const hostName = sanitizeText(event.hostName, 120) || sanitizeText(origin?.options?.name, 120);
|
|
783
|
+
const runtimeVersion = sanitizeText(origin?.version, 80) || appliedRuntimeVersion;
|
|
784
|
+
const message = getRawText(event.message) || errorInfo.errorMessage;
|
|
785
|
+
const normalizedEvent = {
|
|
786
|
+
traceId,
|
|
787
|
+
timestamp: event.timestamp || Date.now(),
|
|
788
|
+
phase: sanitizeText(event.phase, 120) || "runtime",
|
|
789
|
+
status: event.status,
|
|
790
|
+
requestId: sanitizeRequestId(event.requestId),
|
|
791
|
+
requestAlias,
|
|
792
|
+
hostName,
|
|
793
|
+
runtimeVersion,
|
|
794
|
+
remote: sanitizedRemote,
|
|
795
|
+
shared: sanitizedShared,
|
|
796
|
+
expose: sanitizeText(event.expose, 240),
|
|
797
|
+
sanitizedUrl: clipText(event.url || event.remote?.entry, 320),
|
|
798
|
+
message,
|
|
799
|
+
errorCode: errorInfo.errorCode,
|
|
800
|
+
errorName: errorInfo.errorName,
|
|
801
|
+
errorMessage: errorInfo.errorMessage,
|
|
802
|
+
errorStack: errorInfo.errorStack,
|
|
803
|
+
duration: typeof event.duration === "number" && Number.isFinite(event.duration) ? Math.max(0, event.duration) : void 0,
|
|
804
|
+
lifecycle: sanitizeText(event.lifecycle, 120),
|
|
805
|
+
eventName: sanitizeText(event.eventName, 160),
|
|
806
|
+
source: normalizeEventSource(event.source),
|
|
807
|
+
recovered: event.recovered === true || void 0,
|
|
808
|
+
cached: event.cached === true || void 0,
|
|
809
|
+
componentName: sanitizeText(event.componentName, 160),
|
|
810
|
+
metadata: clipObservabilityMetadata(event.metadata),
|
|
811
|
+
loadedBefore: copyLoadedBeforeInfo(event.loadedBefore)
|
|
812
|
+
};
|
|
813
|
+
if (normalizedEvent.status === "error" || event.error) {
|
|
814
|
+
normalizedEvent.ownerHint = getOwnerHint(normalizedEvent);
|
|
815
|
+
normalizedEvent.retryable = getRetryable(normalizedEvent);
|
|
816
|
+
normalizedEvent.errorContext = createErrorContext(normalizedEvent, event.errorContext);
|
|
817
|
+
}
|
|
818
|
+
return normalizedEvent;
|
|
819
|
+
};
|
|
820
|
+
const supportsRuntimeHookObservability = (origin) => supportsRuntimeObservability({
|
|
821
|
+
...origin,
|
|
822
|
+
version: sanitizeText(origin?.version, 80) || appliedRuntimeVersion || origin?.version
|
|
823
|
+
});
|
|
824
|
+
const shouldSkipRuntimeHook = (origin) => shouldGuardRuntimeHooksByRuntimeVersion && !supportsRuntimeHookObservability(origin);
|
|
825
|
+
const applyPhaseDuration = (event) => {
|
|
826
|
+
const key = getPhaseDurationKey(event);
|
|
827
|
+
if (event.status === "start") {
|
|
828
|
+
phaseStartTimes.set(key, event.timestamp);
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
if (event.duration !== void 0) return;
|
|
832
|
+
const startedAt = phaseStartTimes.get(key);
|
|
833
|
+
if (startedAt === void 0) return;
|
|
834
|
+
event.duration = Math.max(0, event.timestamp - startedAt);
|
|
835
|
+
phaseStartTimes.delete(key);
|
|
836
|
+
};
|
|
837
|
+
const updateTraceMaps = (event) => {
|
|
838
|
+
if (event.requestId) traceByRequest.set(event.requestId, event.traceId);
|
|
839
|
+
if (event.remote?.name) traceByRemote.set(event.remote.name, event.traceId);
|
|
840
|
+
};
|
|
841
|
+
const trimEvents = (report) => {
|
|
842
|
+
while (events.length > effectiveMaxEvents) events.shift();
|
|
843
|
+
while (report.events.length > effectiveMaxEvents) report.events.shift();
|
|
844
|
+
};
|
|
845
|
+
const getEventOutcome = (event) => {
|
|
846
|
+
if (event.status === "success") return "success";
|
|
847
|
+
if (event.status === "error") return "error";
|
|
848
|
+
if (event.status === "complete") {
|
|
849
|
+
if (event.recovered) return "recovered";
|
|
850
|
+
if (event.errorName || event.errorMessage) return "error";
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
const isLoadRemoteCompleteEvent = (event) => event.phase === "loadRemote" && event.status === "complete";
|
|
854
|
+
const isRuntimeLoadedEvent = (event) => event.phase === "loadRemote" && (event.status === "success" || event.status === "complete" && event.recovered);
|
|
855
|
+
const isSharedResolvedEvent = (event) => event.phase === "shared" && (event.status === "success" || event.status === "complete" && event.recovered);
|
|
856
|
+
const isPreloadedEvent = (event) => event.phase === "preload" && event.status === "success";
|
|
857
|
+
const isComponentLoadedEvent = (event) => event.status === "success" && (event.eventName === COMPONENT_BUSINESS_LOADED_EVENT || event.phase === "component" && event.message === COMPONENT_BUSINESS_LOADED_EVENT);
|
|
858
|
+
const shouldReplaceFailedPhase = (report, event) => {
|
|
859
|
+
if (isLoadRemoteCompleteEvent(event) && report.failedPhase) return false;
|
|
860
|
+
if (!report.failedPhase) return true;
|
|
861
|
+
return report.failedPhase === "loadRemote" && event.phase !== "loadRemote";
|
|
862
|
+
};
|
|
863
|
+
const createEmptyPhaseCollection = () => ({
|
|
864
|
+
phases: {},
|
|
865
|
+
flags: {
|
|
866
|
+
cached: false,
|
|
867
|
+
fallback: false,
|
|
868
|
+
recovered: false
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
const createPhaseCollection = (eventsForReport) => {
|
|
872
|
+
const collection = createEmptyPhaseCollection();
|
|
873
|
+
eventsForReport.forEach((event) => {
|
|
874
|
+
const phase = event.phase;
|
|
875
|
+
const phaseSummary = collection.phases[phase] || { status: event.status };
|
|
876
|
+
if (event.status !== "start") phaseSummary.status = event.status;
|
|
877
|
+
if (event.duration !== void 0) phaseSummary.duration = event.duration;
|
|
878
|
+
if (event.cached) {
|
|
879
|
+
phaseSummary.cached = true;
|
|
880
|
+
collection.flags.cached = true;
|
|
881
|
+
}
|
|
882
|
+
if (event.recovered) {
|
|
883
|
+
phaseSummary.recovered = true;
|
|
884
|
+
collection.flags.recovered = true;
|
|
885
|
+
}
|
|
886
|
+
if (event.lifecycle) phaseSummary.lifecycle = event.lifecycle;
|
|
887
|
+
collection.phases[phase] = phaseSummary;
|
|
888
|
+
if (event.phase === "loadRemote" && event.status === "complete" && event.recovered) collection.flags.fallback = true;
|
|
889
|
+
if (event.shared?.selectedVersion || event.shared?.provider) collection.shared = {
|
|
890
|
+
name: event.shared.name,
|
|
891
|
+
provider: event.shared.provider,
|
|
892
|
+
selectedVersion: event.shared.selectedVersion,
|
|
893
|
+
shareScope: event.shared.shareScope ? [...event.shared.shareScope] : void 0
|
|
894
|
+
};
|
|
895
|
+
});
|
|
896
|
+
return collection;
|
|
897
|
+
};
|
|
898
|
+
const createErrorSummary = (eventsForReport, failedPhase) => {
|
|
899
|
+
const errorEvent = eventsForReport.find((event) => event.status === "error" && event.phase === failedPhase) || eventsForReport.find((event) => event.status === "error") || eventsForReport.find((event) => event.status === "complete" && event.errorMessage);
|
|
900
|
+
if (!errorEvent) return;
|
|
901
|
+
return {
|
|
902
|
+
errorCode: errorEvent.errorCode,
|
|
903
|
+
errorName: errorEvent.errorName,
|
|
904
|
+
errorMessage: errorEvent.errorMessage,
|
|
905
|
+
failedPhase: failedPhase || errorEvent.phase,
|
|
906
|
+
lifecycle: errorEvent.lifecycle,
|
|
907
|
+
ownerHint: errorEvent.ownerHint,
|
|
908
|
+
retryable: errorEvent.retryable,
|
|
909
|
+
context: errorEvent.errorContext ? { ...errorEvent.errorContext } : void 0
|
|
910
|
+
};
|
|
911
|
+
};
|
|
912
|
+
const createReportSummary = (report) => {
|
|
913
|
+
const loadCompleted = report.events.some(isLoadRemoteCompleteEvent);
|
|
914
|
+
const runtimeLoaded = report.events.some(isRuntimeLoadedEvent);
|
|
915
|
+
const sharedResolved = report.events.some(isSharedResolvedEvent);
|
|
916
|
+
const preloaded = report.events.some(isPreloadedEvent);
|
|
917
|
+
const recovered = report.events.some((item) => item.recovered);
|
|
918
|
+
const componentLoaded = report.events.some(isComponentLoadedEvent);
|
|
919
|
+
const lastEvent = report.events[report.events.length - 1];
|
|
920
|
+
let outcome = "pending";
|
|
921
|
+
if (recovered) outcome = "recovered";
|
|
922
|
+
else if (componentLoaded) outcome = "component-loaded";
|
|
923
|
+
else if (report.status === "error") outcome = "failed";
|
|
924
|
+
else if (runtimeLoaded) outcome = "runtime-loaded";
|
|
925
|
+
else if (sharedResolved) outcome = "shared-resolved";
|
|
926
|
+
else if (preloaded) outcome = "preloaded";
|
|
927
|
+
const phaseCollection = createPhaseCollection(report.events);
|
|
928
|
+
return {
|
|
929
|
+
eventCount: report.events.length,
|
|
930
|
+
recovered,
|
|
931
|
+
loadCompleted,
|
|
932
|
+
runtimeLoaded,
|
|
933
|
+
sharedResolved,
|
|
934
|
+
preloaded,
|
|
935
|
+
componentLoaded,
|
|
936
|
+
outcome,
|
|
937
|
+
lastPhase: lastEvent?.phase,
|
|
938
|
+
phases: phaseCollection.phases,
|
|
939
|
+
shared: phaseCollection.shared,
|
|
940
|
+
flags: phaseCollection.flags,
|
|
941
|
+
error: createErrorSummary(report.events, report.failedPhase)
|
|
942
|
+
};
|
|
943
|
+
};
|
|
944
|
+
const refreshModuleInfoSummary = (report) => {
|
|
945
|
+
const moduleInfo = createModuleInfoSummary(report);
|
|
946
|
+
if (moduleInfo) report.moduleInfo = moduleInfo;
|
|
947
|
+
};
|
|
948
|
+
const getReportContext = (report) => report.summary.error?.context || report.errorContext;
|
|
949
|
+
const getContextText = (context, key) => {
|
|
950
|
+
const value = context?.[key];
|
|
951
|
+
return typeof value === "string" && value ? value : void 0;
|
|
952
|
+
};
|
|
953
|
+
const getDiagnosisOwnerHint = (report) => report.summary.error?.ownerHint || report.ownerHint || (report.shared ? "shared" : report.remote ? "remote" : "unknown");
|
|
954
|
+
const getDiagnosisResourceErrorType = (report) => getContextText(getReportContext(report), "resourceErrorType") || getResourceErrorType({
|
|
955
|
+
errorCode: report.errorCode,
|
|
956
|
+
errorMessage: report.errorMessage,
|
|
957
|
+
message: report.events.at(-1)?.message,
|
|
958
|
+
lifecycle: report.summary.error?.lifecycle
|
|
959
|
+
});
|
|
960
|
+
const getDiagnosisDocLink = (report) => {
|
|
961
|
+
const matched = [
|
|
962
|
+
report.errorMessage,
|
|
963
|
+
report.errorStack,
|
|
964
|
+
...report.events.flatMap((event) => [
|
|
965
|
+
event.errorMessage,
|
|
966
|
+
event.errorStack,
|
|
967
|
+
event.message
|
|
968
|
+
])
|
|
969
|
+
].filter((item) => Boolean(item)).join("\n").match(DIAGNOSTIC_DOC_LINK_PATTERN)?.[0];
|
|
970
|
+
const docLink = sanitizeText(matched, 240);
|
|
971
|
+
if (docLink) return docLink;
|
|
972
|
+
return report.errorCode?.startsWith("RUNTIME-") ? RUNTIME_DOC_LINK : void 0;
|
|
973
|
+
};
|
|
974
|
+
const getDiagnosisTitle = (report) => {
|
|
975
|
+
if (report.status !== "error") {
|
|
976
|
+
if (report.shared) {
|
|
977
|
+
if (report.summary.sharedResolved) return "Shared dependency resolved successfully";
|
|
978
|
+
return "Shared dependency loading is pending";
|
|
979
|
+
}
|
|
980
|
+
if (report.summary.componentLoaded) return "Business component loaded";
|
|
981
|
+
if (report.summary.runtimeLoaded) return "Remote loaded successfully";
|
|
982
|
+
if (report.summary.preloaded) return "Remote preloaded successfully";
|
|
983
|
+
return "Remote loading is pending";
|
|
984
|
+
}
|
|
985
|
+
switch (report.errorCode) {
|
|
986
|
+
case "RUNTIME-001": return "Remote entry global was not registered";
|
|
987
|
+
case "RUNTIME-003": return "Manifest could not be loaded";
|
|
988
|
+
case "RUNTIME-004": return "Remote was not found in host remotes";
|
|
989
|
+
case "RUNTIME-007": return "Deployment moduleInfo did not match the requested remote";
|
|
990
|
+
case "RUNTIME-013": return "Manifest is not a valid Module Federation manifest";
|
|
991
|
+
case "RUNTIME-014": return "Requested expose was not found in the remote";
|
|
992
|
+
case "RUNTIME-015": return "Remote container initialization failed";
|
|
993
|
+
case "RUNTIME-005":
|
|
994
|
+
case "RUNTIME-006": return "Shared dependency could not be resolved";
|
|
995
|
+
case "RUNTIME-008": {
|
|
996
|
+
const resourceErrorType = getDiagnosisResourceErrorType(report);
|
|
997
|
+
if (resourceErrorType === "network") return "Remote entry failed because of a network error";
|
|
998
|
+
if (resourceErrorType === "timeout") return "Remote entry request timed out";
|
|
999
|
+
if (resourceErrorType === "script-execution") return "Remote entry loaded but failed during execution";
|
|
1000
|
+
return "Remote entry resource could not be loaded";
|
|
1001
|
+
}
|
|
1002
|
+
default:
|
|
1003
|
+
if (report.failedPhase === "shared" || report.shared) return "Shared dependency could not be resolved";
|
|
1004
|
+
return report.failedPhase ? `Module Federation failed at ${report.failedPhase}` : "Module Federation loading failed";
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
const getCompletedPhases = (report) => Array.from(new Set(report.events.filter((event) => event.status === "success" || event.status === "complete").map((event) => event.phase)));
|
|
1008
|
+
const getPendingPhases = (report) => {
|
|
1009
|
+
const started = /* @__PURE__ */ new Set();
|
|
1010
|
+
const ended = /* @__PURE__ */ new Set();
|
|
1011
|
+
report.events.forEach((event) => {
|
|
1012
|
+
if (event.status === "start") {
|
|
1013
|
+
started.add(event.phase);
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
ended.add(event.phase);
|
|
1017
|
+
});
|
|
1018
|
+
return Array.from(started).filter((phase) => !ended.has(phase));
|
|
1019
|
+
};
|
|
1020
|
+
const createDiagnosisFacts = (report, ownerHint) => {
|
|
1021
|
+
const context = getReportContext(report);
|
|
1022
|
+
const facts = {};
|
|
1023
|
+
const addFact = (key, value) => {
|
|
1024
|
+
if (value === void 0 || value === null || value === "") return;
|
|
1025
|
+
facts[key] = Array.isArray(value) ? value.join(",") : value;
|
|
1026
|
+
};
|
|
1027
|
+
addFact("traceId", report.traceId);
|
|
1028
|
+
addFact("status", report.status);
|
|
1029
|
+
addFact("outcome", report.summary.outcome);
|
|
1030
|
+
addFact("errorCode", report.errorCode || report.summary.error?.errorCode);
|
|
1031
|
+
addFact("failedPhase", report.failedPhase || report.summary.error?.failedPhase);
|
|
1032
|
+
addFact("lifecycle", report.summary.error?.lifecycle);
|
|
1033
|
+
addFact("ownerHint", ownerHint);
|
|
1034
|
+
addFact("retryable", report.retryable ?? report.summary.error?.retryable);
|
|
1035
|
+
addFact("requestId", report.requestId);
|
|
1036
|
+
addFact("requestAlias", report.requestAlias || report.summary.error?.context?.["requestAlias"]);
|
|
1037
|
+
addFact("hostName", report.hostName);
|
|
1038
|
+
addFact("remoteName", report.remote?.name);
|
|
1039
|
+
addFact("remoteAlias", report.remote?.alias);
|
|
1040
|
+
addFact("remoteEntry", report.remote?.entry);
|
|
1041
|
+
addFact("entryGlobalName", report.remote?.entryGlobalName);
|
|
1042
|
+
addFact("remoteType", report.remote?.type);
|
|
1043
|
+
addFact("url", report.sanitizedUrl || getContextText(context, "url"));
|
|
1044
|
+
addFact("expose", report.expose);
|
|
1045
|
+
addFact("hostRemotes", getContextText(context, "hostRemotes"));
|
|
1046
|
+
addFact("resourceErrorType", getDiagnosisResourceErrorType(report));
|
|
1047
|
+
addFact("shareName", report.shared?.name);
|
|
1048
|
+
addFact("shareScope", report.shared?.shareScope);
|
|
1049
|
+
addFact("requiredVersion", report.shared?.requiredVersion);
|
|
1050
|
+
addFact("selectedVersion", report.shared?.selectedVersion);
|
|
1051
|
+
addFact("availableVersions", report.shared?.availableVersions);
|
|
1052
|
+
addFact("provider", report.shared?.provider);
|
|
1053
|
+
addFact("sharedFrom", report.shared?.from);
|
|
1054
|
+
addFact("singleton", report.shared?.singleton);
|
|
1055
|
+
addFact("strictVersion", report.shared?.strictVersion);
|
|
1056
|
+
addFact("eager", report.shared?.eager);
|
|
1057
|
+
addFact("sharedReason", report.shared?.reason);
|
|
1058
|
+
addFact("componentName", report.events.find(isComponentLoadedEvent)?.componentName);
|
|
1059
|
+
addFact("moduleInfoReason", report.moduleInfo?.reason);
|
|
1060
|
+
addFact("moduleInfoTotalCount", report.moduleInfo?.totalCount);
|
|
1061
|
+
addFact("moduleInfoMatchedCount", report.moduleInfo?.matchedCount);
|
|
1062
|
+
addFact("moduleInfoNames", report.moduleInfo?.entries.length ? report.moduleInfo.entries.map((entry) => entry.name) : report.moduleInfo?.availableNames);
|
|
1063
|
+
addFact("cached", report.summary.flags.cached);
|
|
1064
|
+
addFact("fallback", report.summary.flags.fallback);
|
|
1065
|
+
addFact("recovered", report.summary.recovered);
|
|
1066
|
+
addFact("loadCompleted", report.summary.loadCompleted);
|
|
1067
|
+
addFact("runtimeLoaded", report.summary.runtimeLoaded);
|
|
1068
|
+
addFact("componentLoaded", report.summary.componentLoaded);
|
|
1069
|
+
return clipMetadata(facts, MAX_FACT_KEYS) || {};
|
|
1070
|
+
};
|
|
1071
|
+
const createDiagnosisWarnings = (report) => {
|
|
1072
|
+
const warnings = [];
|
|
1073
|
+
if (report.status === "error" && !report.errorCode) warnings.push("No known Module Federation error code was captured");
|
|
1074
|
+
if (report.summary.flags.fallback) warnings.push("Remote loading completed through fallback recovery");
|
|
1075
|
+
if (report.summary.runtimeLoaded && !report.summary.componentLoaded) warnings.push("Business component readiness signal was not recorded");
|
|
1076
|
+
if (report.moduleInfo && report.moduleInfo.matchedCount === 0) warnings.push("No matching clipped moduleInfo entry was found for the failed remote");
|
|
1077
|
+
return warnings;
|
|
1078
|
+
};
|
|
1079
|
+
const createDiagnosisActions = (report, ownerHint) => {
|
|
1080
|
+
const actions = [];
|
|
1081
|
+
const pushAction = (id, title, hint = ownerHint, detail) => {
|
|
1082
|
+
actions.push({
|
|
1083
|
+
id,
|
|
1084
|
+
ownerHint: hint,
|
|
1085
|
+
title,
|
|
1086
|
+
detail
|
|
1087
|
+
});
|
|
1088
|
+
};
|
|
1089
|
+
if (report.status !== "error" && !report.summary.error) return actions;
|
|
1090
|
+
switch (report.errorCode) {
|
|
1091
|
+
case "RUNTIME-001":
|
|
1092
|
+
pushAction("check-remote-global", "Check the remote global name against the remoteEntry build output", "remote");
|
|
1093
|
+
pushAction("check-remote-entry", "Check that remoteEntry registers the expected container", "remote");
|
|
1094
|
+
break;
|
|
1095
|
+
case "RUNTIME-003":
|
|
1096
|
+
pushAction("check-manifest-url", "Check the manifest URL and manifest JSON response", "host");
|
|
1097
|
+
pushAction("check-network", "Check network availability, CORS, and timeout for the manifest", "network");
|
|
1098
|
+
break;
|
|
1099
|
+
case "RUNTIME-013":
|
|
1100
|
+
pushAction("check-manifest-url", "Check that the manifest response is valid Module Federation JSON", "remote");
|
|
1101
|
+
break;
|
|
1102
|
+
case "RUNTIME-004":
|
|
1103
|
+
pushAction("check-host-remotes", "Check that the requested remote exists in host remotes", "host");
|
|
1104
|
+
break;
|
|
1105
|
+
case "RUNTIME-007":
|
|
1106
|
+
pushAction("check-module-info", "Check deployment-provided __FEDERATION__.moduleInfo for the requested remote", "host");
|
|
1107
|
+
pushAction("check-host-remotes", "Check that the runtime remote name or alias matches moduleInfo", "host");
|
|
1108
|
+
break;
|
|
1109
|
+
case "RUNTIME-014":
|
|
1110
|
+
pushAction("check-expose", "Check that the requested expose exists in the remote build output", "remote");
|
|
1111
|
+
break;
|
|
1112
|
+
case "RUNTIME-015":
|
|
1113
|
+
pushAction("check-remote-entry", "Check the error thrown during remoteEntry init", "remote");
|
|
1114
|
+
pushAction("check-shared-provider", "Check share scope initialization data passed to the remote", "shared");
|
|
1115
|
+
break;
|
|
1116
|
+
case "RUNTIME-005":
|
|
1117
|
+
case "RUNTIME-006":
|
|
1118
|
+
pushAction("check-shared-provider", "Check that a compatible shared provider is available", "shared");
|
|
1119
|
+
pushAction("check-shared-version", "Compare requested shared version with available versions", "shared");
|
|
1120
|
+
if (report.summary.error?.lifecycle === "loadShareSync" || report.shared?.reason === "sync-async-boundary" || report.shared?.eager === false) pushAction("check-eager-config", "Check eager configuration or add an async boundary before sync shared consumption", "shared");
|
|
1121
|
+
break;
|
|
1122
|
+
case "RUNTIME-008": {
|
|
1123
|
+
const resourceErrorType = getDiagnosisResourceErrorType(report);
|
|
1124
|
+
if (resourceErrorType === "network" || resourceErrorType === "timeout") pushAction("check-network", "Check remoteEntry URL, CORS, status code, and timeout", "network");
|
|
1125
|
+
pushAction("check-remote-entry", resourceErrorType === "script-execution" ? "Check remoteEntry execution errors in the remote build output" : "Check that remoteEntry is reachable and serves JavaScript", resourceErrorType === "network" || resourceErrorType === "timeout" ? "network" : "remote");
|
|
1126
|
+
break;
|
|
1127
|
+
}
|
|
1128
|
+
default:
|
|
1129
|
+
if (report.failedPhase === "manifest") pushAction("check-manifest-url", "Check manifest loading and parsing", "host");
|
|
1130
|
+
if (report.failedPhase === "remoteEntry") pushAction("check-remote-entry", "Check remoteEntry loading and initialization", "remote");
|
|
1131
|
+
if (report.failedPhase === "expose") pushAction("check-expose", "Check that the requested expose exists in the remote", "remote");
|
|
1132
|
+
if (report.failedPhase === "shared") {
|
|
1133
|
+
pushAction("check-shared-provider", "Check shared dependency resolution", "shared");
|
|
1134
|
+
if (report.shared?.requiredVersion !== void 0 || report.shared?.availableVersions?.length || report.shared?.reason === "version-mismatch") pushAction("check-shared-version", "Compare requested shared version with available versions", "shared");
|
|
1135
|
+
if (report.summary.error?.lifecycle === "loadShareSync" || report.shared?.reason === "sync-async-boundary" || report.shared?.eager === false) pushAction("check-eager-config", "Check eager configuration or add an async boundary before sync shared consumption", "shared");
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
if (report.moduleInfo && !actions.some((action) => action.id === "check-module-info")) pushAction("check-module-info", "Check deployment-provided __FEDERATION__.moduleInfo for the requested remote", "host");
|
|
1139
|
+
if (!actions.length) pushAction("inspect-runtime-events", "Inspect the ordered observability events for the failed phase", ownerHint);
|
|
1140
|
+
return actions;
|
|
1141
|
+
};
|
|
1142
|
+
const createFactReport = (report) => {
|
|
1143
|
+
const ownerHint = getDiagnosisOwnerHint(report);
|
|
1144
|
+
const warnings = createDiagnosisWarnings(report);
|
|
1145
|
+
return {
|
|
1146
|
+
title: getDiagnosisTitle(report),
|
|
1147
|
+
outcome: report.summary.outcome,
|
|
1148
|
+
status: report.status,
|
|
1149
|
+
ownerHint,
|
|
1150
|
+
failedPhase: report.failedPhase || report.summary.error?.failedPhase,
|
|
1151
|
+
errorCode: report.errorCode || report.summary.error?.errorCode,
|
|
1152
|
+
errorName: report.errorName || report.summary.error?.errorName,
|
|
1153
|
+
errorMessage: report.errorMessage || report.summary.error?.errorMessage,
|
|
1154
|
+
docLink: getDiagnosisDocLink(report),
|
|
1155
|
+
facts: createDiagnosisFacts(report, ownerHint),
|
|
1156
|
+
completedPhases: getCompletedPhases(report),
|
|
1157
|
+
pendingPhases: getPendingPhases(report),
|
|
1158
|
+
warnings: warnings.length ? warnings : void 0,
|
|
1159
|
+
actions: createDiagnosisActions(report, ownerHint)
|
|
1160
|
+
};
|
|
1161
|
+
};
|
|
1162
|
+
const refreshReportDerivedFields = (report) => {
|
|
1163
|
+
report.summary = createReportSummary(report);
|
|
1164
|
+
refreshModuleInfoSummary(report);
|
|
1165
|
+
report.diagnosis = createFactReport(report);
|
|
1166
|
+
};
|
|
1167
|
+
const updateReport = (event) => {
|
|
1168
|
+
let report = reports.get(event.traceId);
|
|
1169
|
+
if (!report) {
|
|
1170
|
+
report = {
|
|
1171
|
+
traceId: event.traceId,
|
|
1172
|
+
status: event.status === "error" ? "error" : "pending",
|
|
1173
|
+
requestId: event.requestId,
|
|
1174
|
+
requestAlias: event.requestAlias,
|
|
1175
|
+
hostName: event.hostName,
|
|
1176
|
+
runtimeVersion: event.runtimeVersion,
|
|
1177
|
+
remote: event.remote ? { ...event.remote } : void 0,
|
|
1178
|
+
shared: event.shared ? copyEvent(event).shared : void 0,
|
|
1179
|
+
expose: event.expose,
|
|
1180
|
+
sanitizedUrl: event.sanitizedUrl,
|
|
1181
|
+
startedAt: event.timestamp,
|
|
1182
|
+
updatedAt: event.timestamp,
|
|
1183
|
+
duration: 0,
|
|
1184
|
+
failedPhase: event.status === "error" ? event.phase : void 0,
|
|
1185
|
+
errorCode: event.errorCode,
|
|
1186
|
+
errorName: event.errorName,
|
|
1187
|
+
errorMessage: event.errorMessage,
|
|
1188
|
+
errorStack: event.errorStack,
|
|
1189
|
+
ownerHint: event.ownerHint,
|
|
1190
|
+
retryable: event.retryable,
|
|
1191
|
+
errorContext: event.errorContext ? { ...event.errorContext } : void 0,
|
|
1192
|
+
loadedBefore: copyLoadedBeforeInfo(event.loadedBefore),
|
|
1193
|
+
events: [],
|
|
1194
|
+
summary: {
|
|
1195
|
+
eventCount: 0,
|
|
1196
|
+
recovered: false,
|
|
1197
|
+
loadCompleted: false,
|
|
1198
|
+
runtimeLoaded: false,
|
|
1199
|
+
sharedResolved: false,
|
|
1200
|
+
preloaded: false,
|
|
1201
|
+
componentLoaded: false,
|
|
1202
|
+
outcome: "pending",
|
|
1203
|
+
lastPhase: void 0,
|
|
1204
|
+
phases: {},
|
|
1205
|
+
shared: void 0,
|
|
1206
|
+
flags: createEmptyPhaseCollection().flags,
|
|
1207
|
+
error: void 0
|
|
1208
|
+
}
|
|
1209
|
+
};
|
|
1210
|
+
reports.set(event.traceId, report);
|
|
1211
|
+
}
|
|
1212
|
+
if (event.requestId) report.requestId = event.requestId;
|
|
1213
|
+
if (event.requestAlias) report.requestAlias = event.requestAlias;
|
|
1214
|
+
if (event.hostName) report.hostName = event.hostName;
|
|
1215
|
+
if (event.runtimeVersion) report.runtimeVersion = event.runtimeVersion;
|
|
1216
|
+
if (event.remote) report.remote = { ...event.remote };
|
|
1217
|
+
if (event.shared) report.shared = copyEvent(event).shared;
|
|
1218
|
+
if (event.expose) report.expose = event.expose;
|
|
1219
|
+
if (event.sanitizedUrl) report.sanitizedUrl = event.sanitizedUrl;
|
|
1220
|
+
if (event.errorStack) report.errorStack = event.errorStack;
|
|
1221
|
+
if (event.errorCode) report.errorCode = event.errorCode;
|
|
1222
|
+
if (event.errorName) report.errorName = event.errorName;
|
|
1223
|
+
if (event.errorMessage) report.errorMessage = event.errorMessage;
|
|
1224
|
+
if (event.ownerHint) report.ownerHint = event.ownerHint;
|
|
1225
|
+
if (event.retryable !== void 0) report.retryable = event.retryable;
|
|
1226
|
+
if (event.errorContext) report.errorContext = { ...event.errorContext };
|
|
1227
|
+
if (event.loadedBefore) report.loadedBefore = copyLoadedBeforeInfo(event.loadedBefore);
|
|
1228
|
+
report.events.push(event);
|
|
1229
|
+
report.updatedAt = event.timestamp;
|
|
1230
|
+
report.duration = Math.max(0, report.updatedAt - report.startedAt);
|
|
1231
|
+
const eventOutcome = getEventOutcome(event);
|
|
1232
|
+
if (eventOutcome === "error") {
|
|
1233
|
+
report.status = "error";
|
|
1234
|
+
if (shouldReplaceFailedPhase(report, event)) report.failedPhase = event.phase;
|
|
1235
|
+
} else if (eventOutcome === "recovered") report.status = "success";
|
|
1236
|
+
else if (eventOutcome === "success" && report.status !== "error") report.status = "success";
|
|
1237
|
+
refreshReportDerivedFields(report);
|
|
1238
|
+
latestTraceId = event.traceId;
|
|
1239
|
+
trimEvents(report);
|
|
1240
|
+
return report;
|
|
1241
|
+
};
|
|
1242
|
+
const notifyEvent = (event, report, origin) => {
|
|
1243
|
+
try {
|
|
1244
|
+
options.onEvent?.(copyEvent(event), copyReport(report), { origin });
|
|
1245
|
+
} catch {}
|
|
1246
|
+
};
|
|
1247
|
+
const notifyReport = (report, origin) => {
|
|
1248
|
+
if (report.events[report.events.length - 1]?.status === "start") return;
|
|
1249
|
+
try {
|
|
1250
|
+
options.onReport?.(copyReport(report), { origin });
|
|
1251
|
+
} catch {}
|
|
1252
|
+
};
|
|
1253
|
+
const notifyRawError = (errorValue, event, report, origin) => {
|
|
1254
|
+
if (!errorValue || !options.onRawError) return;
|
|
1255
|
+
try {
|
|
1256
|
+
options.onRawError(errorValue, {
|
|
1257
|
+
origin,
|
|
1258
|
+
event: copyEvent(event),
|
|
1259
|
+
report: copyReport(report)
|
|
1260
|
+
});
|
|
1261
|
+
} catch {}
|
|
1262
|
+
};
|
|
1263
|
+
const notifyCollector = (event, report) => {
|
|
1264
|
+
if (!collectorOptions) return;
|
|
1265
|
+
const fetcher = globalThis.fetch;
|
|
1266
|
+
if (typeof fetcher !== "function") return;
|
|
1267
|
+
try {
|
|
1268
|
+
const body = JSON.stringify({
|
|
1269
|
+
schemaVersion: 1,
|
|
1270
|
+
source: "browser",
|
|
1271
|
+
kind: "event",
|
|
1272
|
+
createdAt: Date.now(),
|
|
1273
|
+
event: copyEvent(event),
|
|
1274
|
+
report: copyReport(report)
|
|
1275
|
+
});
|
|
1276
|
+
fetcher(getCollectorUrl(collectorOptions.port), {
|
|
1277
|
+
method: "POST",
|
|
1278
|
+
headers: { "content-type": "application/json" },
|
|
1279
|
+
body,
|
|
1280
|
+
keepalive: body.length <= 64 * 1024,
|
|
1281
|
+
credentials: "omit",
|
|
1282
|
+
mode: "cors"
|
|
1283
|
+
}).catch((error) => {
|
|
1284
|
+
logger.debug("Failed to notify local observability collector.", error);
|
|
1285
|
+
});
|
|
1286
|
+
} catch (error) {
|
|
1287
|
+
logger.debug("Failed to notify local observability collector.", error);
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
const notifyDevtools = (event, report) => {
|
|
1291
|
+
if (!devtoolsOptions) return;
|
|
1292
|
+
const poster = globalThis.postMessage;
|
|
1293
|
+
if (typeof poster !== "function") return;
|
|
1294
|
+
try {
|
|
1295
|
+
poster.call(globalThis, {
|
|
1296
|
+
schemaVersion: 1,
|
|
1297
|
+
source: devtoolsOptions.source,
|
|
1298
|
+
kind: "event",
|
|
1299
|
+
createdAt: Date.now(),
|
|
1300
|
+
scope: browserGlobalScope || report.hostName,
|
|
1301
|
+
event: copyEvent(event),
|
|
1302
|
+
report: copyReport(report)
|
|
1303
|
+
}, "*");
|
|
1304
|
+
} catch {}
|
|
1305
|
+
};
|
|
1306
|
+
const getEventsSnapshot = () => events.map(copyEvent);
|
|
1307
|
+
const getTraceIdsSnapshot = () => Array.from(reports.keys());
|
|
1308
|
+
const getReportTimeline = () => Array.from(reports.values()).sort((left, right) => {
|
|
1309
|
+
if (right.updatedAt !== left.updatedAt) return right.updatedAt - left.updatedAt;
|
|
1310
|
+
return right.startedAt - left.startedAt;
|
|
1311
|
+
});
|
|
1312
|
+
const matchesReportValue = (value, expected) => {
|
|
1313
|
+
if (!value || !expected) return false;
|
|
1314
|
+
const normalizedValue = value.toLowerCase();
|
|
1315
|
+
const normalizedExpected = expected.toLowerCase();
|
|
1316
|
+
return normalizedValue === normalizedExpected || normalizedValue.includes(normalizedExpected);
|
|
1317
|
+
};
|
|
1318
|
+
const matchesReportQuery = (report, query) => {
|
|
1319
|
+
if (query.traceId && report.traceId !== query.traceId) return false;
|
|
1320
|
+
if (query.status && report.status !== query.status) return false;
|
|
1321
|
+
if (query.outcome && report.summary.outcome !== query.outcome) return false;
|
|
1322
|
+
if (query.remote && ![
|
|
1323
|
+
report.remote?.name,
|
|
1324
|
+
report.remote?.alias,
|
|
1325
|
+
report.remote?.entry,
|
|
1326
|
+
report.requestId,
|
|
1327
|
+
report.requestAlias,
|
|
1328
|
+
report.sanitizedUrl
|
|
1329
|
+
].some((value) => matchesReportValue(value, query.remote))) return false;
|
|
1330
|
+
if (query.expose && ![report.expose, report.requestId].some((value) => matchesReportValue(value, query.expose))) return false;
|
|
1331
|
+
if (query.shared && ![report.shared?.name].some((value) => matchesReportValue(value, query.shared))) return false;
|
|
1332
|
+
return true;
|
|
1333
|
+
};
|
|
1334
|
+
const getReportsSnapshot = (options = {}) => {
|
|
1335
|
+
const limit = normalizeQueryLimit(options.limit);
|
|
1336
|
+
const timeline = getReportTimeline();
|
|
1337
|
+
return (limit ? timeline.slice(0, limit) : timeline).map(copyReport);
|
|
1338
|
+
};
|
|
1339
|
+
const findReportsSnapshot = (query = {}) => {
|
|
1340
|
+
const limit = normalizeQueryLimit(query.limit);
|
|
1341
|
+
const matchedReports = getReportTimeline().filter((report) => matchesReportQuery(report, query));
|
|
1342
|
+
return (limit ? matchedReports.slice(0, limit) : matchedReports).map(copyReport);
|
|
1343
|
+
};
|
|
1344
|
+
const getLatestReportSnapshot = () => {
|
|
1345
|
+
if (!latestTraceId) return;
|
|
1346
|
+
const report = reports.get(latestTraceId);
|
|
1347
|
+
return report ? copyReport(report) : void 0;
|
|
1348
|
+
};
|
|
1349
|
+
const getReportSnapshot = (traceId) => {
|
|
1350
|
+
const report = reports.get(traceId);
|
|
1351
|
+
return report ? copyReport(report) : void 0;
|
|
1352
|
+
};
|
|
1353
|
+
const exportReportSnapshot = (traceId) => traceId ? getReportSnapshot(traceId) : getLatestReportSnapshot();
|
|
1354
|
+
const createBrowserReader = () => ({
|
|
1355
|
+
getEvents: getEventsSnapshot,
|
|
1356
|
+
getTraceIds: getTraceIdsSnapshot,
|
|
1357
|
+
getReports: getReportsSnapshot,
|
|
1358
|
+
findReports: findReportsSnapshot,
|
|
1359
|
+
getLatestReport: getLatestReportSnapshot,
|
|
1360
|
+
getReport: getReportSnapshot,
|
|
1361
|
+
exportReport: exportReportSnapshot
|
|
1362
|
+
});
|
|
1363
|
+
const shouldExposeBrowserGlobal = () => options.browser?.enabled === true;
|
|
1364
|
+
const ensureBrowserGlobal = (origin) => {
|
|
1365
|
+
if (!shouldExposeBrowserGlobal()) return;
|
|
1366
|
+
const federationGlobal = getFederationGlobal();
|
|
1367
|
+
if (!federationGlobal) return;
|
|
1368
|
+
const scope = normalizeScope(options.browser?.scope || origin?.options?.name || "default");
|
|
1369
|
+
const reader = createBrowserReader();
|
|
1370
|
+
const readers = federationGlobal.__OBSERVABILITY__ || {};
|
|
1371
|
+
federationGlobal.__OBSERVABILITY__ = readers;
|
|
1372
|
+
browserGlobalScope = scope;
|
|
1373
|
+
try {
|
|
1374
|
+
Object.defineProperty(readers, scope, {
|
|
1375
|
+
value: reader,
|
|
1376
|
+
configurable: true,
|
|
1377
|
+
enumerable: true
|
|
1378
|
+
});
|
|
1379
|
+
} catch {
|
|
1380
|
+
readers[scope] = reader;
|
|
1381
|
+
}
|
|
1382
|
+
};
|
|
1383
|
+
const shouldUseConsole = () => options.console !== false;
|
|
1384
|
+
const shouldUseDevelopmentChannels = () => {
|
|
1385
|
+
if (shouldUseMinimalBrowserConsole()) return false;
|
|
1386
|
+
if (shouldForceDevelopmentChannels) return true;
|
|
1387
|
+
if (typeof process === "undefined" || !process.env) return true;
|
|
1388
|
+
return process.env.NODE_ENV !== "production";
|
|
1389
|
+
};
|
|
1390
|
+
const shouldNotifyCollector = () => Boolean(collectorOptions);
|
|
1391
|
+
const shouldNotifyDevtools = () => shouldUseDevelopmentChannels();
|
|
1392
|
+
const shouldUseMinimalBrowserConsole = () => options.browser?.mode === "production";
|
|
1393
|
+
const shouldUseStartTrace = () => options.trace?.printStart ?? (options.browser?.enabled === true && !shouldUseMinimalBrowserConsole());
|
|
1394
|
+
const shouldPrintStartConsole = (event) => shouldUseStartTrace() && event.status === "start" && (event.phase === "loadRemote" || event.phase === "shared") && shouldUseConsole();
|
|
1395
|
+
const shouldRecordStartTrace = (input) => shouldUseStartTrace() && input.status === "start" && (input.phase === "loadRemote" || input.phase === "shared");
|
|
1396
|
+
const shouldCollectLoadedBefore = (error) => Boolean(error) || level === "verbose" && !shouldUseMinimalBrowserConsole();
|
|
1397
|
+
const getBrowserReadCommand = (traceId) => {
|
|
1398
|
+
if (!browserGlobalScope) return;
|
|
1399
|
+
return `window.__FEDERATION__.__OBSERVABILITY__[${JSON.stringify(browserGlobalScope)}].getReport(${JSON.stringify(traceId)})`;
|
|
1400
|
+
};
|
|
1401
|
+
const emitConsoleHint = (event, report, rawError) => {
|
|
1402
|
+
if (getEventOutcome(event) !== "error" || !shouldUseConsole() || consoleReportedTraceIds.has(report.traceId)) return;
|
|
1403
|
+
consoleReportedTraceIds.add(report.traceId);
|
|
1404
|
+
if (shouldUseMinimalBrowserConsole()) {
|
|
1405
|
+
const lines = ["[Module Federation] Observability report generated", `traceId: ${report.traceId}`];
|
|
1406
|
+
if (report.errorCode) lines.push(`errorCode: ${report.errorCode}`);
|
|
1407
|
+
try {
|
|
1408
|
+
console.error(lines.join("\n"));
|
|
1409
|
+
} catch {}
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
const lines = [
|
|
1413
|
+
"[Module Federation] Observability report generated",
|
|
1414
|
+
`traceId: ${report.traceId}`,
|
|
1415
|
+
`phase: ${report.failedPhase || event.phase}`
|
|
1416
|
+
];
|
|
1417
|
+
if (report.requestId) lines.push(`requestId: ${report.requestId}`);
|
|
1418
|
+
if (report.requestAlias) lines.push(`requestAlias: ${report.requestAlias}`);
|
|
1419
|
+
if (report.errorCode) lines.push(`errorCode: ${report.errorCode}`);
|
|
1420
|
+
if (report.shared?.name) lines.push(`shared: ${report.shared.name}`);
|
|
1421
|
+
const browserReadCommand = getBrowserReadCommand(report.traceId);
|
|
1422
|
+
if (browserReadCommand) lines.push(`read: ${browserReadCommand}`);
|
|
1423
|
+
else lines.push("read: enable browser output or use onReport(report)");
|
|
1424
|
+
const rawStack = getRawStack(rawError);
|
|
1425
|
+
if (options.printRawStack === true && rawStack) lines.push("rawStack:", rawStack);
|
|
1426
|
+
try {
|
|
1427
|
+
console.error(lines.join("\n"));
|
|
1428
|
+
} catch {}
|
|
1429
|
+
};
|
|
1430
|
+
const emitStartConsoleHint = (event, report) => {
|
|
1431
|
+
if (!shouldPrintStartConsole(event)) return;
|
|
1432
|
+
const startKey = [
|
|
1433
|
+
event.traceId,
|
|
1434
|
+
event.phase,
|
|
1435
|
+
event.requestId || event.shared?.name || event.remote?.name || "",
|
|
1436
|
+
event.lifecycle || ""
|
|
1437
|
+
].join("|");
|
|
1438
|
+
if (consoleReportedStartKeys.has(startKey)) return;
|
|
1439
|
+
consoleReportedStartKeys.add(startKey);
|
|
1440
|
+
const lines = [
|
|
1441
|
+
"[Module Federation] Observability trace started",
|
|
1442
|
+
`traceId: ${report.traceId}`,
|
|
1443
|
+
`phase: ${event.phase}`
|
|
1444
|
+
];
|
|
1445
|
+
if (event.requestId) lines.push(`requestId: ${event.requestId}`);
|
|
1446
|
+
if (event.requestAlias) lines.push(`requestAlias: ${event.requestAlias}`);
|
|
1447
|
+
if (event.remote?.name) lines.push(`remote: ${event.remote.name}`);
|
|
1448
|
+
if (event.shared?.name) lines.push(`shared: ${event.shared.name}`);
|
|
1449
|
+
if (event.lifecycle) lines.push(`lifecycle: ${event.lifecycle}`);
|
|
1450
|
+
const browserReadCommand = getBrowserReadCommand(report.traceId);
|
|
1451
|
+
if (browserReadCommand) lines.push(`read: ${browserReadCommand}`);
|
|
1452
|
+
else lines.push("read: enable browser output or use getReports({ limit: 10 })");
|
|
1453
|
+
try {
|
|
1454
|
+
console.info(lines.join("\n"));
|
|
1455
|
+
} catch {}
|
|
1456
|
+
};
|
|
1457
|
+
const prepareOutputChannels = (origin) => {
|
|
1458
|
+
browserGlobalScope = void 0;
|
|
1459
|
+
ensureBrowserGlobal(origin);
|
|
1460
|
+
};
|
|
1461
|
+
const prepareRuntimeOrigin = (origin) => {
|
|
1462
|
+
if (!isEnabled()) return false;
|
|
1463
|
+
lastRuntimeOrigin = origin;
|
|
1464
|
+
prepareOutputChannels(origin);
|
|
1465
|
+
return true;
|
|
1466
|
+
};
|
|
1467
|
+
const recordEvent = (input, origin) => {
|
|
1468
|
+
if (suppressRuntimeEvents) return;
|
|
1469
|
+
const event = normalizeEvent(input, resolveTraceId(input), origin);
|
|
1470
|
+
applyPhaseDuration(event);
|
|
1471
|
+
updateTraceMaps(event);
|
|
1472
|
+
if (!shouldRecordEvent(level, input) && !shouldRecordStartTrace(input)) return;
|
|
1473
|
+
events.push(event);
|
|
1474
|
+
const report = updateReport(event);
|
|
1475
|
+
emitStartConsoleHint(event, report);
|
|
1476
|
+
emitConsoleHint(event, report, input.error);
|
|
1477
|
+
if (shouldNotifyCollector()) notifyCollector(event, report);
|
|
1478
|
+
if (shouldNotifyDevtools()) notifyDevtools(event, report);
|
|
1479
|
+
notifyRawError(input.error, event, report, origin);
|
|
1480
|
+
notifyEvent(event, report, origin);
|
|
1481
|
+
notifyReport(report, origin);
|
|
1482
|
+
return event;
|
|
1483
|
+
};
|
|
1484
|
+
const markComponentLoaded = (markOptions = {}) => {
|
|
1485
|
+
if (options.enabled === false || !runtimeObservabilityEnabled) return;
|
|
1486
|
+
return recordEvent({
|
|
1487
|
+
traceId: markOptions.traceId || (markOptions.requestId ? traceByRequest.get(sanitizeRequestId(markOptions.requestId) || "") : void 0) || latestTraceId || createTraceId({
|
|
1488
|
+
phase: "component",
|
|
1489
|
+
status: "success",
|
|
1490
|
+
requestId: markOptions.requestId
|
|
1491
|
+
}),
|
|
1492
|
+
phase: "component",
|
|
1493
|
+
status: "success",
|
|
1494
|
+
requestId: markOptions.requestId,
|
|
1495
|
+
componentName: markOptions.componentName,
|
|
1496
|
+
metadata: markOptions.metadata,
|
|
1497
|
+
eventName: COMPONENT_BUSINESS_LOADED_EVENT,
|
|
1498
|
+
message: COMPONENT_BUSINESS_LOADED_EVENT,
|
|
1499
|
+
source: "business"
|
|
1500
|
+
}, lastRuntimeOrigin);
|
|
1501
|
+
};
|
|
1502
|
+
const getReactForOrigin = async (origin) => {
|
|
1503
|
+
const previousSuppressRuntimeEvents = suppressRuntimeEvents;
|
|
1504
|
+
suppressRuntimeEvents = true;
|
|
1505
|
+
try {
|
|
1506
|
+
let reactFactory;
|
|
1507
|
+
try {
|
|
1508
|
+
reactFactory = origin.loadShareSync?.("react");
|
|
1509
|
+
} catch {
|
|
1510
|
+
reactFactory = void 0;
|
|
1511
|
+
}
|
|
1512
|
+
if (typeof reactFactory !== "function") reactFactory = await origin.loadShare?.("react");
|
|
1513
|
+
if (typeof reactFactory !== "function") return;
|
|
1514
|
+
return resolveReactLike(reactFactory());
|
|
1515
|
+
} catch {
|
|
1516
|
+
return;
|
|
1517
|
+
} finally {
|
|
1518
|
+
suppressRuntimeEvents = previousSuppressRuntimeEvents;
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
const getReactWrapPolicy = (loadArgs) => {
|
|
1522
|
+
if (options.react?.enabled === false || options.react?.injectLoadedCallback !== true) return;
|
|
1523
|
+
const remoteIds = options.react.remoteIds || [];
|
|
1524
|
+
if (!remoteIds.length) return { allowAnonymousComponent: false };
|
|
1525
|
+
const normalizeRemoteId = (value) => value.replace(/\/\.\//g, "/").replace(/^\.\//, "");
|
|
1526
|
+
const expectedRemoteIds = new Set(remoteIds.map(normalizeRemoteId));
|
|
1527
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
1528
|
+
const addCandidate = (value) => {
|
|
1529
|
+
if (!value) return;
|
|
1530
|
+
candidates.add(value);
|
|
1531
|
+
candidates.add(normalizeRemoteId(value));
|
|
1532
|
+
};
|
|
1533
|
+
const exposeValues = [loadArgs.expose];
|
|
1534
|
+
if (loadArgs.expose?.startsWith("./")) exposeValues.push(loadArgs.expose.slice(2));
|
|
1535
|
+
const remoteNames = [
|
|
1536
|
+
loadArgs.pkgNameOrAlias,
|
|
1537
|
+
loadArgs.remote?.alias,
|
|
1538
|
+
loadArgs.remote?.name
|
|
1539
|
+
];
|
|
1540
|
+
addCandidate(loadArgs.id);
|
|
1541
|
+
addCandidate(loadArgs.expose);
|
|
1542
|
+
remoteNames.forEach((remoteName) => {
|
|
1543
|
+
exposeValues.forEach((expose) => {
|
|
1544
|
+
addCandidate(remoteName && expose ? `${remoteName}/${expose}` : "");
|
|
1545
|
+
});
|
|
1546
|
+
});
|
|
1547
|
+
return Array.from(candidates).some((candidate) => expectedRemoteIds.has(candidate)) ? { allowAnonymousComponent: true } : void 0;
|
|
1548
|
+
};
|
|
1549
|
+
const createReactComponentWrapper = (component, loadArgs, wrapPolicy, react) => {
|
|
1550
|
+
const target = resolveReactComponentTarget(component, options.react?.defaultExportMode || (wrapPolicy.allowAnonymousComponent ? "component" : "preserve"), wrapPolicy.allowAnonymousComponent);
|
|
1551
|
+
if (!target) return;
|
|
1552
|
+
const componentName = getReactComponentName(target.component, loadArgs.expose || loadArgs.id);
|
|
1553
|
+
const originalComponent = target.component;
|
|
1554
|
+
const ObservedRemoteComponent = (props) => {
|
|
1555
|
+
const incomingProps = isRecord(props) ? props : {};
|
|
1556
|
+
const originalLoadedCallback = getObjectValue(incomingProps, ON_MF_REMOTE_LOADED_PROP);
|
|
1557
|
+
const onMFRemoteLoaded = (loadedOptions = {}) => {
|
|
1558
|
+
markComponentLoaded({
|
|
1559
|
+
requestId: loadArgs.id,
|
|
1560
|
+
componentName: loadedOptions.componentName || componentName,
|
|
1561
|
+
metadata: loadedOptions.metadata
|
|
1562
|
+
});
|
|
1563
|
+
if (typeof originalLoadedCallback === "function") originalLoadedCallback(loadedOptions);
|
|
1564
|
+
};
|
|
1565
|
+
const nextProps = {
|
|
1566
|
+
...incomingProps,
|
|
1567
|
+
[ON_MF_REMOTE_LOADED_PROP]: onMFRemoteLoaded
|
|
1568
|
+
};
|
|
1569
|
+
if (react) return react.createElement(originalComponent, nextProps);
|
|
1570
|
+
return originalComponent(nextProps);
|
|
1571
|
+
};
|
|
1572
|
+
ObservedRemoteComponent.displayName = `ObservedRemote(${componentName})`;
|
|
1573
|
+
copyComponentStatics(ObservedRemoteComponent, originalComponent);
|
|
1574
|
+
return target.createResult(ObservedRemoteComponent);
|
|
1575
|
+
};
|
|
1576
|
+
const wrapReactComponent = async (component, loadArgs) => {
|
|
1577
|
+
const wrapPolicy = getReactWrapPolicy(loadArgs);
|
|
1578
|
+
if (!wrapPolicy) return;
|
|
1579
|
+
return createReactComponentWrapper(component, loadArgs, wrapPolicy, await getReactForOrigin(loadArgs.origin));
|
|
1580
|
+
};
|
|
1581
|
+
const wrapReactComponentFactory = async (factory, loadArgs) => {
|
|
1582
|
+
const wrapPolicy = getReactWrapPolicy(loadArgs);
|
|
1583
|
+
if (!wrapPolicy || typeof factory !== "function") return;
|
|
1584
|
+
const react = await getReactForOrigin(loadArgs.origin);
|
|
1585
|
+
const originalFactory = factory;
|
|
1586
|
+
return (...factoryArgs) => {
|
|
1587
|
+
const moduleOrPromise = originalFactory(...factoryArgs);
|
|
1588
|
+
if (moduleOrPromise && typeof moduleOrPromise.then === "function") return moduleOrPromise.then((module) => {
|
|
1589
|
+
return createReactComponentWrapper(module, loadArgs, wrapPolicy, react) || module;
|
|
1590
|
+
});
|
|
1591
|
+
return createReactComponentWrapper(moduleOrPromise, loadArgs, wrapPolicy, react) || moduleOrPromise;
|
|
1592
|
+
};
|
|
1593
|
+
};
|
|
1594
|
+
const plugin = {
|
|
1595
|
+
name: pluginName,
|
|
1596
|
+
apply(instance) {
|
|
1597
|
+
appliedRuntimeVersion = sanitizeText(instance.version, 80) || appliedRuntimeVersion;
|
|
1598
|
+
if (shouldAttachInstanceApi) instance.markComponentLoaded = markComponentLoaded;
|
|
1599
|
+
},
|
|
1600
|
+
beforeRequest(args) {
|
|
1601
|
+
const requestArgs = args;
|
|
1602
|
+
if (!prepareRuntimeOrigin(requestArgs.origin)) return returnHookArgs(args);
|
|
1603
|
+
const remote = resolveRemoteFromRequestId(requestArgs.id, requestArgs.options);
|
|
1604
|
+
recordEvent({
|
|
1605
|
+
phase: "loadRemote",
|
|
1606
|
+
status: "start",
|
|
1607
|
+
requestId: requestArgs.id,
|
|
1608
|
+
remote,
|
|
1609
|
+
lifecycle: "beforeRequest",
|
|
1610
|
+
message: "remote:load-start"
|
|
1611
|
+
}, requestArgs.origin);
|
|
1612
|
+
return returnHookArgs(args);
|
|
1613
|
+
},
|
|
1614
|
+
afterMatchRemote(args) {
|
|
1615
|
+
const matchArgs = args;
|
|
1616
|
+
if (!prepareRuntimeOrigin(matchArgs.origin)) return;
|
|
1617
|
+
const remote = createRemoteInfo(matchArgs.remoteInfo || matchArgs.remote);
|
|
1618
|
+
const hostRemotes = getHostRemotesSummary(matchArgs.options);
|
|
1619
|
+
recordEvent({
|
|
1620
|
+
phase: "matchRemote",
|
|
1621
|
+
status: matchArgs.error ? "error" : "success",
|
|
1622
|
+
requestId: matchArgs.id,
|
|
1623
|
+
lifecycle: "afterMatchRemote",
|
|
1624
|
+
expose: matchArgs.expose,
|
|
1625
|
+
remote,
|
|
1626
|
+
message: matchArgs.error ? "remote:match-failed" : "remote:matched",
|
|
1627
|
+
error: matchArgs.error,
|
|
1628
|
+
errorContext: hostRemotes ? { hostRemotes } : void 0
|
|
1629
|
+
}, matchArgs.origin);
|
|
1630
|
+
},
|
|
1631
|
+
beforeLoadRemoteSnapshot(args) {
|
|
1632
|
+
prepareRuntimeOrigin(args.origin);
|
|
1633
|
+
},
|
|
1634
|
+
loadSnapshot(args) {
|
|
1635
|
+
if (!isEnabled()) return returnHookArgs(args);
|
|
1636
|
+
const snapshotArgs = args;
|
|
1637
|
+
const moduleRemote = createRemoteInfo(snapshotArgs.moduleInfo);
|
|
1638
|
+
const snapshotRemoteEntry = snapshotArgs.remoteSnapshot?.remoteEntry || snapshotArgs.remoteSnapshot?.entry;
|
|
1639
|
+
const manifestUrl = isManifestUrl(moduleRemote?.entry) ? moduleRemote?.entry : isManifestUrl(snapshotRemoteEntry) ? snapshotRemoteEntry : void 0;
|
|
1640
|
+
if (!manifestUrl) return returnHookArgs(args);
|
|
1641
|
+
const remote = createRemoteInfo({
|
|
1642
|
+
name: moduleRemote?.name || sanitizeText(snapshotArgs.remoteSnapshot?.name, 120),
|
|
1643
|
+
alias: moduleRemote?.alias,
|
|
1644
|
+
entry: manifestUrl,
|
|
1645
|
+
entryGlobalName: moduleRemote?.entryGlobalName || sanitizeText(snapshotArgs.remoteSnapshot?.entryGlobalName, 120),
|
|
1646
|
+
type: moduleRemote?.type || sanitizeText(snapshotArgs.remoteSnapshot?.type, 80)
|
|
1647
|
+
});
|
|
1648
|
+
if (seenManifestUrls.has(manifestUrl)) {
|
|
1649
|
+
recordEvent({
|
|
1650
|
+
phase: "manifest",
|
|
1651
|
+
status: "success",
|
|
1652
|
+
requestId: manifestUrl,
|
|
1653
|
+
remote,
|
|
1654
|
+
url: manifestUrl,
|
|
1655
|
+
lifecycle: "loadSnapshot",
|
|
1656
|
+
message: "manifest:cached",
|
|
1657
|
+
cached: true
|
|
1658
|
+
}, lastRuntimeOrigin);
|
|
1659
|
+
return returnHookArgs(args);
|
|
1660
|
+
}
|
|
1661
|
+
if (loadingManifestUrls.has(manifestUrl)) return returnHookArgs(args);
|
|
1662
|
+
loadingManifestUrls.add(manifestUrl);
|
|
1663
|
+
recordEvent({
|
|
1664
|
+
phase: "manifest",
|
|
1665
|
+
status: "start",
|
|
1666
|
+
requestId: manifestUrl,
|
|
1667
|
+
remote,
|
|
1668
|
+
url: manifestUrl,
|
|
1669
|
+
lifecycle: "loadSnapshot",
|
|
1670
|
+
message: "manifest:load-start"
|
|
1671
|
+
}, lastRuntimeOrigin);
|
|
1672
|
+
return returnHookArgs(args);
|
|
1673
|
+
},
|
|
1674
|
+
loadRemoteSnapshot(args) {
|
|
1675
|
+
if (options.enabled === false) return returnHookArgs(args);
|
|
1676
|
+
const snapshotArgs = args;
|
|
1677
|
+
if (snapshotArgs.from !== "manifest") return returnHookArgs(args);
|
|
1678
|
+
const manifestUrl = sanitizeUrl(snapshotArgs.manifestUrl) || sanitizeUrl(snapshotArgs.moduleInfo?.entry);
|
|
1679
|
+
recordEvent({
|
|
1680
|
+
phase: "manifest",
|
|
1681
|
+
status: "success",
|
|
1682
|
+
requestId: manifestUrl,
|
|
1683
|
+
remote: createRemoteInfo({
|
|
1684
|
+
...snapshotArgs.moduleInfo,
|
|
1685
|
+
entry: manifestUrl || snapshotArgs.moduleInfo?.entry
|
|
1686
|
+
}),
|
|
1687
|
+
url: manifestUrl,
|
|
1688
|
+
lifecycle: "loadRemoteSnapshot",
|
|
1689
|
+
message: "manifest:resolved",
|
|
1690
|
+
cached: Boolean(manifestUrl && seenManifestUrls.has(manifestUrl))
|
|
1691
|
+
}, lastRuntimeOrigin);
|
|
1692
|
+
if (manifestUrl) {
|
|
1693
|
+
loadingManifestUrls.delete(manifestUrl);
|
|
1694
|
+
seenManifestUrls.add(manifestUrl);
|
|
1695
|
+
}
|
|
1696
|
+
return returnHookArgs(args);
|
|
1697
|
+
},
|
|
1698
|
+
afterResolve(args) {
|
|
1699
|
+
const resolveArgs = args;
|
|
1700
|
+
if (!prepareRuntimeOrigin(resolveArgs.origin)) return returnHookArgs(args);
|
|
1701
|
+
if (!isManifestUrl(createRemoteInfo(resolveArgs.remoteInfo || resolveArgs.remote)?.entry)) return returnHookArgs(args);
|
|
1702
|
+
return returnHookArgs(args);
|
|
1703
|
+
},
|
|
1704
|
+
async onLoad(args) {
|
|
1705
|
+
const loadArgs = args;
|
|
1706
|
+
if (!prepareRuntimeOrigin(loadArgs.origin)) return;
|
|
1707
|
+
const wrappedComponent = typeof loadArgs.exposeModuleFactory === "function" ? await wrapReactComponentFactory(loadArgs.exposeModuleFactory, loadArgs) : await wrapReactComponent(loadArgs.exposeModule, loadArgs);
|
|
1708
|
+
const remote = createRemoteInfo(loadArgs.remote);
|
|
1709
|
+
recordEvent({
|
|
1710
|
+
phase: "loadRemote",
|
|
1711
|
+
status: "success",
|
|
1712
|
+
requestId: loadArgs.id,
|
|
1713
|
+
lifecycle: "onLoad",
|
|
1714
|
+
expose: loadArgs.expose,
|
|
1715
|
+
remote,
|
|
1716
|
+
message: "remote:loaded",
|
|
1717
|
+
loadedBefore: shouldCollectLoadedBefore() ? collectLoadedBeforeInfo(remote, loadArgs.expose, loadArgs.origin) : void 0
|
|
1718
|
+
}, loadArgs.origin);
|
|
1719
|
+
if (wrappedComponent) return wrappedComponent;
|
|
1720
|
+
},
|
|
1721
|
+
errorLoadRemote(args) {
|
|
1722
|
+
const errorArgs = args;
|
|
1723
|
+
if (!prepareRuntimeOrigin(errorArgs.origin) || errorArgs.lifecycle !== "onLoad" && errorArgs.lifecycle !== "beforeRequest" && errorArgs.lifecycle !== "afterResolve") return;
|
|
1724
|
+
const isManifestError = errorArgs.lifecycle === "afterResolve";
|
|
1725
|
+
if (isManifestError && errorArgs.id) loadingManifestUrls.delete(errorArgs.id);
|
|
1726
|
+
const remote = createRemoteInfo(errorArgs.remote);
|
|
1727
|
+
recordEvent({
|
|
1728
|
+
phase: isManifestError ? "manifest" : "loadRemote",
|
|
1729
|
+
status: "error",
|
|
1730
|
+
requestId: errorArgs.id,
|
|
1731
|
+
lifecycle: errorArgs.lifecycle,
|
|
1732
|
+
expose: errorArgs.expose,
|
|
1733
|
+
remote,
|
|
1734
|
+
url: isManifestError ? errorArgs.id : void 0,
|
|
1735
|
+
message: isManifestError ? "manifest:failed" : errorArgs.lifecycle ? `remote:${errorArgs.lifecycle}:failed` : "remote:failed",
|
|
1736
|
+
error: errorArgs.error,
|
|
1737
|
+
loadedBefore: collectLoadedBeforeInfo(remote, errorArgs.expose, errorArgs.origin)
|
|
1738
|
+
}, errorArgs.origin);
|
|
1739
|
+
},
|
|
1740
|
+
afterLoadRemote(args) {
|
|
1741
|
+
const loadArgs = args;
|
|
1742
|
+
if (!prepareRuntimeOrigin(loadArgs.origin)) return;
|
|
1743
|
+
const remote = createRemoteInfo(loadArgs.remote);
|
|
1744
|
+
recordEvent({
|
|
1745
|
+
phase: "loadRemote",
|
|
1746
|
+
status: "complete",
|
|
1747
|
+
requestId: loadArgs.id,
|
|
1748
|
+
lifecycle: "afterLoadRemote",
|
|
1749
|
+
expose: loadArgs.expose,
|
|
1750
|
+
remote,
|
|
1751
|
+
message: loadArgs.recovered ? "remote:load-recovered" : loadArgs.error ? "remote:load-failed" : "remote:load-complete",
|
|
1752
|
+
error: loadArgs.error,
|
|
1753
|
+
recovered: loadArgs.recovered,
|
|
1754
|
+
loadedBefore: shouldCollectLoadedBefore(loadArgs.error) ? collectLoadedBeforeInfo(remote, loadArgs.expose, loadArgs.origin) : void 0
|
|
1755
|
+
}, loadArgs.origin);
|
|
1756
|
+
},
|
|
1757
|
+
loadEntry(args) {
|
|
1758
|
+
const entryArgs = args;
|
|
1759
|
+
if (shouldSkipRuntimeHook(entryArgs.origin) || !prepareRuntimeOrigin(entryArgs.origin)) return;
|
|
1760
|
+
const remote = createRemoteInfo(entryArgs.remoteInfo);
|
|
1761
|
+
recordEvent({
|
|
1762
|
+
phase: "remoteEntry",
|
|
1763
|
+
status: "start",
|
|
1764
|
+
requestId: remote?.name,
|
|
1765
|
+
remote,
|
|
1766
|
+
url: remote?.entry,
|
|
1767
|
+
lifecycle: "loadEntry",
|
|
1768
|
+
message: "remoteEntry:load-start"
|
|
1769
|
+
}, entryArgs.origin);
|
|
1770
|
+
},
|
|
1771
|
+
afterLoadEntry(args) {
|
|
1772
|
+
const entryArgs = args;
|
|
1773
|
+
if (shouldSkipRuntimeHook(entryArgs.origin) || !prepareRuntimeOrigin(entryArgs.origin)) return;
|
|
1774
|
+
const remote = createRemoteInfo(entryArgs.remoteInfo);
|
|
1775
|
+
const remoteEntryKey = getRemoteEntryKey(sanitizeRemote(remote));
|
|
1776
|
+
const cached = entryArgs.cached === true || Boolean(remoteEntryKey && seenRemoteEntryKeys.has(remoteEntryKey));
|
|
1777
|
+
recordEvent({
|
|
1778
|
+
phase: "remoteEntry",
|
|
1779
|
+
status: entryArgs.error ? "error" : "success",
|
|
1780
|
+
requestId: remote?.name,
|
|
1781
|
+
remote,
|
|
1782
|
+
url: remote?.entry,
|
|
1783
|
+
lifecycle: "afterLoadEntry",
|
|
1784
|
+
message: entryArgs.error ? "remoteEntry:load-failed" : entryArgs.recovered ? "remoteEntry:load-recovered" : "remoteEntry:loaded",
|
|
1785
|
+
error: entryArgs.error,
|
|
1786
|
+
recovered: entryArgs.recovered,
|
|
1787
|
+
cached
|
|
1788
|
+
}, entryArgs.origin);
|
|
1789
|
+
if (!entryArgs.error && remoteEntryKey) seenRemoteEntryKeys.add(remoteEntryKey);
|
|
1790
|
+
},
|
|
1791
|
+
beforeInitRemote(args) {
|
|
1792
|
+
const initArgs = args;
|
|
1793
|
+
if (shouldSkipRuntimeHook(initArgs.origin) || !prepareRuntimeOrigin(initArgs.origin)) return;
|
|
1794
|
+
const remote = createRemoteInfo(initArgs.remoteInfo);
|
|
1795
|
+
recordEvent({
|
|
1796
|
+
phase: "remoteEntryInit",
|
|
1797
|
+
status: "start",
|
|
1798
|
+
requestId: initArgs.id || remote?.name,
|
|
1799
|
+
remote,
|
|
1800
|
+
lifecycle: "beforeInitRemote",
|
|
1801
|
+
message: "remoteEntry:init-start"
|
|
1802
|
+
}, initArgs.origin);
|
|
1803
|
+
},
|
|
1804
|
+
afterInitRemote(args) {
|
|
1805
|
+
const initArgs = args;
|
|
1806
|
+
if (shouldSkipRuntimeHook(initArgs.origin) || !prepareRuntimeOrigin(initArgs.origin)) return;
|
|
1807
|
+
const remote = createRemoteInfo(initArgs.remoteInfo);
|
|
1808
|
+
recordEvent({
|
|
1809
|
+
phase: "remoteEntryInit",
|
|
1810
|
+
status: initArgs.error ? "error" : "success",
|
|
1811
|
+
requestId: initArgs.id || remote?.name,
|
|
1812
|
+
remote,
|
|
1813
|
+
lifecycle: "afterInitRemote",
|
|
1814
|
+
message: initArgs.error ? "remoteEntry:init-failed" : initArgs.cached ? "remoteEntry:init-reused" : "remoteEntry:initialized",
|
|
1815
|
+
error: initArgs.error,
|
|
1816
|
+
cached: initArgs.cached
|
|
1817
|
+
}, initArgs.origin);
|
|
1818
|
+
},
|
|
1819
|
+
beforeGetExpose(args) {
|
|
1820
|
+
const exposeArgs = args;
|
|
1821
|
+
if (shouldSkipRuntimeHook(exposeArgs.origin) || !prepareRuntimeOrigin(exposeArgs.origin)) return;
|
|
1822
|
+
recordEvent({
|
|
1823
|
+
phase: "expose",
|
|
1824
|
+
status: "start",
|
|
1825
|
+
requestId: exposeArgs.id,
|
|
1826
|
+
expose: exposeArgs.expose,
|
|
1827
|
+
remote: createRemoteInfo(exposeArgs.moduleInfo),
|
|
1828
|
+
lifecycle: "beforeGetExpose",
|
|
1829
|
+
message: "expose:get-start"
|
|
1830
|
+
}, exposeArgs.origin);
|
|
1831
|
+
},
|
|
1832
|
+
afterGetExpose(args) {
|
|
1833
|
+
const exposeArgs = args;
|
|
1834
|
+
if (shouldSkipRuntimeHook(exposeArgs.origin) || !prepareRuntimeOrigin(exposeArgs.origin)) return;
|
|
1835
|
+
const remote = createRemoteInfo(exposeArgs.moduleInfo);
|
|
1836
|
+
recordEvent({
|
|
1837
|
+
phase: "expose",
|
|
1838
|
+
status: exposeArgs.error ? "error" : "success",
|
|
1839
|
+
requestId: exposeArgs.id,
|
|
1840
|
+
expose: exposeArgs.expose,
|
|
1841
|
+
remote,
|
|
1842
|
+
lifecycle: "afterGetExpose",
|
|
1843
|
+
message: exposeArgs.error ? "expose:get-failed" : "expose:resolved",
|
|
1844
|
+
error: exposeArgs.error,
|
|
1845
|
+
loadedBefore: shouldCollectLoadedBefore(exposeArgs.error) ? collectLoadedBeforeInfo(remote, exposeArgs.expose, exposeArgs.origin) : void 0
|
|
1846
|
+
}, exposeArgs.origin);
|
|
1847
|
+
},
|
|
1848
|
+
beforeExecuteFactory(args) {
|
|
1849
|
+
const factoryArgs = args;
|
|
1850
|
+
if (shouldSkipRuntimeHook(factoryArgs.origin) || !prepareRuntimeOrigin(factoryArgs.origin)) return;
|
|
1851
|
+
recordEvent({
|
|
1852
|
+
phase: "moduleFactory",
|
|
1853
|
+
status: "start",
|
|
1854
|
+
requestId: factoryArgs.id,
|
|
1855
|
+
expose: factoryArgs.expose,
|
|
1856
|
+
remote: createRemoteInfo(factoryArgs.moduleInfo),
|
|
1857
|
+
lifecycle: "beforeExecuteFactory",
|
|
1858
|
+
message: "moduleFactory:execute-start"
|
|
1859
|
+
}, factoryArgs.origin);
|
|
1860
|
+
},
|
|
1861
|
+
afterExecuteFactory(args) {
|
|
1862
|
+
const factoryArgs = args;
|
|
1863
|
+
if (shouldSkipRuntimeHook(factoryArgs.origin) || !prepareRuntimeOrigin(factoryArgs.origin)) return;
|
|
1864
|
+
const remote = createRemoteInfo(factoryArgs.moduleInfo);
|
|
1865
|
+
recordEvent({
|
|
1866
|
+
phase: "moduleFactory",
|
|
1867
|
+
status: factoryArgs.error ? "error" : "success",
|
|
1868
|
+
requestId: factoryArgs.id,
|
|
1869
|
+
expose: factoryArgs.expose,
|
|
1870
|
+
remote,
|
|
1871
|
+
lifecycle: "afterExecuteFactory",
|
|
1872
|
+
message: factoryArgs.error ? "moduleFactory:execute-failed" : "moduleFactory:executed",
|
|
1873
|
+
error: factoryArgs.error,
|
|
1874
|
+
loadedBefore: shouldCollectLoadedBefore(factoryArgs.error) ? collectLoadedBeforeInfo(remote, factoryArgs.expose, factoryArgs.origin) : void 0
|
|
1875
|
+
}, factoryArgs.origin);
|
|
1876
|
+
},
|
|
1877
|
+
beforeLoadShare(args) {
|
|
1878
|
+
if (shouldGuardSharedHooksByRuntimeVersion && !supportsRuntimeHookObservability(args.origin)) return returnHookArgs(args);
|
|
1879
|
+
if (!prepareRuntimeOrigin(args.origin)) return returnHookArgs(args);
|
|
1880
|
+
recordEvent({
|
|
1881
|
+
phase: "shared",
|
|
1882
|
+
status: "start",
|
|
1883
|
+
requestId: `shared:${args.pkgName}`,
|
|
1884
|
+
lifecycle: "loadShare",
|
|
1885
|
+
shared: createSharedInfo(args),
|
|
1886
|
+
message: "shared:load-start"
|
|
1887
|
+
}, args.origin);
|
|
1888
|
+
return returnHookArgs(args);
|
|
1889
|
+
},
|
|
1890
|
+
afterLoadShare(args) {
|
|
1891
|
+
if (shouldGuardSharedHooksByRuntimeVersion && !supportsRuntimeHookObservability(args.origin)) return returnHookArgs(args);
|
|
1892
|
+
if (!prepareRuntimeOrigin(args.origin)) return returnHookArgs(args);
|
|
1893
|
+
recordEvent({
|
|
1894
|
+
phase: "shared",
|
|
1895
|
+
status: "success",
|
|
1896
|
+
requestId: `shared:${args.pkgName}`,
|
|
1897
|
+
lifecycle: args.lifecycle,
|
|
1898
|
+
shared: createSharedInfo(args),
|
|
1899
|
+
message: args.lifecycle === "loadShareSync" ? "shared:resolved-sync" : "shared:resolved"
|
|
1900
|
+
}, args.origin);
|
|
1901
|
+
return returnHookArgs(args);
|
|
1902
|
+
},
|
|
1903
|
+
errorLoadShare(args) {
|
|
1904
|
+
if (shouldGuardSharedHooksByRuntimeVersion && !supportsRuntimeHookObservability(args.origin)) return returnHookArgs(args);
|
|
1905
|
+
if (!prepareRuntimeOrigin(args.origin)) return returnHookArgs(args);
|
|
1906
|
+
const handledCustomShareMiss = args.recovered === true && !args.error;
|
|
1907
|
+
const reason = handledCustomShareMiss ? "custom-share-info-unmatched" : getSharedErrorReason(args);
|
|
1908
|
+
recordEvent({
|
|
1909
|
+
phase: "shared",
|
|
1910
|
+
status: handledCustomShareMiss ? "complete" : "error",
|
|
1911
|
+
requestId: `shared:${args.pkgName}`,
|
|
1912
|
+
lifecycle: args.lifecycle,
|
|
1913
|
+
shared: createSharedInfo(args, reason),
|
|
1914
|
+
message: reason ? `shared:${reason}` : void 0,
|
|
1915
|
+
error: handledCustomShareMiss ? void 0 : args.error,
|
|
1916
|
+
recovered: args.recovered
|
|
1917
|
+
}, args.origin);
|
|
1918
|
+
return returnHookArgs(args);
|
|
1919
|
+
}
|
|
1920
|
+
};
|
|
1921
|
+
if (!shouldDisablePreloadHooks) {
|
|
1922
|
+
plugin.generatePreloadAssets = (args) => {
|
|
1923
|
+
const preloadArgs = args;
|
|
1924
|
+
if (!prepareRuntimeOrigin(preloadArgs.origin)) return returnHookArgs(args);
|
|
1925
|
+
const remote = createRemoteInfo(preloadArgs.remoteInfo || preloadArgs.remote);
|
|
1926
|
+
const preloadConfig = preloadArgs.preloadOptions?.preloadConfig;
|
|
1927
|
+
recordEvent({
|
|
1928
|
+
phase: "preload",
|
|
1929
|
+
status: "start",
|
|
1930
|
+
requestId: remote?.name || sanitizeText(preloadConfig?.nameOrAlias, 160),
|
|
1931
|
+
remote,
|
|
1932
|
+
lifecycle: "generatePreloadAssets",
|
|
1933
|
+
message: "preload:assets-ready",
|
|
1934
|
+
metadata: clipObservabilityMetadata({
|
|
1935
|
+
nameOrAlias: preloadConfig?.nameOrAlias,
|
|
1936
|
+
exposes: preloadConfig?.exposes?.join(","),
|
|
1937
|
+
resourceCategory: preloadConfig?.resourceCategory,
|
|
1938
|
+
share: preloadConfig?.share,
|
|
1939
|
+
depsRemote: Array.isArray(preloadConfig?.depsRemote) ? "custom" : preloadConfig?.depsRemote
|
|
1940
|
+
})
|
|
1941
|
+
}, preloadArgs.origin);
|
|
1942
|
+
return returnHookArgs(args);
|
|
1943
|
+
};
|
|
1944
|
+
plugin.afterPreloadRemote = (args) => {
|
|
1945
|
+
const preloadArgs = args;
|
|
1946
|
+
if (!prepareRuntimeOrigin(preloadArgs.origin)) return returnHookArgs(args);
|
|
1947
|
+
const results = preloadArgs.results || [];
|
|
1948
|
+
if (results.length === 0 && preloadArgs.error) {
|
|
1949
|
+
recordEvent({
|
|
1950
|
+
phase: "preload",
|
|
1951
|
+
status: "error",
|
|
1952
|
+
requestId: "preloadRemote",
|
|
1953
|
+
lifecycle: "afterPreloadRemote",
|
|
1954
|
+
message: "preload:failed",
|
|
1955
|
+
error: preloadArgs.error
|
|
1956
|
+
}, preloadArgs.origin);
|
|
1957
|
+
return returnHookArgs(args);
|
|
1958
|
+
}
|
|
1959
|
+
results.forEach((preloadResult) => {
|
|
1960
|
+
const remote = createRemoteInfo(preloadResult.remoteInfo || preloadResult.remote);
|
|
1961
|
+
const requestId = sanitizeRequestId(preloadResult.id) || remote?.name || sanitizeText(preloadResult.preloadConfig?.nameOrAlias, 160);
|
|
1962
|
+
preloadResult.results?.forEach((assetResult) => {
|
|
1963
|
+
const isError = assetResult.status === "error" || assetResult.status === "timeout";
|
|
1964
|
+
recordEvent({
|
|
1965
|
+
phase: "preload",
|
|
1966
|
+
status: isError ? "error" : "success",
|
|
1967
|
+
requestId,
|
|
1968
|
+
remote,
|
|
1969
|
+
url: assetResult.url,
|
|
1970
|
+
cached: assetResult.status === "cached",
|
|
1971
|
+
lifecycle: "afterPreloadRemote",
|
|
1972
|
+
message: `preload:${assetResult.resourceType || "resource"}:${assetResult.status || "complete"}`,
|
|
1973
|
+
error: isError ? assetResult.error : void 0,
|
|
1974
|
+
errorContext: isError ? {
|
|
1975
|
+
resourceType: assetResult.resourceType,
|
|
1976
|
+
initiator: assetResult.initiator,
|
|
1977
|
+
status: assetResult.status,
|
|
1978
|
+
id: assetResult.id
|
|
1979
|
+
} : void 0,
|
|
1980
|
+
metadata: clipObservabilityMetadata({
|
|
1981
|
+
resourceType: assetResult.resourceType,
|
|
1982
|
+
initiator: assetResult.initiator,
|
|
1983
|
+
status: assetResult.status,
|
|
1984
|
+
id: assetResult.id,
|
|
1985
|
+
preloadNameOrAlias: preloadResult.preloadConfig?.nameOrAlias
|
|
1986
|
+
})
|
|
1987
|
+
}, preloadArgs.origin);
|
|
1988
|
+
});
|
|
1989
|
+
});
|
|
1990
|
+
return returnHookArgs(args);
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
return {
|
|
1994
|
+
plugin,
|
|
1995
|
+
getEvents() {
|
|
1996
|
+
return getEventsSnapshot();
|
|
1997
|
+
},
|
|
1998
|
+
getTraceIds() {
|
|
1999
|
+
return getTraceIdsSnapshot();
|
|
2000
|
+
},
|
|
2001
|
+
getReports(options) {
|
|
2002
|
+
return getReportsSnapshot(options);
|
|
2003
|
+
},
|
|
2004
|
+
findReports(query) {
|
|
2005
|
+
return findReportsSnapshot(query);
|
|
2006
|
+
},
|
|
2007
|
+
getLatestReport() {
|
|
2008
|
+
return getLatestReportSnapshot();
|
|
2009
|
+
},
|
|
2010
|
+
getReport(traceId) {
|
|
2011
|
+
return getReportSnapshot(traceId);
|
|
2012
|
+
},
|
|
2013
|
+
exportReport(traceId) {
|
|
2014
|
+
return exportReportSnapshot(traceId);
|
|
2015
|
+
},
|
|
2016
|
+
clear() {
|
|
2017
|
+
events.length = 0;
|
|
2018
|
+
reports.clear();
|
|
2019
|
+
traceByRequest.clear();
|
|
2020
|
+
traceByRemote.clear();
|
|
2021
|
+
phaseStartTimes.clear();
|
|
2022
|
+
seenManifestUrls.clear();
|
|
2023
|
+
seenRemoteEntryKeys.clear();
|
|
2024
|
+
consoleReportedTraceIds.clear();
|
|
2025
|
+
consoleReportedStartKeys.clear();
|
|
2026
|
+
latestTraceId = void 0;
|
|
2027
|
+
runtimeObservabilityEnabled = false;
|
|
2028
|
+
effectiveMaxEvents = configuredMaxEvents;
|
|
2029
|
+
browserGlobalScope = void 0;
|
|
2030
|
+
lastRuntimeOrigin = void 0;
|
|
2031
|
+
},
|
|
2032
|
+
markComponentLoaded
|
|
2033
|
+
};
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
//#endregion
|
|
2037
|
+
Object.defineProperty(exports, 'createObservability', {
|
|
2038
|
+
enumerable: true,
|
|
2039
|
+
get: function () {
|
|
2040
|
+
return createObservability;
|
|
2041
|
+
}
|
|
2042
|
+
});
|