@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/dist/index.js CHANGED
@@ -1,1444 +1,9 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
2
+ const require_core = require('./core--1ofIHU9.js');
3
+ const require_browser = require('./browser.js');
4
+ const require_chrome_devtool = require('./chrome-devtool.js');
2
5
 
3
- //#region src/index.ts
4
- const DEFAULT_MAX_EVENTS = 100;
5
- const HARD_MAX_EVENTS = 1e3;
6
- const COMPONENT_BUSINESS_LOADED_EVENT = "component:business-loaded";
7
- const SENSITIVE_PAIR_PATTERN = /\b(token|authorization|cookie|secret|password|session|access_token|refresh_token|api_key|apikey|key)\s*[:=]\s*([^&\s'",;<>]+)/gi;
8
- const ERROR_CODE_PATTERN = /\b(?:RUNTIME|TYPE|BUILD)-\d{3}\b/;
9
- const URL_PATTERN = /https?:\/\/[^\s'"<>]+/g;
10
- const DIAGNOSTIC_DOC_LINK_PATTERN = /https?:\/\/module-federation\.io\/guide\/troubleshooting\/[^\s'"<>]+/i;
11
- const RUNTIME_DOC_LINK = "https://module-federation.io/guide/troubleshooting/runtime";
12
- const MAX_METADATA_KEYS = 20;
13
- const MAX_FACT_KEYS = 50;
14
- const MAX_MODULE_INFO_ENTRIES = 20;
15
- const HARD_MAX_REPORT_QUERY_LIMIT = 1e3;
16
- let traceCounter = 0;
17
- function isRecord(value) {
18
- return typeof value === "object" && value !== null;
19
- }
20
- function normalizeMaxEvents(value, fallback) {
21
- if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
22
- return Math.max(1, Math.min(HARD_MAX_EVENTS, Math.floor(value)));
23
- }
24
- function normalizeQueryLimit(value) {
25
- if (typeof value !== "number" || !Number.isFinite(value)) return;
26
- return Math.max(1, Math.min(HARD_MAX_REPORT_QUERY_LIMIT, Math.floor(value)));
27
- }
28
- function sanitizeText(value, maxLength = 800) {
29
- if (value === void 0 || value === null) return;
30
- const sanitized = String(value).replace(URL_PATTERN, (url) => sanitizeUrl(url) || "[redacted-url]").replace(SENSITIVE_PAIR_PATTERN, "[redacted]");
31
- return sanitized.length > maxLength ? `${sanitized.slice(0, maxLength)}...` : sanitized;
32
- }
33
- function getRawText(value) {
34
- if (value === void 0 || value === null) return;
35
- return String(value);
36
- }
37
- function clipText(value, maxLength = 320) {
38
- if (value === void 0 || value === null) return;
39
- const sanitized = String(value);
40
- return sanitized.length > maxLength ? `${sanitized.slice(0, maxLength)}...` : sanitized;
41
- }
42
- function clipObservabilityMetadata(metadata, maxKeys = MAX_METADATA_KEYS) {
43
- if (!metadata || typeof metadata !== "object") return;
44
- const clipped = {};
45
- Object.entries(metadata).slice(0, maxKeys).forEach(([rawKey, rawValue]) => {
46
- const key = clipText(rawKey, 80);
47
- if (!key || rawValue === void 0 || rawValue === null) return;
48
- if (typeof rawValue === "boolean") {
49
- clipped[key] = rawValue;
50
- return;
51
- }
52
- if (typeof rawValue === "number") {
53
- if (Number.isFinite(rawValue)) clipped[key] = rawValue;
54
- return;
55
- }
56
- const value = clipText(rawValue, 240);
57
- if (value) clipped[key] = value;
58
- });
59
- return Object.keys(clipped).length ? clipped : void 0;
60
- }
61
- function clipMetadata(metadata, maxKeys = MAX_METADATA_KEYS) {
62
- if (!metadata || typeof metadata !== "object") return;
63
- const clipped = {};
64
- Object.entries(metadata).slice(0, maxKeys).forEach(([rawKey, rawValue]) => {
65
- const key = sanitizeText(rawKey, 80);
66
- if (!key || rawValue === void 0 || rawValue === null) return;
67
- if (typeof rawValue === "boolean") {
68
- clipped[key] = rawValue;
69
- return;
70
- }
71
- if (typeof rawValue === "number") {
72
- if (Number.isFinite(rawValue)) clipped[key] = rawValue;
73
- return;
74
- }
75
- const value = clipText(rawValue, 240);
76
- if (value) clipped[key] = value;
77
- });
78
- return Object.keys(clipped).length ? clipped : void 0;
79
- }
80
- function sanitizeStack(stack, options) {
81
- if (!stack || options?.enabled === false) return;
82
- return stack;
83
- }
84
- function getRawStack(error) {
85
- if (error instanceof Error) return error.stack || error.message;
86
- }
87
- function sanitizeRequestId(value) {
88
- if (!value) return;
89
- return clipText(value, 240);
90
- }
91
- function sanitizeUrl(value) {
92
- if (!value) return;
93
- try {
94
- const base = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
95
- const parsedUrl = new URL(value, base);
96
- const sanitized = `${parsedUrl.origin}${parsedUrl.pathname}`;
97
- return /^https?:\/\//i.test(value) ? sanitized : parsedUrl.pathname;
98
- } catch {
99
- const [withoutHash] = value.split("#");
100
- const [withoutQuery] = withoutHash.split("?");
101
- return sanitizeText(withoutQuery, 240);
102
- }
103
- }
104
- function sanitizeRemote(remote) {
105
- if (!remote || !remote.name) return;
106
- return {
107
- name: remote.name,
108
- alias: sanitizeText(remote.alias, 120),
109
- entry: clipText(remote.entry, 320),
110
- entryGlobalName: sanitizeText(remote.entryGlobalName, 120),
111
- type: sanitizeText(remote.type, 80)
112
- };
113
- }
114
- function createRemoteInfo(remote) {
115
- if (!remote?.name) return;
116
- return {
117
- name: remote.name,
118
- alias: remote.alias,
119
- entry: remote.entry,
120
- entryGlobalName: remote.entryGlobalName,
121
- type: remote.type
122
- };
123
- }
124
- function isManifestUrl(value) {
125
- const sanitized = sanitizeUrl(value);
126
- return Boolean(sanitized && /manifest.*\.json$/i.test(sanitized));
127
- }
128
- function normalizeSharedScope(value) {
129
- if (!value) return [];
130
- return (Array.isArray(value) ? value : [value]).map((scope) => sanitizeText(scope, 120)).filter((scope) => Boolean(scope));
131
- }
132
- function getSharedScopes(shareInfo) {
133
- return normalizeSharedScope(shareInfo?.scope).length ? normalizeSharedScope(shareInfo?.scope) : ["default"];
134
- }
135
- function getAvailableSharedVersions(args) {
136
- const versions = /* @__PURE__ */ new Set();
137
- const shareScopeMap = args.shareScopeMap || {};
138
- getSharedScopes(args.shareInfo).forEach((scope) => {
139
- Object.keys(shareScopeMap[scope]?.[args.pkgName] || {}).forEach((version) => {
140
- versions.add(version);
141
- });
142
- });
143
- return Array.from(versions);
144
- }
145
- function getSharedMissReason(args) {
146
- if (!args.shareInfo) return "missing-config";
147
- return getAvailableSharedVersions(args).length ? "version-mismatch" : "missing-provider";
148
- }
149
- function getSharedErrorReason(args) {
150
- if (args.recovered) return getSharedMissReason(args);
151
- const errorMessage = getErrorInfo(args.error, { enabled: false }).errorMessage || "";
152
- if (!args.shareInfo || /Cannot find shared/i.test(errorMessage)) return "missing-config";
153
- if (args.lifecycle === "loadShareSync" && typeof args.shareInfo.get === "function" && /RUNTIME-00[56]/.test(errorMessage)) return "sync-async-boundary";
154
- if (args.lifecycle === "loadShareSync" && !args.shareInfo.get && /RUNTIME-006/.test(errorMessage)) return getSharedMissReason(args);
155
- if (args.error) return "load-error";
156
- }
157
- function createSharedInfo(args, reason) {
158
- const shareConfig = args.shareInfo?.shareConfig;
159
- return {
160
- name: args.pkgName,
161
- shareScope: getSharedScopes(args.shareInfo),
162
- requiredVersion: shareConfig?.requiredVersion,
163
- selectedVersion: args.selectedShared?.version,
164
- availableVersions: getAvailableSharedVersions(args),
165
- provider: args.selectedShared?.from,
166
- from: args.shareInfo?.from,
167
- singleton: shareConfig?.singleton,
168
- strictVersion: shareConfig?.strictVersion,
169
- eager: shareConfig?.eager,
170
- strategy: args.shareInfo?.strategy,
171
- loaded: args.selectedShared?.loaded,
172
- loading: Boolean(args.selectedShared?.loading) || void 0,
173
- reason
174
- };
175
- }
176
- function sanitizeShared(shared) {
177
- if (!shared || !shared.name) return;
178
- return {
179
- name: sanitizeText(shared.name, 160) || "unknown",
180
- shareScope: normalizeSharedScope(shared.shareScope),
181
- requiredVersion: shared.requiredVersion === false ? false : sanitizeText(shared.requiredVersion, 120),
182
- selectedVersion: sanitizeText(shared.selectedVersion, 120),
183
- availableVersions: (shared.availableVersions || []).map((version) => sanitizeText(version, 120)).filter((version) => Boolean(version)).slice(0, 20),
184
- provider: sanitizeText(shared.provider, 160),
185
- from: sanitizeText(shared.from, 160),
186
- singleton: shared.singleton,
187
- strictVersion: shared.strictVersion,
188
- eager: shared.eager,
189
- strategy: sanitizeText(shared.strategy, 80),
190
- loaded: shared.loaded,
191
- loading: shared.loading,
192
- reason: sanitizeText(shared.reason, 120)
193
- };
194
- }
195
- function normalizeEventSource(value) {
196
- return value === "runtime" || value === "business" ? value : void 0;
197
- }
198
- function extractErrorCode(value) {
199
- const matched = String(value ?? "").match(ERROR_CODE_PATTERN)?.[0];
200
- return matched ? sanitizeText(matched, 40) : void 0;
201
- }
202
- function getErrorInfo(error, stackTraceOptions) {
203
- if (!error) return {};
204
- if (error instanceof Error) return {
205
- errorCode: extractErrorCode(`${error.name}\n${error.message}\n${error.stack || ""}`),
206
- errorName: getRawText(error.name),
207
- errorMessage: getRawText(error.message),
208
- errorStack: sanitizeStack(error.stack, stackTraceOptions)
209
- };
210
- return {
211
- errorCode: extractErrorCode(error),
212
- errorMessage: getRawText(error)
213
- };
214
- }
215
- function omitUndefinedFields(value) {
216
- if (Array.isArray(value)) return value.map((item) => omitUndefinedFields(item));
217
- if (!value || typeof value !== "object") return value;
218
- const cleanValue = {};
219
- Object.entries(value).forEach(([key, item]) => {
220
- if (item === void 0) return;
221
- cleanValue[key] = omitUndefinedFields(item);
222
- });
223
- return cleanValue;
224
- }
225
- function copyEvent(event) {
226
- return omitUndefinedFields({
227
- ...event,
228
- remote: event.remote ? { ...event.remote } : void 0,
229
- shared: event.shared ? {
230
- ...event.shared,
231
- shareScope: event.shared.shareScope ? [...event.shared.shareScope] : void 0,
232
- availableVersions: event.shared.availableVersions ? [...event.shared.availableVersions] : void 0
233
- } : void 0,
234
- errorContext: event.errorContext ? { ...event.errorContext } : void 0,
235
- metadata: event.metadata ? { ...event.metadata } : void 0
236
- });
237
- }
238
- function copySummary(summary) {
239
- return {
240
- ...summary,
241
- phases: Object.entries(summary.phases).reduce((memo, [phase, phaseSummary]) => {
242
- memo[phase] = { ...phaseSummary };
243
- return memo;
244
- }, {}),
245
- shared: summary.shared ? {
246
- ...summary.shared,
247
- shareScope: summary.shared.shareScope ? [...summary.shared.shareScope] : void 0
248
- } : void 0,
249
- flags: { ...summary.flags },
250
- error: summary.error ? {
251
- ...summary.error,
252
- context: summary.error.context ? { ...summary.error.context } : void 0
253
- } : void 0
254
- };
255
- }
256
- function copyFactReport(diagnosis) {
257
- if (!diagnosis) return;
258
- return {
259
- ...diagnosis,
260
- facts: { ...diagnosis.facts },
261
- completedPhases: [...diagnosis.completedPhases],
262
- pendingPhases: [...diagnosis.pendingPhases],
263
- warnings: diagnosis.warnings ? [...diagnosis.warnings] : void 0,
264
- actions: diagnosis.actions.map((action) => ({ ...action }))
265
- };
266
- }
267
- function copyModuleInfoSummary(moduleInfo) {
268
- if (!moduleInfo) return;
269
- return {
270
- ...moduleInfo,
271
- entries: moduleInfo.entries.map((entry) => ({ ...entry })),
272
- availableNames: moduleInfo.availableNames ? [...moduleInfo.availableNames] : void 0
273
- };
274
- }
275
- function copyReport(report) {
276
- return omitUndefinedFields({
277
- ...report,
278
- remote: report.remote ? { ...report.remote } : void 0,
279
- shared: report.shared ? {
280
- ...report.shared,
281
- shareScope: report.shared.shareScope ? [...report.shared.shareScope] : void 0,
282
- availableVersions: report.shared.availableVersions ? [...report.shared.availableVersions] : void 0
283
- } : void 0,
284
- errorContext: report.errorContext ? { ...report.errorContext } : void 0,
285
- moduleInfo: copyModuleInfoSummary(report.moduleInfo),
286
- events: report.events.map(copyEvent),
287
- summary: copySummary(report.summary),
288
- diagnosis: copyFactReport(report.diagnosis)
289
- });
290
- }
291
- function getFederationGlobal() {
292
- return globalThis.__FEDERATION__;
293
- }
294
- function normalizeScope(value) {
295
- return sanitizeText(value, 120)?.replace(/[^\w:@.-]+/g, "-") || "default";
296
- }
297
- function shouldRecordEvent(level, event) {
298
- if (level === "verbose") return true;
299
- if (level === "summary") return event.status !== "start";
300
- return event.status === "error" || Boolean(event.error);
301
- }
302
- function createTraceId(event) {
303
- traceCounter += 1;
304
- return `mf-${(event.remote?.name || event.phase || "runtime").replace(/[^a-z0-9]+/gi, "-").slice(0, 80)}-${Date.now().toString(36)}-${traceCounter.toString(36)}`;
305
- }
306
- function getPhaseDurationKey(event) {
307
- const exposeKey = event.phase === "expose" || event.phase === "moduleFactory" ? event.expose || "" : "";
308
- return [
309
- event.traceId,
310
- event.phase,
311
- event.requestId || event.remote?.name || event.shared?.name || "",
312
- exposeKey
313
- ].join("|");
314
- }
315
- function getRemoteEntryKey(remote) {
316
- if (!remote?.name) return;
317
- return [
318
- remote.name,
319
- remote.entryGlobalName || "",
320
- remote.entry || ""
321
- ].join("|");
322
- }
323
- function getHostRemotesSummary(options) {
324
- const remotes = (options?.remotes || []).map((remote) => clipText(remote.alias || remote.name || remote.entry, 120)).filter((remote) => Boolean(remote)).slice(0, 20);
325
- return remotes.length ? remotes.join(",") : void 0;
326
- }
327
- function sanitizeModuleInfoPath(value) {
328
- if (typeof value !== "string") return;
329
- return clipText(value, 320);
330
- }
331
- function sanitizeModuleInfoGetPublicPath(value) {
332
- if (typeof value !== "string") return;
333
- return clipText(value, 500);
334
- }
335
- function sanitizeModuleInfoRemoteEntry(value) {
336
- if (typeof value !== "string") return;
337
- return clipText(value, 320);
338
- }
339
- function createClippedModuleInfoEntry(rawName, rawValue) {
340
- const name = clipText(rawName, 240);
341
- if (!name) return;
342
- const value = isRecord(rawValue) ? rawValue : {};
343
- return {
344
- name,
345
- publicPath: sanitizeModuleInfoPath(value["publicPath"]),
346
- getPublicPath: sanitizeModuleInfoGetPublicPath(value["getPublicPath"]),
347
- remoteEntry: sanitizeModuleInfoRemoteEntry(value["remoteEntry"]),
348
- globalName: sanitizeText(value["globalName"], 160)
349
- };
350
- }
351
- function normalizeModuleInfoLookupValue(value) {
352
- if (typeof value !== "string" || !value) return;
353
- return (/^https?:\/\//i.test(value) || value.startsWith("/") ? sanitizeUrl(value) : sanitizeText(value, 240))?.toLowerCase();
354
- }
355
- function getModuleInfoLookupValues(report) {
356
- return new Set([
357
- report.requestId?.split("/")[0],
358
- report.remote?.name,
359
- report.remote?.alias,
360
- report.remote?.entry,
361
- report.remote?.entryGlobalName,
362
- report.sanitizedUrl,
363
- report.errorContext?.["remoteName"],
364
- report.errorContext?.["remoteAlias"],
365
- report.errorContext?.["url"],
366
- report.summary.error?.context?.["remoteName"],
367
- report.summary.error?.context?.["remoteAlias"],
368
- report.summary.error?.context?.["url"]
369
- ].map(normalizeModuleInfoLookupValue).filter((value) => Boolean(value)));
370
- }
371
- function matchesModuleInfoLookup(entry, lookupValues) {
372
- if (!lookupValues.size) return false;
373
- return [
374
- entry.name,
375
- entry.publicPath,
376
- entry.getPublicPath,
377
- entry.remoteEntry,
378
- entry.globalName
379
- ].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)));
380
- }
381
- function getModuleInfoCaptureReason(report) {
382
- const text = [
383
- report.errorCode,
384
- report.errorName,
385
- report.errorMessage,
386
- report.summary.error?.errorCode,
387
- report.summary.error?.errorName,
388
- report.summary.error?.errorMessage,
389
- ...report.events.flatMap((event) => [
390
- event.errorCode,
391
- event.errorName,
392
- event.errorMessage,
393
- event.message,
394
- event.lifecycle
395
- ])
396
- ].join("\n");
397
- if (/RUNTIME-007/.test(text)) return "remote-snapshot";
398
- if (/RUNTIME-011/.test(text)) return "remote-entry-missing-in-snapshot";
399
- if (/moduleInfo|module info/i.test(text)) return "module-info";
400
- if (/remote snapshot|global snapshot|snapshot/i.test(text)) return "remote-snapshot";
401
- }
402
- function createModuleInfoSummary(report) {
403
- const reason = getModuleInfoCaptureReason(report);
404
- if (!reason) return;
405
- const moduleInfo = getFederationGlobal()?.moduleInfo;
406
- const rawEntries = isRecord(moduleInfo) ? Object.entries(moduleInfo) : [];
407
- const clippedEntries = rawEntries.map(([name, value]) => createClippedModuleInfoEntry(name, value)).filter((entry) => Boolean(entry));
408
- const lookupValues = getModuleInfoLookupValues(report);
409
- const matchedEntries = clippedEntries.filter((entry) => matchesModuleInfoLookup(entry, lookupValues));
410
- return {
411
- reason,
412
- clipped: true,
413
- totalCount: rawEntries.length,
414
- matchedCount: matchedEntries.length,
415
- entries: matchedEntries.slice(0, MAX_MODULE_INFO_ENTRIES),
416
- availableNames: matchedEntries.length ? void 0 : clippedEntries.map((entry) => entry.name).slice(0, MAX_MODULE_INFO_ENTRIES)
417
- };
418
- }
419
- function getResourceErrorType(event) {
420
- const text = `${event.errorMessage || ""}\n${event.message || ""}`;
421
- if (!event.errorCode && !text) return;
422
- if (/ScriptExecutionError/i.test(text)) return "script-execution";
423
- if (/timeout|timed out/i.test(text)) return "timeout";
424
- if (/ScriptNetworkError|NetworkError|Failed to fetch|Request failed|ERR_|404|CORS/i.test(text)) return "network";
425
- return event.errorCode === "RUNTIME-008" ? "unknown" : void 0;
426
- }
427
- function getOwnerHint(event) {
428
- const resourceErrorType = getResourceErrorType(event);
429
- switch (event.errorCode) {
430
- case "RUNTIME-001":
431
- case "RUNTIME-002":
432
- case "RUNTIME-011":
433
- case "RUNTIME-013":
434
- case "RUNTIME-014":
435
- case "RUNTIME-015": return "remote";
436
- case "RUNTIME-003":
437
- case "RUNTIME-004":
438
- case "RUNTIME-007": return "host";
439
- case "RUNTIME-005":
440
- case "RUNTIME-006":
441
- case "RUNTIME-012": return "shared";
442
- case "RUNTIME-008": return resourceErrorType === "network" || resourceErrorType === "timeout" ? "network" : "remote";
443
- default:
444
- if (event.shared) return "shared";
445
- if (event.remote) return "remote";
446
- if (event.phase === "manifest" || event.phase === "matchRemote") return "host";
447
- return event.errorCode ? "runtime" : void 0;
448
- }
449
- }
450
- function getRetryable(event) {
451
- const resourceErrorType = getResourceErrorType(event);
452
- if (event.errorCode === "RUNTIME-008") return resourceErrorType === "network" || resourceErrorType === "timeout";
453
- if (event.errorCode === "RUNTIME-003") {
454
- const text = `${event.errorMessage || ""}\n${event.message || ""}`;
455
- return /NetworkError|Failed to fetch|Request failed|timeout|timed out/i.test(text);
456
- }
457
- if (event.errorCode && [
458
- "RUNTIME-001",
459
- "RUNTIME-002",
460
- "RUNTIME-004",
461
- "RUNTIME-005",
462
- "RUNTIME-006",
463
- "RUNTIME-011",
464
- "RUNTIME-012",
465
- "RUNTIME-013",
466
- "RUNTIME-014",
467
- "RUNTIME-015"
468
- ].includes(event.errorCode)) return false;
469
- }
470
- function createErrorContext(event, inputContext) {
471
- const context = { ...inputContext };
472
- if (event.lifecycle) context.lifecycle = event.lifecycle;
473
- if (event.requestId) context.requestId = event.requestId;
474
- if (event.remote?.name) context.remoteName = event.remote.name;
475
- if (event.remote?.alias) context.remoteAlias = event.remote.alias;
476
- if (event.remote?.type) context.remoteType = event.remote.type;
477
- if (event.remote?.entryGlobalName) context.entryGlobalName = event.remote.entryGlobalName;
478
- if (event.sanitizedUrl) context.url = event.sanitizedUrl;
479
- if (event.expose) context.expose = event.expose;
480
- if (event.shared?.name) context.shareName = event.shared.name;
481
- if (event.shared?.requiredVersion) context.requiredVersion = event.shared.requiredVersion;
482
- if (event.shared?.selectedVersion) context.selectedVersion = event.shared.selectedVersion;
483
- if (event.shared?.provider) context.provider = event.shared.provider;
484
- const resourceErrorType = getResourceErrorType(event);
485
- if (resourceErrorType) context.resourceErrorType = resourceErrorType;
486
- return clipObservabilityMetadata(context);
487
- }
488
- function ObservabilityPlugin(options = {}) {
489
- const level = options.level || "summary";
490
- const configuredMaxEvents = normalizeMaxEvents(options.maxEvents, DEFAULT_MAX_EVENTS);
491
- const events = [];
492
- const reports = /* @__PURE__ */ new Map();
493
- const traceByRequest = /* @__PURE__ */ new Map();
494
- const traceByRemote = /* @__PURE__ */ new Map();
495
- const phaseStartTimes = /* @__PURE__ */ new Map();
496
- const seenManifestUrls = /* @__PURE__ */ new Set();
497
- const seenRemoteEntryKeys = /* @__PURE__ */ new Set();
498
- const consoleReportedTraceIds = /* @__PURE__ */ new Set();
499
- let latestTraceId;
500
- let runtimeObservabilityEnabled = false;
501
- let effectiveMaxEvents = configuredMaxEvents;
502
- let browserGlobalScope;
503
- let lastRuntimeOrigin;
504
- const isEnabled = () => {
505
- if (options.enabled === false) return false;
506
- runtimeObservabilityEnabled = true;
507
- return true;
508
- };
509
- const resolveTraceId = (event) => {
510
- const sanitizedRequestId = sanitizeRequestId(event.requestId);
511
- if (event.traceId && reports.has(event.traceId)) return event.traceId;
512
- if (event.status === "start" && event.phase === "loadRemote") {
513
- const traceId = event.traceId || createTraceId(event);
514
- if (sanitizedRequestId) traceByRequest.set(sanitizedRequestId, traceId);
515
- if (event.remote?.name) traceByRemote.set(event.remote.name, traceId);
516
- return traceId;
517
- }
518
- if (sanitizedRequestId) {
519
- const traceId = traceByRequest.get(sanitizedRequestId);
520
- if (traceId) return traceId;
521
- }
522
- if (event.remote?.name) {
523
- const traceId = traceByRemote.get(event.remote.name);
524
- if (traceId) return traceId;
525
- }
526
- return event.traceId || createTraceId(event);
527
- };
528
- const normalizeEvent = (event, traceId, origin) => {
529
- const errorInfo = getErrorInfo(event.error, options.stackTrace);
530
- const sanitizedRemote = sanitizeRemote(event.remote);
531
- const sanitizedShared = sanitizeShared(event.shared);
532
- const hostName = sanitizeText(event.hostName, 120) || sanitizeText(origin?.options?.name, 120);
533
- const message = getRawText(event.message) || errorInfo.errorMessage;
534
- const normalizedEvent = {
535
- traceId,
536
- timestamp: event.timestamp || Date.now(),
537
- phase: sanitizeText(event.phase, 120) || "runtime",
538
- status: event.status,
539
- requestId: sanitizeRequestId(event.requestId),
540
- hostName,
541
- remote: sanitizedRemote,
542
- shared: sanitizedShared,
543
- expose: sanitizeText(event.expose, 240),
544
- sanitizedUrl: clipText(event.url || event.remote?.entry, 320),
545
- message,
546
- errorCode: errorInfo.errorCode,
547
- errorName: errorInfo.errorName,
548
- errorMessage: errorInfo.errorMessage,
549
- errorStack: errorInfo.errorStack,
550
- duration: typeof event.duration === "number" && Number.isFinite(event.duration) ? Math.max(0, event.duration) : void 0,
551
- lifecycle: sanitizeText(event.lifecycle, 120),
552
- eventName: sanitizeText(event.eventName, 160),
553
- source: normalizeEventSource(event.source),
554
- recovered: event.recovered === true || void 0,
555
- cached: event.cached === true || void 0,
556
- componentName: sanitizeText(event.componentName, 160),
557
- metadata: clipObservabilityMetadata(event.metadata)
558
- };
559
- if (normalizedEvent.status === "error" || event.error) {
560
- normalizedEvent.ownerHint = getOwnerHint(normalizedEvent);
561
- normalizedEvent.retryable = getRetryable(normalizedEvent);
562
- normalizedEvent.errorContext = createErrorContext(normalizedEvent, event.errorContext);
563
- }
564
- return normalizedEvent;
565
- };
566
- const applyPhaseDuration = (event) => {
567
- const key = getPhaseDurationKey(event);
568
- if (event.status === "start") {
569
- phaseStartTimes.set(key, event.timestamp);
570
- return;
571
- }
572
- if (event.duration !== void 0) return;
573
- const startedAt = phaseStartTimes.get(key);
574
- if (startedAt === void 0) return;
575
- event.duration = Math.max(0, event.timestamp - startedAt);
576
- phaseStartTimes.delete(key);
577
- };
578
- const updateTraceMaps = (event) => {
579
- if (event.requestId) traceByRequest.set(event.requestId, event.traceId);
580
- if (event.remote?.name) traceByRemote.set(event.remote.name, event.traceId);
581
- };
582
- const trimEvents = (report) => {
583
- while (events.length > effectiveMaxEvents) events.shift();
584
- while (report.events.length > effectiveMaxEvents) report.events.shift();
585
- };
586
- const getEventOutcome = (event) => {
587
- if (event.status === "success") return "success";
588
- if (event.status === "error") return "error";
589
- if (event.status === "complete") {
590
- if (event.recovered) return "recovered";
591
- if (event.errorName || event.errorMessage) return "error";
592
- }
593
- };
594
- const isLoadRemoteCompleteEvent = (event) => event.phase === "loadRemote" && event.status === "complete";
595
- const isRuntimeLoadedEvent = (event) => event.phase === "loadRemote" && (event.status === "success" || event.status === "complete" && event.recovered);
596
- const isComponentLoadedEvent = (event) => event.status === "success" && (event.eventName === COMPONENT_BUSINESS_LOADED_EVENT || event.phase === "component" && event.message === COMPONENT_BUSINESS_LOADED_EVENT);
597
- const shouldReplaceFailedPhase = (report, event) => {
598
- if (isLoadRemoteCompleteEvent(event) && report.failedPhase) return false;
599
- if (!report.failedPhase) return true;
600
- return report.failedPhase === "loadRemote" && event.phase !== "loadRemote";
601
- };
602
- const createEmptyPhaseCollection = () => ({
603
- phases: {},
604
- flags: {
605
- cached: false,
606
- retried: false,
607
- fallback: false,
608
- recovered: false
609
- }
610
- });
611
- const createPhaseCollection = (eventsForReport) => {
612
- const collection = createEmptyPhaseCollection();
613
- eventsForReport.forEach((event) => {
614
- const phase = event.phase;
615
- const phaseSummary = collection.phases[phase] || { status: event.status };
616
- if (event.status !== "start") phaseSummary.status = event.status;
617
- if (event.duration !== void 0) phaseSummary.duration = event.duration;
618
- if (event.cached) {
619
- phaseSummary.cached = true;
620
- collection.flags.cached = true;
621
- }
622
- if (event.recovered) {
623
- phaseSummary.recovered = true;
624
- collection.flags.recovered = true;
625
- }
626
- if (event.lifecycle) phaseSummary.lifecycle = event.lifecycle;
627
- collection.phases[phase] = phaseSummary;
628
- if (event.phase === "remoteEntry" && event.recovered) collection.flags.retried = true;
629
- if (event.phase === "loadRemote" && event.status === "complete" && event.recovered) collection.flags.fallback = true;
630
- if (event.shared?.selectedVersion || event.shared?.provider) collection.shared = {
631
- name: event.shared.name,
632
- provider: event.shared.provider,
633
- selectedVersion: event.shared.selectedVersion,
634
- shareScope: event.shared.shareScope ? [...event.shared.shareScope] : void 0
635
- };
636
- });
637
- return collection;
638
- };
639
- const createErrorSummary = (eventsForReport, failedPhase) => {
640
- 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);
641
- if (!errorEvent) return;
642
- return {
643
- errorCode: errorEvent.errorCode,
644
- errorName: errorEvent.errorName,
645
- errorMessage: errorEvent.errorMessage,
646
- failedPhase: failedPhase || errorEvent.phase,
647
- lifecycle: errorEvent.lifecycle,
648
- ownerHint: errorEvent.ownerHint,
649
- retryable: errorEvent.retryable,
650
- context: errorEvent.errorContext ? { ...errorEvent.errorContext } : void 0
651
- };
652
- };
653
- const createReportSummary = (report) => {
654
- const loadCompleted = report.events.some(isLoadRemoteCompleteEvent);
655
- const runtimeLoaded = report.events.some(isRuntimeLoadedEvent);
656
- const recovered = report.events.some((item) => item.recovered);
657
- const componentLoaded = report.events.some(isComponentLoadedEvent);
658
- const lastEvent = report.events[report.events.length - 1];
659
- let outcome = "pending";
660
- if (componentLoaded) outcome = "component-loaded";
661
- else if (recovered && runtimeLoaded) outcome = "recovered";
662
- else if (report.status === "error") outcome = "failed";
663
- else if (runtimeLoaded) outcome = "runtime-loaded";
664
- const phaseCollection = createPhaseCollection(report.events);
665
- return {
666
- eventCount: report.events.length,
667
- recovered,
668
- loadCompleted,
669
- runtimeLoaded,
670
- componentLoaded,
671
- outcome,
672
- lastPhase: lastEvent?.phase,
673
- phases: phaseCollection.phases,
674
- shared: phaseCollection.shared,
675
- flags: phaseCollection.flags,
676
- error: createErrorSummary(report.events, report.failedPhase)
677
- };
678
- };
679
- const refreshModuleInfoSummary = (report) => {
680
- const moduleInfo = createModuleInfoSummary(report);
681
- if (moduleInfo) report.moduleInfo = moduleInfo;
682
- };
683
- const getReportContext = (report) => report.summary.error?.context || report.errorContext;
684
- const getContextText = (context, key) => {
685
- const value = context?.[key];
686
- return typeof value === "string" && value ? value : void 0;
687
- };
688
- const getDiagnosisOwnerHint = (report) => report.summary.error?.ownerHint || report.ownerHint || (report.shared ? "shared" : report.remote ? "remote" : "unknown");
689
- const getDiagnosisResourceErrorType = (report) => getContextText(getReportContext(report), "resourceErrorType") || getResourceErrorType({
690
- errorCode: report.errorCode,
691
- errorMessage: report.errorMessage,
692
- message: report.events.at(-1)?.message,
693
- lifecycle: report.summary.error?.lifecycle
694
- });
695
- const getDiagnosisDocLink = (report) => {
696
- const matched = [
697
- report.errorMessage,
698
- report.errorStack,
699
- ...report.events.flatMap((event) => [
700
- event.errorMessage,
701
- event.errorStack,
702
- event.message
703
- ])
704
- ].filter((item) => Boolean(item)).join("\n").match(DIAGNOSTIC_DOC_LINK_PATTERN)?.[0];
705
- const docLink = sanitizeText(matched, 240);
706
- if (docLink) return docLink;
707
- return report.errorCode?.startsWith("RUNTIME-") ? RUNTIME_DOC_LINK : void 0;
708
- };
709
- const getDiagnosisTitle = (report) => {
710
- if (report.status !== "error") {
711
- if (report.summary.componentLoaded) return "Business component loaded";
712
- if (report.summary.runtimeLoaded) return "Remote loaded successfully";
713
- return "Remote loading is pending";
714
- }
715
- switch (report.errorCode) {
716
- case "RUNTIME-001": return "Remote entry global was not registered";
717
- case "RUNTIME-003": return "Manifest could not be loaded";
718
- case "RUNTIME-004": return "Remote was not found in host remotes";
719
- case "RUNTIME-007": return "Deployment moduleInfo did not match the requested remote";
720
- case "RUNTIME-013": return "Manifest is not a valid Module Federation manifest";
721
- case "RUNTIME-014": return "Requested expose was not found in the remote";
722
- case "RUNTIME-015": return "Remote container initialization failed";
723
- case "RUNTIME-005":
724
- case "RUNTIME-006": return "Shared dependency could not be resolved";
725
- case "RUNTIME-008": {
726
- const resourceErrorType = getDiagnosisResourceErrorType(report);
727
- if (resourceErrorType === "network") return "Remote entry failed because of a network error";
728
- if (resourceErrorType === "timeout") return "Remote entry request timed out";
729
- if (resourceErrorType === "script-execution") return "Remote entry loaded but failed during execution";
730
- return "Remote entry resource could not be loaded";
731
- }
732
- default:
733
- if (report.failedPhase === "shared" || report.shared) return "Shared dependency could not be resolved";
734
- return report.failedPhase ? `Module Federation failed at ${report.failedPhase}` : "Module Federation loading failed";
735
- }
736
- };
737
- const getCompletedPhases = (report) => Array.from(new Set(report.events.filter((event) => event.status === "success" || event.status === "complete").map((event) => event.phase)));
738
- const getPendingPhases = (report) => {
739
- const started = /* @__PURE__ */ new Set();
740
- const ended = /* @__PURE__ */ new Set();
741
- report.events.forEach((event) => {
742
- if (event.status === "start") {
743
- started.add(event.phase);
744
- return;
745
- }
746
- ended.add(event.phase);
747
- });
748
- return Array.from(started).filter((phase) => !ended.has(phase));
749
- };
750
- const createDiagnosisFacts = (report, ownerHint) => {
751
- const context = getReportContext(report);
752
- const facts = {};
753
- const addFact = (key, value) => {
754
- if (value === void 0 || value === null || value === "") return;
755
- facts[key] = Array.isArray(value) ? value.join(",") : value;
756
- };
757
- addFact("traceId", report.traceId);
758
- addFact("status", report.status);
759
- addFact("outcome", report.summary.outcome);
760
- addFact("errorCode", report.errorCode || report.summary.error?.errorCode);
761
- addFact("failedPhase", report.failedPhase || report.summary.error?.failedPhase);
762
- addFact("lifecycle", report.summary.error?.lifecycle);
763
- addFact("ownerHint", ownerHint);
764
- addFact("retryable", report.retryable ?? report.summary.error?.retryable);
765
- addFact("requestId", report.requestId);
766
- addFact("hostName", report.hostName);
767
- addFact("remoteName", report.remote?.name);
768
- addFact("remoteAlias", report.remote?.alias);
769
- addFact("remoteEntry", report.remote?.entry);
770
- addFact("entryGlobalName", report.remote?.entryGlobalName);
771
- addFact("remoteType", report.remote?.type);
772
- addFact("url", report.sanitizedUrl || getContextText(context, "url"));
773
- addFact("expose", report.expose);
774
- addFact("hostRemotes", getContextText(context, "hostRemotes"));
775
- addFact("resourceErrorType", getDiagnosisResourceErrorType(report));
776
- addFact("shareName", report.shared?.name);
777
- addFact("shareScope", report.shared?.shareScope);
778
- addFact("requiredVersion", report.shared?.requiredVersion);
779
- addFact("selectedVersion", report.shared?.selectedVersion);
780
- addFact("availableVersions", report.shared?.availableVersions);
781
- addFact("provider", report.shared?.provider);
782
- addFact("sharedFrom", report.shared?.from);
783
- addFact("singleton", report.shared?.singleton);
784
- addFact("strictVersion", report.shared?.strictVersion);
785
- addFact("eager", report.shared?.eager);
786
- addFact("sharedReason", report.shared?.reason);
787
- addFact("componentName", report.events.find(isComponentLoadedEvent)?.componentName);
788
- addFact("moduleInfoReason", report.moduleInfo?.reason);
789
- addFact("moduleInfoTotalCount", report.moduleInfo?.totalCount);
790
- addFact("moduleInfoMatchedCount", report.moduleInfo?.matchedCount);
791
- addFact("moduleInfoNames", report.moduleInfo?.entries.length ? report.moduleInfo.entries.map((entry) => entry.name) : report.moduleInfo?.availableNames);
792
- addFact("cached", report.summary.flags.cached);
793
- addFact("retried", report.summary.flags.retried);
794
- addFact("fallback", report.summary.flags.fallback);
795
- addFact("recovered", report.summary.recovered);
796
- addFact("loadCompleted", report.summary.loadCompleted);
797
- addFact("runtimeLoaded", report.summary.runtimeLoaded);
798
- addFact("componentLoaded", report.summary.componentLoaded);
799
- return clipMetadata(facts, MAX_FACT_KEYS) || {};
800
- };
801
- const createDiagnosisWarnings = (report) => {
802
- const warnings = [];
803
- if (report.status === "error" && !report.errorCode) warnings.push("No known Module Federation error code was captured");
804
- if (report.summary.flags.retried) warnings.push("Remote entry loading recovered after retry");
805
- if (report.summary.flags.fallback) warnings.push("Remote loading completed through fallback recovery");
806
- if (report.summary.runtimeLoaded && !report.summary.componentLoaded) warnings.push("Business component readiness signal was not recorded");
807
- if (report.moduleInfo && report.moduleInfo.matchedCount === 0) warnings.push("No matching clipped moduleInfo entry was found for the failed remote");
808
- return warnings;
809
- };
810
- const createDiagnosisActions = (report, ownerHint) => {
811
- const actions = [];
812
- const pushAction = (id, title, hint = ownerHint, detail) => {
813
- actions.push({
814
- id,
815
- ownerHint: hint,
816
- title,
817
- detail
818
- });
819
- };
820
- if (report.status !== "error" && !report.summary.error) return actions;
821
- switch (report.errorCode) {
822
- case "RUNTIME-001":
823
- pushAction("check-remote-global", "Check the remote global name against the remoteEntry build output", "remote");
824
- pushAction("check-remote-entry", "Check that remoteEntry registers the expected container", "remote");
825
- break;
826
- case "RUNTIME-003":
827
- pushAction("check-manifest-url", "Check the manifest URL and manifest JSON response", "host");
828
- pushAction("check-network", "Check network availability, CORS, and timeout for the manifest", "network");
829
- break;
830
- case "RUNTIME-013":
831
- pushAction("check-manifest-url", "Check that the manifest response is valid Module Federation JSON", "remote");
832
- break;
833
- case "RUNTIME-004":
834
- pushAction("check-host-remotes", "Check that the requested remote exists in host remotes", "host");
835
- break;
836
- case "RUNTIME-007":
837
- pushAction("check-module-info", "Check deployment-provided __FEDERATION__.moduleInfo for the requested remote", "host");
838
- pushAction("check-host-remotes", "Check that the runtime remote name or alias matches moduleInfo", "host");
839
- break;
840
- case "RUNTIME-014":
841
- pushAction("check-expose", "Check that the requested expose exists in the remote build output", "remote");
842
- break;
843
- case "RUNTIME-015":
844
- pushAction("check-remote-entry", "Check the error thrown during remoteEntry init", "remote");
845
- pushAction("check-shared-provider", "Check share scope initialization data passed to the remote", "shared");
846
- break;
847
- case "RUNTIME-005":
848
- case "RUNTIME-006":
849
- pushAction("check-shared-provider", "Check that a compatible shared provider is available", "shared");
850
- pushAction("check-shared-version", "Compare requested shared version with available versions", "shared");
851
- 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");
852
- break;
853
- case "RUNTIME-008": {
854
- const resourceErrorType = getDiagnosisResourceErrorType(report);
855
- if (resourceErrorType === "network" || resourceErrorType === "timeout") pushAction("check-network", "Check remoteEntry URL, CORS, status code, and timeout", "network");
856
- 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");
857
- break;
858
- }
859
- default:
860
- if (report.failedPhase === "manifest") pushAction("check-manifest-url", "Check manifest loading and parsing", "host");
861
- if (report.failedPhase === "remoteEntry") pushAction("check-remote-entry", "Check remoteEntry loading and initialization", "remote");
862
- if (report.failedPhase === "expose") pushAction("check-expose", "Check that the requested expose exists in the remote", "remote");
863
- if (report.failedPhase === "shared") {
864
- pushAction("check-shared-provider", "Check shared dependency resolution", "shared");
865
- 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");
866
- 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");
867
- }
868
- }
869
- 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");
870
- if (!actions.length) pushAction("inspect-runtime-events", "Inspect the ordered observability events for the failed phase", ownerHint);
871
- return actions;
872
- };
873
- const createFactReport = (report) => {
874
- const ownerHint = getDiagnosisOwnerHint(report);
875
- const warnings = createDiagnosisWarnings(report);
876
- return {
877
- title: getDiagnosisTitle(report),
878
- outcome: report.summary.outcome,
879
- status: report.status,
880
- ownerHint,
881
- failedPhase: report.failedPhase || report.summary.error?.failedPhase,
882
- errorCode: report.errorCode || report.summary.error?.errorCode,
883
- errorName: report.errorName || report.summary.error?.errorName,
884
- errorMessage: report.errorMessage || report.summary.error?.errorMessage,
885
- docLink: getDiagnosisDocLink(report),
886
- facts: createDiagnosisFacts(report, ownerHint),
887
- completedPhases: getCompletedPhases(report),
888
- pendingPhases: getPendingPhases(report),
889
- warnings: warnings.length ? warnings : void 0,
890
- actions: createDiagnosisActions(report, ownerHint)
891
- };
892
- };
893
- const refreshReportDerivedFields = (report) => {
894
- report.summary = createReportSummary(report);
895
- refreshModuleInfoSummary(report);
896
- report.diagnosis = createFactReport(report);
897
- };
898
- const updateReport = (event) => {
899
- let report = reports.get(event.traceId);
900
- if (!report) {
901
- report = {
902
- traceId: event.traceId,
903
- status: event.status === "error" ? "error" : "pending",
904
- requestId: event.requestId,
905
- hostName: event.hostName,
906
- remote: event.remote ? { ...event.remote } : void 0,
907
- shared: event.shared ? copyEvent(event).shared : void 0,
908
- expose: event.expose,
909
- sanitizedUrl: event.sanitizedUrl,
910
- startedAt: event.timestamp,
911
- updatedAt: event.timestamp,
912
- duration: 0,
913
- failedPhase: event.status === "error" ? event.phase : void 0,
914
- errorCode: event.errorCode,
915
- errorName: event.errorName,
916
- errorMessage: event.errorMessage,
917
- errorStack: event.errorStack,
918
- ownerHint: event.ownerHint,
919
- retryable: event.retryable,
920
- errorContext: event.errorContext ? { ...event.errorContext } : void 0,
921
- events: [],
922
- summary: {
923
- eventCount: 0,
924
- recovered: false,
925
- loadCompleted: false,
926
- runtimeLoaded: false,
927
- componentLoaded: false,
928
- outcome: "pending",
929
- lastPhase: void 0,
930
- phases: {},
931
- shared: void 0,
932
- flags: createEmptyPhaseCollection().flags,
933
- error: void 0
934
- }
935
- };
936
- reports.set(event.traceId, report);
937
- }
938
- if (event.requestId) report.requestId = event.requestId;
939
- if (event.hostName) report.hostName = event.hostName;
940
- if (event.remote) report.remote = { ...event.remote };
941
- if (event.shared) report.shared = copyEvent(event).shared;
942
- if (event.expose) report.expose = event.expose;
943
- if (event.sanitizedUrl) report.sanitizedUrl = event.sanitizedUrl;
944
- if (event.errorStack) report.errorStack = event.errorStack;
945
- if (event.errorCode) report.errorCode = event.errorCode;
946
- if (event.errorName) report.errorName = event.errorName;
947
- if (event.errorMessage) report.errorMessage = event.errorMessage;
948
- if (event.ownerHint) report.ownerHint = event.ownerHint;
949
- if (event.retryable !== void 0) report.retryable = event.retryable;
950
- if (event.errorContext) report.errorContext = { ...event.errorContext };
951
- report.events.push(event);
952
- report.updatedAt = event.timestamp;
953
- report.duration = Math.max(0, report.updatedAt - report.startedAt);
954
- const eventOutcome = getEventOutcome(event);
955
- if (eventOutcome === "error") {
956
- report.status = "error";
957
- if (shouldReplaceFailedPhase(report, event)) report.failedPhase = event.phase;
958
- } else if (eventOutcome === "recovered") report.status = "success";
959
- else if (eventOutcome === "success" && report.status !== "error") report.status = "success";
960
- refreshReportDerivedFields(report);
961
- latestTraceId = event.traceId;
962
- trimEvents(report);
963
- return report;
964
- };
965
- const notifyEvent = (event, report, origin) => {
966
- try {
967
- options.onEvent?.(copyEvent(event), copyReport(report), { origin });
968
- } catch {}
969
- };
970
- const notifyReport = (report, origin) => {
971
- if (report.events[report.events.length - 1]?.status === "start") return;
972
- try {
973
- options.onReport?.(copyReport(report), { origin });
974
- } catch {}
975
- };
976
- const notifyRawError = (errorValue, event, report, origin) => {
977
- if (!errorValue || !options.onRawError) return;
978
- try {
979
- options.onRawError(errorValue, {
980
- origin,
981
- event: copyEvent(event),
982
- report: copyReport(report)
983
- });
984
- } catch {}
985
- };
986
- const getEventsSnapshot = () => events.map(copyEvent);
987
- const getTraceIdsSnapshot = () => Array.from(reports.keys());
988
- const getReportTimeline = () => Array.from(reports.values()).sort((left, right) => {
989
- if (right.updatedAt !== left.updatedAt) return right.updatedAt - left.updatedAt;
990
- return right.startedAt - left.startedAt;
991
- });
992
- const matchesReportValue = (value, expected) => {
993
- if (!value || !expected) return false;
994
- const normalizedValue = value.toLowerCase();
995
- const normalizedExpected = expected.toLowerCase();
996
- return normalizedValue === normalizedExpected || normalizedValue.includes(normalizedExpected);
997
- };
998
- const matchesReportQuery = (report, query) => {
999
- if (query.traceId && report.traceId !== query.traceId) return false;
1000
- if (query.status && report.status !== query.status) return false;
1001
- if (query.outcome && report.summary.outcome !== query.outcome) return false;
1002
- if (query.remote && ![
1003
- report.remote?.name,
1004
- report.remote?.alias,
1005
- report.remote?.entry,
1006
- report.requestId,
1007
- report.sanitizedUrl
1008
- ].some((value) => matchesReportValue(value, query.remote))) return false;
1009
- if (query.expose && ![report.expose, report.requestId].some((value) => matchesReportValue(value, query.expose))) return false;
1010
- if (query.shared && ![report.shared?.name].some((value) => matchesReportValue(value, query.shared))) return false;
1011
- return true;
1012
- };
1013
- const getReportsSnapshot = (options = {}) => {
1014
- const limit = normalizeQueryLimit(options.limit);
1015
- const timeline = getReportTimeline();
1016
- return (limit ? timeline.slice(0, limit) : timeline).map(copyReport);
1017
- };
1018
- const findReportsSnapshot = (query = {}) => {
1019
- const limit = normalizeQueryLimit(query.limit);
1020
- const matchedReports = getReportTimeline().filter((report) => matchesReportQuery(report, query));
1021
- return (limit ? matchedReports.slice(0, limit) : matchedReports).map(copyReport);
1022
- };
1023
- const getLatestReportSnapshot = () => {
1024
- if (!latestTraceId) return;
1025
- const report = reports.get(latestTraceId);
1026
- return report ? copyReport(report) : void 0;
1027
- };
1028
- const getReportSnapshot = (traceId) => {
1029
- const report = reports.get(traceId);
1030
- return report ? copyReport(report) : void 0;
1031
- };
1032
- const exportReportSnapshot = (traceId) => traceId ? getReportSnapshot(traceId) : getLatestReportSnapshot();
1033
- const createBrowserReader = () => ({
1034
- getEvents: getEventsSnapshot,
1035
- getTraceIds: getTraceIdsSnapshot,
1036
- getReports: getReportsSnapshot,
1037
- findReports: findReportsSnapshot,
1038
- getLatestReport: getLatestReportSnapshot,
1039
- getReport: getReportSnapshot,
1040
- exportReport: exportReportSnapshot
1041
- });
1042
- const shouldExposeBrowserGlobal = () => options.browser?.enabled === true;
1043
- const ensureBrowserGlobal = (origin) => {
1044
- if (!shouldExposeBrowserGlobal()) return;
1045
- const federationGlobal = getFederationGlobal();
1046
- if (!federationGlobal) return;
1047
- const scope = normalizeScope(options.browser?.scope || origin?.options?.name || "default");
1048
- const reader = createBrowserReader();
1049
- const readers = federationGlobal.__OBSERVABILITY__ || {};
1050
- federationGlobal.__OBSERVABILITY__ = readers;
1051
- browserGlobalScope = scope;
1052
- try {
1053
- Object.defineProperty(readers, scope, {
1054
- value: reader,
1055
- configurable: true,
1056
- enumerable: true
1057
- });
1058
- } catch {
1059
- readers[scope] = reader;
1060
- }
1061
- };
1062
- const shouldUseConsole = () => options.console !== false;
1063
- const shouldUseMinimalBrowserConsole = () => options.browser?.mode === "production";
1064
- const getBrowserReadCommand = (traceId) => {
1065
- if (!browserGlobalScope) return;
1066
- return `window.__FEDERATION__.__OBSERVABILITY__[${JSON.stringify(browserGlobalScope)}].getReport(${JSON.stringify(traceId)})`;
1067
- };
1068
- const emitConsoleHint = (event, report, rawError) => {
1069
- if (getEventOutcome(event) !== "error" || !shouldUseConsole() || consoleReportedTraceIds.has(report.traceId)) return;
1070
- consoleReportedTraceIds.add(report.traceId);
1071
- if (shouldUseMinimalBrowserConsole()) {
1072
- const lines = ["[Module Federation] Observability report generated", `traceId: ${report.traceId}`];
1073
- if (report.errorCode) lines.push(`errorCode: ${report.errorCode}`);
1074
- try {
1075
- console.error(lines.join("\n"));
1076
- } catch {}
1077
- return;
1078
- }
1079
- const lines = [
1080
- "[Module Federation] Observability report generated",
1081
- `traceId: ${report.traceId}`,
1082
- `phase: ${report.failedPhase || event.phase}`
1083
- ];
1084
- if (report.requestId) lines.push(`requestId: ${report.requestId}`);
1085
- if (report.errorCode) lines.push(`errorCode: ${report.errorCode}`);
1086
- if (report.shared?.name) lines.push(`shared: ${report.shared.name}`);
1087
- const browserReadCommand = getBrowserReadCommand(report.traceId);
1088
- if (browserReadCommand) lines.push(`read: ${browserReadCommand}`);
1089
- else lines.push(`read: observability.getReport(${JSON.stringify(report.traceId)})`);
1090
- const rawStack = getRawStack(rawError);
1091
- if (options.printRawStack === true && rawStack) lines.push("rawStack:", rawStack);
1092
- try {
1093
- console.error(lines.join("\n"));
1094
- } catch {}
1095
- };
1096
- const prepareOutputChannels = (origin) => {
1097
- browserGlobalScope = void 0;
1098
- ensureBrowserGlobal(origin);
1099
- };
1100
- const prepareRuntimeOrigin = (origin) => {
1101
- if (!isEnabled()) return false;
1102
- lastRuntimeOrigin = origin;
1103
- prepareOutputChannels(origin);
1104
- return true;
1105
- };
1106
- const recordEvent = (input, origin) => {
1107
- const event = normalizeEvent(input, resolveTraceId(input), origin);
1108
- applyPhaseDuration(event);
1109
- updateTraceMaps(event);
1110
- if (!shouldRecordEvent(level, input)) return;
1111
- events.push(event);
1112
- const report = updateReport(event);
1113
- emitConsoleHint(event, report, input.error);
1114
- notifyRawError(input.error, event, report, origin);
1115
- notifyEvent(event, report, origin);
1116
- notifyReport(report, origin);
1117
- return event;
1118
- };
1119
- return {
1120
- plugin: {
1121
- name: "observability-plugin",
1122
- beforeRequest(args) {
1123
- const requestArgs = args;
1124
- if (!prepareRuntimeOrigin(requestArgs.origin)) return;
1125
- recordEvent({
1126
- phase: "loadRemote",
1127
- status: "start",
1128
- requestId: requestArgs.id,
1129
- lifecycle: "beforeRequest",
1130
- message: "remote:load-start"
1131
- }, requestArgs.origin);
1132
- },
1133
- afterMatchRemote(args) {
1134
- const matchArgs = args;
1135
- if (!prepareRuntimeOrigin(matchArgs.origin)) return;
1136
- const remote = createRemoteInfo(matchArgs.remoteInfo || matchArgs.remote);
1137
- const hostRemotes = getHostRemotesSummary(matchArgs.options);
1138
- recordEvent({
1139
- phase: "matchRemote",
1140
- status: matchArgs.error ? "error" : "success",
1141
- requestId: matchArgs.id,
1142
- lifecycle: "afterMatchRemote",
1143
- expose: matchArgs.expose,
1144
- remote,
1145
- message: matchArgs.error ? "remote:match-failed" : "remote:matched",
1146
- error: matchArgs.error,
1147
- errorContext: hostRemotes ? { hostRemotes } : void 0
1148
- }, matchArgs.origin);
1149
- },
1150
- beforeLoadRemoteSnapshot(args) {
1151
- const snapshotArgs = args;
1152
- if (!prepareRuntimeOrigin(snapshotArgs.origin)) return;
1153
- const remote = createRemoteInfo(snapshotArgs.moduleInfo);
1154
- if (!isManifestUrl(remote?.entry)) return;
1155
- recordEvent({
1156
- phase: "manifest",
1157
- status: "start",
1158
- requestId: remote?.entry,
1159
- remote,
1160
- url: remote?.entry,
1161
- lifecycle: "beforeLoadRemoteSnapshot",
1162
- message: "manifest:load-start"
1163
- }, snapshotArgs.origin);
1164
- },
1165
- loadRemoteSnapshot(args) {
1166
- if (options.enabled === false) return;
1167
- },
1168
- afterResolve(args) {
1169
- const resolveArgs = args;
1170
- if (!prepareRuntimeOrigin(resolveArgs.origin)) return;
1171
- const remote = createRemoteInfo(resolveArgs.remoteInfo || resolveArgs.remote);
1172
- if (!isManifestUrl(remote?.entry)) return;
1173
- const manifestUrl = sanitizeUrl(remote?.entry);
1174
- const cached = resolveArgs.cached === true || Boolean(manifestUrl && seenManifestUrls.has(manifestUrl));
1175
- recordEvent({
1176
- phase: "manifest",
1177
- status: "success",
1178
- requestId: remote?.entry,
1179
- expose: resolveArgs.expose,
1180
- remote,
1181
- url: remote?.entry,
1182
- lifecycle: "afterResolve",
1183
- message: "manifest:resolved",
1184
- cached
1185
- }, resolveArgs.origin);
1186
- if (manifestUrl) seenManifestUrls.add(manifestUrl);
1187
- },
1188
- onLoad(args) {
1189
- const loadArgs = args;
1190
- if (!prepareRuntimeOrigin(loadArgs.origin)) return;
1191
- recordEvent({
1192
- phase: "loadRemote",
1193
- status: "success",
1194
- requestId: loadArgs.id,
1195
- lifecycle: "onLoad",
1196
- expose: loadArgs.expose,
1197
- remote: createRemoteInfo(loadArgs.remote),
1198
- message: "remote:loaded"
1199
- }, loadArgs.origin);
1200
- },
1201
- errorLoadRemote(args) {
1202
- const errorArgs = args;
1203
- if (!prepareRuntimeOrigin(errorArgs.origin) || errorArgs.lifecycle !== "onLoad" && errorArgs.lifecycle !== "beforeRequest" && errorArgs.lifecycle !== "afterResolve") return;
1204
- const isManifestError = errorArgs.lifecycle === "afterResolve";
1205
- recordEvent({
1206
- phase: isManifestError ? "manifest" : "loadRemote",
1207
- status: "error",
1208
- requestId: errorArgs.id,
1209
- lifecycle: errorArgs.lifecycle,
1210
- expose: errorArgs.expose,
1211
- remote: createRemoteInfo(errorArgs.remote),
1212
- url: isManifestError ? errorArgs.id : void 0,
1213
- message: isManifestError ? "manifest:failed" : errorArgs.lifecycle ? `remote:${errorArgs.lifecycle}:failed` : "remote:failed",
1214
- error: errorArgs.error
1215
- }, errorArgs.origin);
1216
- },
1217
- afterLoadRemote(args) {
1218
- const loadArgs = args;
1219
- if (!prepareRuntimeOrigin(loadArgs.origin)) return;
1220
- recordEvent({
1221
- phase: "loadRemote",
1222
- status: "complete",
1223
- requestId: loadArgs.id,
1224
- lifecycle: "afterLoadRemote",
1225
- expose: loadArgs.expose,
1226
- remote: createRemoteInfo(loadArgs.remote),
1227
- message: loadArgs.recovered ? "remote:load-recovered" : loadArgs.error ? "remote:load-failed" : "remote:load-complete",
1228
- error: loadArgs.error,
1229
- recovered: loadArgs.recovered
1230
- }, loadArgs.origin);
1231
- },
1232
- loadEntry(args) {
1233
- const entryArgs = args;
1234
- if (!prepareRuntimeOrigin(entryArgs.origin)) return;
1235
- const remote = createRemoteInfo(entryArgs.remoteInfo);
1236
- recordEvent({
1237
- phase: "remoteEntry",
1238
- status: "start",
1239
- requestId: remote?.name,
1240
- remote,
1241
- url: remote?.entry,
1242
- lifecycle: "loadEntry",
1243
- message: "remoteEntry:load-start"
1244
- }, entryArgs.origin);
1245
- },
1246
- afterLoadEntry(args) {
1247
- const entryArgs = args;
1248
- if (!prepareRuntimeOrigin(entryArgs.origin)) return;
1249
- const remote = createRemoteInfo(entryArgs.remoteInfo);
1250
- const remoteEntryKey = getRemoteEntryKey(sanitizeRemote(remote));
1251
- const cached = entryArgs.cached === true || Boolean(remoteEntryKey && seenRemoteEntryKeys.has(remoteEntryKey));
1252
- recordEvent({
1253
- phase: "remoteEntry",
1254
- status: entryArgs.error ? "error" : "success",
1255
- requestId: remote?.name,
1256
- remote,
1257
- url: remote?.entry,
1258
- lifecycle: "afterLoadEntry",
1259
- message: entryArgs.error ? "remoteEntry:load-failed" : entryArgs.recovered ? "remoteEntry:load-recovered" : "remoteEntry:loaded",
1260
- error: entryArgs.error,
1261
- recovered: entryArgs.recovered,
1262
- cached
1263
- }, entryArgs.origin);
1264
- if (!entryArgs.error && remoteEntryKey) seenRemoteEntryKeys.add(remoteEntryKey);
1265
- },
1266
- beforeInitRemote(args) {
1267
- const initArgs = args;
1268
- if (!prepareRuntimeOrigin(initArgs.origin)) return;
1269
- const remote = createRemoteInfo(initArgs.remoteInfo);
1270
- recordEvent({
1271
- phase: "remoteEntryInit",
1272
- status: "start",
1273
- requestId: initArgs.id || remote?.name,
1274
- remote,
1275
- lifecycle: "beforeInitRemote",
1276
- message: "remoteEntry:init-start"
1277
- }, initArgs.origin);
1278
- },
1279
- afterInitRemote(args) {
1280
- const initArgs = args;
1281
- if (!prepareRuntimeOrigin(initArgs.origin)) return;
1282
- const remote = createRemoteInfo(initArgs.remoteInfo);
1283
- recordEvent({
1284
- phase: "remoteEntryInit",
1285
- status: initArgs.error ? "error" : "success",
1286
- requestId: initArgs.id || remote?.name,
1287
- remote,
1288
- lifecycle: "afterInitRemote",
1289
- message: initArgs.error ? "remoteEntry:init-failed" : initArgs.cached ? "remoteEntry:init-reused" : "remoteEntry:initialized",
1290
- error: initArgs.error,
1291
- cached: initArgs.cached
1292
- }, initArgs.origin);
1293
- },
1294
- beforeGetExpose(args) {
1295
- const exposeArgs = args;
1296
- if (!prepareRuntimeOrigin(exposeArgs.origin)) return;
1297
- recordEvent({
1298
- phase: "expose",
1299
- status: "start",
1300
- requestId: exposeArgs.id,
1301
- expose: exposeArgs.expose,
1302
- remote: createRemoteInfo(exposeArgs.moduleInfo),
1303
- lifecycle: "beforeGetExpose",
1304
- message: "expose:get-start"
1305
- }, exposeArgs.origin);
1306
- },
1307
- afterGetExpose(args) {
1308
- const exposeArgs = args;
1309
- if (!prepareRuntimeOrigin(exposeArgs.origin)) return;
1310
- recordEvent({
1311
- phase: "expose",
1312
- status: exposeArgs.error ? "error" : "success",
1313
- requestId: exposeArgs.id,
1314
- expose: exposeArgs.expose,
1315
- remote: createRemoteInfo(exposeArgs.moduleInfo),
1316
- lifecycle: "afterGetExpose",
1317
- message: exposeArgs.error ? "expose:get-failed" : "expose:resolved",
1318
- error: exposeArgs.error
1319
- }, exposeArgs.origin);
1320
- },
1321
- beforeExecuteFactory(args) {
1322
- const factoryArgs = args;
1323
- if (!prepareRuntimeOrigin(factoryArgs.origin)) return;
1324
- recordEvent({
1325
- phase: "moduleFactory",
1326
- status: "start",
1327
- requestId: factoryArgs.id,
1328
- expose: factoryArgs.expose,
1329
- remote: createRemoteInfo(factoryArgs.moduleInfo),
1330
- lifecycle: "beforeExecuteFactory",
1331
- message: "moduleFactory:execute-start"
1332
- }, factoryArgs.origin);
1333
- },
1334
- afterExecuteFactory(args) {
1335
- const factoryArgs = args;
1336
- if (!prepareRuntimeOrigin(factoryArgs.origin)) return;
1337
- recordEvent({
1338
- phase: "moduleFactory",
1339
- status: factoryArgs.error ? "error" : "success",
1340
- requestId: factoryArgs.id,
1341
- expose: factoryArgs.expose,
1342
- remote: createRemoteInfo(factoryArgs.moduleInfo),
1343
- lifecycle: "afterExecuteFactory",
1344
- message: factoryArgs.error ? "moduleFactory:execute-failed" : "moduleFactory:executed",
1345
- error: factoryArgs.error
1346
- }, factoryArgs.origin);
1347
- },
1348
- beforeLoadShare(args) {
1349
- if (!prepareRuntimeOrigin(args.origin)) return args;
1350
- recordEvent({
1351
- phase: "shared",
1352
- status: "start",
1353
- requestId: `shared:${args.pkgName}`,
1354
- lifecycle: "loadShare",
1355
- shared: createSharedInfo(args),
1356
- message: "shared:load-start"
1357
- }, args.origin);
1358
- return args;
1359
- },
1360
- afterLoadShare(args) {
1361
- if (!prepareRuntimeOrigin(args.origin)) return;
1362
- recordEvent({
1363
- phase: "shared",
1364
- status: "success",
1365
- requestId: `shared:${args.pkgName}`,
1366
- lifecycle: args.lifecycle,
1367
- shared: createSharedInfo(args),
1368
- message: args.lifecycle === "loadShareSync" ? "shared:resolved-sync" : "shared:resolved"
1369
- }, args.origin);
1370
- },
1371
- errorLoadShare(args) {
1372
- if (!prepareRuntimeOrigin(args.origin)) return;
1373
- const reason = getSharedErrorReason(args);
1374
- recordEvent({
1375
- phase: "shared",
1376
- status: "error",
1377
- requestId: `shared:${args.pkgName}`,
1378
- lifecycle: args.lifecycle,
1379
- shared: createSharedInfo(args, reason),
1380
- message: reason ? `shared:${reason}` : void 0,
1381
- error: args.error,
1382
- recovered: args.recovered
1383
- }, args.origin);
1384
- }
1385
- },
1386
- getEvents() {
1387
- return getEventsSnapshot();
1388
- },
1389
- getTraceIds() {
1390
- return getTraceIdsSnapshot();
1391
- },
1392
- getReports(options) {
1393
- return getReportsSnapshot(options);
1394
- },
1395
- findReports(query) {
1396
- return findReportsSnapshot(query);
1397
- },
1398
- getLatestReport() {
1399
- return getLatestReportSnapshot();
1400
- },
1401
- getReport(traceId) {
1402
- return getReportSnapshot(traceId);
1403
- },
1404
- exportReport(traceId) {
1405
- return exportReportSnapshot(traceId);
1406
- },
1407
- clear() {
1408
- events.length = 0;
1409
- reports.clear();
1410
- traceByRequest.clear();
1411
- traceByRemote.clear();
1412
- phaseStartTimes.clear();
1413
- seenManifestUrls.clear();
1414
- seenRemoteEntryKeys.clear();
1415
- consoleReportedTraceIds.clear();
1416
- latestTraceId = void 0;
1417
- runtimeObservabilityEnabled = false;
1418
- effectiveMaxEvents = configuredMaxEvents;
1419
- browserGlobalScope = void 0;
1420
- lastRuntimeOrigin = void 0;
1421
- },
1422
- markComponentLoaded(markOptions = {}) {
1423
- if (options.enabled === false || !runtimeObservabilityEnabled) return;
1424
- return recordEvent({
1425
- traceId: markOptions.traceId || (markOptions.requestId ? traceByRequest.get(sanitizeRequestId(markOptions.requestId) || "") : void 0) || latestTraceId || createTraceId({
1426
- phase: "component",
1427
- status: "success",
1428
- requestId: markOptions.requestId
1429
- }),
1430
- phase: "component",
1431
- status: "success",
1432
- requestId: markOptions.requestId,
1433
- componentName: markOptions.componentName,
1434
- metadata: markOptions.metadata,
1435
- eventName: COMPONENT_BUSINESS_LOADED_EVENT,
1436
- message: COMPONENT_BUSINESS_LOADED_EVENT,
1437
- source: "business"
1438
- }, lastRuntimeOrigin);
1439
- }
1440
- };
1441
- }
1442
-
1443
- //#endregion
1444
- exports.ObservabilityPlugin = ObservabilityPlugin;
6
+ exports.ChromeObservabilityPlugin = require_chrome_devtool.ChromeObservabilityPlugin;
7
+ exports.ObservabilityPlugin = require_browser.ObservabilityPlugin;
8
+ exports.createObservability = require_core.createObservability;
9
+ exports.default = require_browser.ObservabilityPlugin;