@module-federation/observability-plugin 0.0.0-alpha.0
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/AI_TROUBLESHOOTING.md +498 -0
- package/README.md +295 -0
- package/dist/AI_TROUBLESHOOTING.md +498 -0
- package/dist/README.md +295 -0
- package/dist/build.d.ts +194 -0
- package/dist/build.js +710 -0
- package/dist/esm/build.js +679 -0
- package/dist/esm/index.js +1442 -0
- package/dist/esm/node.js +156 -0
- package/dist/index.d.ts +269 -0
- package/dist/index.js +1444 -0
- package/dist/node.d.ts +13 -0
- package/dist/node.js +158 -0
- package/package.json +64 -0
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ObservabilityController, ObservabilityPluginOptions } from "./index.js";
|
|
2
|
+
|
|
3
|
+
//#region src/node.d.ts
|
|
4
|
+
interface ObservabilityNodeOptions extends Omit<ObservabilityPluginOptions, 'browser'> {
|
|
5
|
+
fileOutput?: boolean;
|
|
6
|
+
directory?: string;
|
|
7
|
+
latestFile?: string;
|
|
8
|
+
eventsFile?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function getNativeNodeRequire(): ((id: string) => unknown) | undefined;
|
|
11
|
+
declare function ObservabilityPlugin(options?: ObservabilityNodeOptions): ObservabilityController;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ObservabilityNodeOptions, ObservabilityPlugin, getNativeNodeRequire };
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_index = require('./index.js');
|
|
3
|
+
|
|
4
|
+
//#region src/node.ts
|
|
5
|
+
const DEFAULT_NODE_DIRECTORY = ".mf/observability";
|
|
6
|
+
const DEFAULT_LATEST_FILE = "latest.json";
|
|
7
|
+
const DEFAULT_EVENTS_FILE = "events.jsonl";
|
|
8
|
+
let nodeOutputModulesPromise;
|
|
9
|
+
function getNodeProcess() {
|
|
10
|
+
return globalThis.process;
|
|
11
|
+
}
|
|
12
|
+
function isNodeEnvironment() {
|
|
13
|
+
return Boolean(getNodeProcess()?.versions?.node);
|
|
14
|
+
}
|
|
15
|
+
function getNativeNodeRequire() {
|
|
16
|
+
if (typeof __non_webpack_require__ === "function") return __non_webpack_require__;
|
|
17
|
+
const globalRequire = globalThis.__non_webpack_require__;
|
|
18
|
+
if (typeof globalRequire === "function") return globalRequire;
|
|
19
|
+
try {
|
|
20
|
+
return Function("return typeof require === \"function\" ? require : undefined")();
|
|
21
|
+
} catch {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function getRuntimeImport() {
|
|
26
|
+
try {
|
|
27
|
+
return Function("specifier", "return import(specifier)");
|
|
28
|
+
} catch {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function unwrapDefaultExport(moduleValue) {
|
|
33
|
+
return moduleValue.default || moduleValue;
|
|
34
|
+
}
|
|
35
|
+
async function getNodeOutputModules() {
|
|
36
|
+
if (!isNodeEnvironment()) return;
|
|
37
|
+
if (nodeOutputModulesPromise) return nodeOutputModulesPromise;
|
|
38
|
+
nodeOutputModulesPromise = (async () => {
|
|
39
|
+
const nativeRequire = getNativeNodeRequire();
|
|
40
|
+
if (nativeRequire) try {
|
|
41
|
+
return {
|
|
42
|
+
fs: nativeRequire("node:fs"),
|
|
43
|
+
path: nativeRequire("node:path")
|
|
44
|
+
};
|
|
45
|
+
} catch {}
|
|
46
|
+
const runtimeImport = getRuntimeImport();
|
|
47
|
+
if (!runtimeImport) return;
|
|
48
|
+
try {
|
|
49
|
+
const [fsModule, pathModule] = await Promise.all([runtimeImport("node:fs"), runtimeImport("node:path")]);
|
|
50
|
+
return {
|
|
51
|
+
fs: unwrapDefaultExport(fsModule),
|
|
52
|
+
path: unwrapDefaultExport(pathModule)
|
|
53
|
+
};
|
|
54
|
+
} catch {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
})();
|
|
58
|
+
return nodeOutputModulesPromise;
|
|
59
|
+
}
|
|
60
|
+
function getNodeOutputConfig(options) {
|
|
61
|
+
return {
|
|
62
|
+
directory: options.directory || DEFAULT_NODE_DIRECTORY,
|
|
63
|
+
latestFile: options.latestFile || DEFAULT_LATEST_FILE,
|
|
64
|
+
eventsFile: options.eventsFile || DEFAULT_EVENTS_FILE
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function shouldUseNodeOutput(options) {
|
|
68
|
+
return options.enabled !== false && options.fileOutput === true && isNodeEnvironment();
|
|
69
|
+
}
|
|
70
|
+
function shouldUseConsole(options) {
|
|
71
|
+
return options.console !== false;
|
|
72
|
+
}
|
|
73
|
+
function getNodeLatestPathForConsole(options) {
|
|
74
|
+
const config = getNodeOutputConfig(options);
|
|
75
|
+
return `${config.directory}/${config.latestFile}`;
|
|
76
|
+
}
|
|
77
|
+
function getNodeEventsPathForConsole(options) {
|
|
78
|
+
const config = getNodeOutputConfig(options);
|
|
79
|
+
return `${config.directory}/${config.eventsFile}`;
|
|
80
|
+
}
|
|
81
|
+
function isErrorEvent(event) {
|
|
82
|
+
return event.status === "error" || event.status === "complete" && Boolean(event.errorName || event.errorMessage);
|
|
83
|
+
}
|
|
84
|
+
function getRawStack(error) {
|
|
85
|
+
if (error instanceof Error) return error.stack || error.message;
|
|
86
|
+
}
|
|
87
|
+
async function writeNodeOutput(options, event, report) {
|
|
88
|
+
const modules = await getNodeOutputModules();
|
|
89
|
+
if (!modules) return;
|
|
90
|
+
const config = getNodeOutputConfig(options);
|
|
91
|
+
const cwd = getNodeProcess()?.cwd?.() || ".";
|
|
92
|
+
const directory = modules.path.isAbsolute(config.directory) ? config.directory : modules.path.resolve(cwd, config.directory);
|
|
93
|
+
const latestFile = modules.path.join(directory, config.latestFile);
|
|
94
|
+
const eventsFile = modules.path.join(directory, config.eventsFile);
|
|
95
|
+
modules.fs.mkdirSync(directory, { recursive: true });
|
|
96
|
+
modules.fs.writeFileSync(latestFile, `${JSON.stringify(report, null, 2)}\n`, "utf8");
|
|
97
|
+
modules.fs.appendFileSync(eventsFile, `${JSON.stringify(event)}\n`, "utf8");
|
|
98
|
+
}
|
|
99
|
+
function emitNodeConsoleHint(options, event, report, context, reportedTraceIds, rawStack) {
|
|
100
|
+
if (!isErrorEvent(event) || !shouldUseConsole(options) || reportedTraceIds.has(report.traceId)) return;
|
|
101
|
+
reportedTraceIds.add(report.traceId);
|
|
102
|
+
const lines = [
|
|
103
|
+
"[Module Federation] Observability report generated",
|
|
104
|
+
`traceId: ${report.traceId}`,
|
|
105
|
+
`phase: ${report.failedPhase || event.phase}`
|
|
106
|
+
];
|
|
107
|
+
if (report.requestId) lines.push(`requestId: ${report.requestId}`);
|
|
108
|
+
if (report.errorCode) lines.push(`errorCode: ${report.errorCode}`);
|
|
109
|
+
if (report.shared?.name) lines.push(`shared: ${report.shared.name}`);
|
|
110
|
+
if (shouldUseNodeOutput(options)) {
|
|
111
|
+
lines.push(`latest: ${getNodeLatestPathForConsole(options)}`);
|
|
112
|
+
lines.push(`events: ${getNodeEventsPathForConsole(options)}`);
|
|
113
|
+
} else lines.push(`read: observability.getReport(${JSON.stringify(report.traceId)})`);
|
|
114
|
+
if (options.printRawStack === true && rawStack) lines.push("rawStack:", rawStack);
|
|
115
|
+
try {
|
|
116
|
+
console.error(lines.join("\n"));
|
|
117
|
+
} catch {}
|
|
118
|
+
}
|
|
119
|
+
function ObservabilityPlugin(options = {}) {
|
|
120
|
+
let nodeWriteQueue = Promise.resolve();
|
|
121
|
+
const consoleReportedTraceIds = /* @__PURE__ */ new Set();
|
|
122
|
+
const rawStackByTraceId = /* @__PURE__ */ new Map();
|
|
123
|
+
const observability = require_index.ObservabilityPlugin({
|
|
124
|
+
...options,
|
|
125
|
+
console: false,
|
|
126
|
+
browser: void 0,
|
|
127
|
+
onRawError(error, context) {
|
|
128
|
+
const rawStack = getRawStack(error);
|
|
129
|
+
if (rawStack) rawStackByTraceId.set(context.report.traceId, rawStack);
|
|
130
|
+
options.onRawError?.(error, context);
|
|
131
|
+
},
|
|
132
|
+
onEvent(event, report, context) {
|
|
133
|
+
if (shouldUseNodeOutput(options)) nodeWriteQueue = nodeWriteQueue.catch(() => void 0).then(() => writeNodeOutput(options, event, report)).catch(() => void 0);
|
|
134
|
+
emitNodeConsoleHint(options, event, report, context, consoleReportedTraceIds, rawStackByTraceId.get(report.traceId));
|
|
135
|
+
try {
|
|
136
|
+
options.onEvent?.(event, report, context);
|
|
137
|
+
} finally {
|
|
138
|
+
if (isErrorEvent(event)) rawStackByTraceId.delete(report.traceId);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
onReport(report, context) {
|
|
142
|
+
options.onReport?.(report, context);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
observability.plugin.name = "observability-node-plugin";
|
|
146
|
+
const clear = observability.clear;
|
|
147
|
+
observability.clear = () => {
|
|
148
|
+
clear();
|
|
149
|
+
nodeWriteQueue = Promise.resolve();
|
|
150
|
+
consoleReportedTraceIds.clear();
|
|
151
|
+
rawStackByTraceId.clear();
|
|
152
|
+
};
|
|
153
|
+
return observability;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
//#endregion
|
|
157
|
+
exports.ObservabilityPlugin = ObservabilityPlugin;
|
|
158
|
+
exports.getNativeNodeRequire = getNativeNodeRequire;
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@module-federation/observability-plugin",
|
|
3
|
+
"version": "0.0.0-alpha.0",
|
|
4
|
+
"author": "module-federation",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/esm/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/module-federation/core.git",
|
|
12
|
+
"directory": "packages/observability-plugin"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist/",
|
|
19
|
+
"README.md",
|
|
20
|
+
"AI_TROUBLESHOOTING.md"
|
|
21
|
+
],
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/esm/index.js",
|
|
26
|
+
"require": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./node": {
|
|
29
|
+
"types": "./dist/node.d.ts",
|
|
30
|
+
"import": "./dist/esm/node.js",
|
|
31
|
+
"require": "./dist/node.js"
|
|
32
|
+
},
|
|
33
|
+
"./build": {
|
|
34
|
+
"types": "./dist/build.d.ts",
|
|
35
|
+
"import": "./dist/esm/build.js",
|
|
36
|
+
"require": "./dist/build.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"typesVersions": {
|
|
40
|
+
"*": {
|
|
41
|
+
".": [
|
|
42
|
+
"./dist/index.d.ts"
|
|
43
|
+
],
|
|
44
|
+
"node": [
|
|
45
|
+
"./dist/node.d.ts"
|
|
46
|
+
],
|
|
47
|
+
"build": [
|
|
48
|
+
"./dist/build.d.ts"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@module-federation/runtime": "workspace:*"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@module-federation/sdk": "workspace:*"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsdown --config tsdown.config.ts && cp *.md dist",
|
|
60
|
+
"test": "vitest run -u -c vitest.config.ts",
|
|
61
|
+
"lint": "ESLINT_USE_FLAT_CONFIG=false pnpm exec eslint --ignore-pattern node_modules \"**/*.ts\" \"package.json\"",
|
|
62
|
+
"pre-release": "pnpm run test && pnpm run build"
|
|
63
|
+
}
|
|
64
|
+
}
|