diff --git a/kit/src/glance/index.js b/kit/src/glance/index.js index 6e01e16..3378272 100644 --- a/kit/src/glance/index.js +++ b/kit/src/glance/index.js @@ -1,11 +1,15 @@ /** * kit glance 命令 * - 记录模式:--pid 或 --port ,采集一次写入 sqlite(~/.kit/glance.db) - * - 报告模式:--report [报告文件](默认 report.html),需配合 --pid/--port + * - 报告文件:--report [文件](默认 report.html),需配合 --pid/--port + * - 报告服务:--report <端口号>,报告导出到系统临时目录 kit-glance/<端口>/index.html, + * 并在该端口开启简易 http 服务在线查看 * - --startTime/--endTime 格式 yyyyMMddHHmmss,指定报告时间范围 */ const fs = require("fs"); const path = require("path"); +const os = require("os"); +const http = require("http"); const store = require("./store"); const report = require("./report"); @@ -119,6 +123,46 @@ function buildReport(cli, reportFile) { $logger.info(`报告已生成: ${path.resolve(reportFile)}`); } +/** + * 报告在线服务:把报告导出为系统临时目录 kit-glance/<端口>/index.html, + * 并在该端口启动一个简易 http 服务供在线查看(监听 0.0.0.0)。 + * 报告数据按 --pid/--port 与 --startTime/--endTime 从当前库生成。 + * @param {object} cli 命令行 + * @param {number} serverPort 报告服务端口 + */ +function serveOnline(cli, serverPort) { + const serveDir = path.join(os.tmpdir(), "kit-glance", String(serverPort)); + fs.mkdirSync(serveDir, { recursive: true }); + const indexPath = path.join(serveDir, "index.html"); + + buildReport(cli, indexPath); + + const server = http.createServer((req, res) => { + const urlPath = (req.url || "/").split("?")[0]; + if (urlPath === "/" || urlPath === "/index.html") { + res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); + fs.createReadStream(indexPath).pipe(res); + return; + } + res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }); + res.end("Not Found"); + }); + + server.on("error", (e) => { + if (e.code === "EADDRINUSE") { + $logger.warn(`端口 ${serverPort} 已被占用:报告已更新到 ${indexPath},已有报告服务运行中可直接刷新查看`); + process.exit(0); + } else { + $logger.error(`启动 http 服务失败: ${e.message}`); + process.exit(-1); + } + }); + + server.listen(serverPort, "0.0.0.0", () => { + $logger.info(`在线查看: http://localhost:${serverPort}/ (监听 0.0.0.0:${serverPort},可通过本机任一 IP 访问)`); + }); +} + async function main(cli) { const pidText = cli.getParamValue("pid"); const portText = cli.getParamValue("port"); @@ -152,8 +196,13 @@ async function main(cli) { } if (isReport) { - const reportFile = reportRaw || "report.html"; - buildReport(cli, reportFile); + const reportValue = reportRaw || ""; + const servePort = /^\d+$/.test(reportValue) ? Number(reportValue) : 0; + if (servePort >= 1 && servePort <= 65535) { + serveOnline(cli, servePort); + return; + } + buildReport(cli, reportValue || "report.html"); return; } diff --git a/kit/src/index.js b/kit/src/index.js index e2fb84f..0fb6a17 100644 --- a/kit/src/index.js +++ b/kit/src/index.js @@ -189,7 +189,7 @@ parser.addCmdLine("killport ", "释放端口", function (cli) { net.killport( parseInt(port, 10) ); }); -parser.addCmdLine("glance [--pid] [--port] [--report] [--startTime] [--endTime]", "进程监控:--pid/--port 采集监控数据(仅 Linux),--report 生成报告并输出 HTML;", async function (cli) { +parser.addCmdLine("glance [--pid] [--port] [--report] [--startTime] [--endTime]", "进程监控:--pid/--port 采集监控数据(仅 Linux);--report 生成报告 HTML,传端口号时导出到临时目录并开启 http 服务在线查看;", async function (cli) { await glance.main(cli); });