@maiyunnet/kebab 9.21.0 → 9.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/doc/kebab-rag.md CHANGED
@@ -272,6 +272,134 @@ const total = estimated === false ? null : estimated;
272
272
 
273
273
  可运行演示见示例项目的 `test/mod-test`、`test/mod-test?s=pgsql` 和 `test/sql?type=seek`。
274
274
 
275
+ monitor.md
276
+ ---
277
+
278
+ # 性能监控与异常复盘
279
+
280
+ Kebab 的每个 HTTP 子进程启动时都会自动启用 `sys/monitor`。这里的“主线程”是该子进程执行请求处理的 JavaScript 主线程;master 是负责创建、管理这些子进程的独立进程,目前没有自动启动这套监控。每个 HTTP 子进程内的主线程每秒检查资源,独立的看门狗 Worker 在该主线程无法运行时继续采样和保存阻塞现场。
281
+
282
+ ## 默认检测规则
283
+
284
+ | 指标 | 默认规则 | 记录含义 |
285
+ | --- | --- | --- |
286
+ | 进程 CPU | 达到 80%,连续采样窗口持续 10 秒 | 资源使用偏高;100% 为占满一个逻辑核心,多线程可以超过 100% |
287
+ | 进程 RSS | 超过自动计算的内存阈值,持续 10 秒 | 进程驻留内存偏高,包含 JS 堆、Buffer 和原生内存 |
288
+ | 事件循环延迟 | 每秒窗口的 P99 达到 500ms,持续 10 秒 | 持续的事件循环延迟 |
289
+ | 主线程心跳 | 连续约 5 秒未更新,每秒检查一次 | 心跳中断;独立 Worker 立即尝试抓取正在执行的主线程调用栈和 CPU Profile |
290
+
291
+ 各指标分别计时,CPU 高后接着内存高不会被合并成“连续异常”。未达到持续时间的 CPU/内存波动只保留在最近一分钟的采样中,不单独触发重型诊断。窗口最大事件循环延迟也保留在采样中,便于查看单次卡顿。
292
+
293
+ CPU 高本身不能证明业务出错。事件的 `impact=resource-high` 表示资源超过阈值;确认事件循环延迟或心跳中断后标记为 `event-loop-delayed`。应结合请求持续时间、CPU Profile 和业务指标判断原因。
294
+
295
+ ## 配置
296
+
297
+ ```ts
298
+ import * as sMonitor from '@maiyunnet/kebab/sys/monitor.js';
299
+
300
+ // --- 已自动启动的实例需要先停止,才能应用新配置 ---
301
+ sMonitor.stop();
302
+ const started = sMonitor.start({
303
+ 'cpu': 80,
304
+ 'mem': 512,
305
+ 'eloop': 500,
306
+ 'duration': 10_000,
307
+ 'blocked': 5_000,
308
+ 'heapSnapshot': false,
309
+ });
310
+ if (started === false) {
311
+ process.stderr.write('Monitor configuration is invalid.\n');
312
+ }
313
+ ```
314
+
315
+ `start()` 成功或已经启动时返回 `true`,无效配置返回 `false`。`mem=0` 自动参考系统/容器内存限制和 V8 堆上限,配置单位为 MB;`duration` 和 `blocked` 单位为 ms,最小 1000。内存预算与业务并发差异较大,应按实际进程预算配置 `mem`。监控依据绝对阈值,不会自动学习业务基线。
316
+
317
+ `stop()` 停止监控、断开正在进行的主线程 Profile 并清空请求追踪。调用它重新配置时,原有活跃请求的追踪不会延续。
318
+
319
+ ## 监控日志
320
+
321
+ 主线程与看门狗的监控简讯保存到 `log/system-monitor/YYYY/MM/DD/HH.jsonl` 或 `HH.csv`,采用框架的 `logFormat` 配置,默认 `jsonl`。JSONL 字段和 CSV 的 12 列顺序与 `Core.log` 一致,可通过 `Core.getLog` 读取,指定 `hostname='system'`、`fend='-monitor'` 和对应日期、小时的 `path`。看门狗在主线程阻塞时仍独立写盘;热重载后的日志格式随下一次主线程采样同步到看门狗。
322
+
323
+ 日志用于查看异常简讯和诊断目录。完整的采样、诊断结果与 Profile 等取证文件保存在下述 `log/monitor/` 目录,不作为普通日志行返回。
324
+
325
+ ## 读取事件和下载文件
326
+
327
+ `lib/core` 提供三个方法,通过目标服务器的 master RPC 读取已保存数据。目标 HTTP 子进程即使正在阻塞或已经退出,仍可读取磁盘中保留的记录;master 或服务器不可用时则返回读取错误。`host` 与 `getLog` 一样:省略表示本机,传入节点地址表示读取该服务器,使用当前框架配置的 `rpcPort` 和 `rpcSecret`。
328
+
329
+ | 方法 | 输入 | 返回 |
330
+ | --- | --- | --- |
331
+ | `getMonitorEvents()` | `path` 为 `YYYY/MM/DD`,默认目标服务器当天;`offset` 默认 0,`limit` 默认 20、范围 1–100;可传 `host` | `{ list, total }`;按事件目录时间倒序,摘要包含 `path`、`pid`、`time`、`source`、`status`、`reasons` |
332
+ | `getMonitorEvent()` | `path` 使用列表返回的事件路径;可传 `host` | `{ summary, data, recordStatus, files }`,包含原始事件数据及文件清单 |
333
+ | `getMonitorFile()` | `path` 使用 `files` 中的文件路径;可传 `host`、`preview` | 框架 HTTP `Response`,可通过 `getStream()` 取得原始文件流 |
334
+
335
+ 三个方法发生参数、配置或读取错误时返回 `false`。列表无事件时返回空列表;事件或文件不存在时,详情和文件方法返回 `null`。调用后需要分别检查错误与不存在,不能直接将返回值作为数据使用。
336
+
337
+ ```ts
338
+ import * as lCore from '@maiyunnet/kebab/lib/core.js';
339
+
340
+ // --- 从自己的节点配置中选取地址;undefined 表示本机 ---
341
+ const host = lCore.globalConfig.hosts[0];
342
+ const events = await lCore.getMonitorEvents({ host, 'limit': 20 });
343
+ if (events !== false && events.list.length > 0) {
344
+ const event = await lCore.getMonitorEvent({ 'path': events.list[0].path, host });
345
+ if (event !== false && event !== null) {
346
+ for (const file of event.files) {
347
+ console.log(file.path, file.size, file.preview);
348
+ }
349
+ }
350
+ }
351
+ ```
352
+
353
+ 路径均相对于目标服务器的 `log/monitor/`,应直接使用接口返回的 `path`。文件清单包含主线程事件 `diagnostics` 引用的看门狗取证文件;不需要从日志中的绝对磁盘路径拼接 URL。读取范围限定在监控目录及框架诊断文件名,拒绝目录穿越和符号链接逃逸。
354
+
355
+ `getMonitorEvent` 最多解析 4 MiB 的事件记录。旧目录没有记录、记录不完整或超过上限时,`data=null`,`recordStatus` 分别说明 `missing`、`invalid`、`too-large` 或 `unreadable`;现有原始文件仍可通过清单下载。
356
+
357
+ 文件的 `preview` 元数据为 `json`、`text` 或 `null`。预览只开放 1 MiB 内的 JSON 和调用栈文本:调用 `getMonitorFile({ path, host, preview: true })` 后可使用 `getText()` 或 `getJson()`。复杂的 `.cpuprofile`、`.heapsnapshot` 即使很小也不提供预览;大 JSON/文本同样只下载。事件读取不会解析 Profile 或堆快照。
358
+
359
+ 下载时省略 `preview` 或设为 `false`,使用 `getStream()` 将原始字节写入本地文件或传给浏览器;调用方负责消费或销毁响应流,不应将大型文件整份读入 Buffer。RPC 不会整文件读取、压缩或转换为 Base64。
360
+
361
+ 浏览器下载地址由应用控制器提供,框架不会自动发布公开文件 URL。开发者应在控制器验证运维权限、限制可选节点,再调用 `getMonitorFile`,设置附件下载响应头并流式输出;不要把 RPC 密钥或内部 RPC 地址交给浏览器。
362
+
363
+ 完整调用演示在 `www/example/ctr/test.ts`:`test/monitor-events` 支持日期、节点选择和分页,`test/monitor-event` 展示详情和文件清单,`test/monitor-file` 提供小文件预览与下载链接,下载过程中断开浏览器会关闭远程文件流。可从示例首页的 Monitor 分组进入。这些演示沿用示例控制器的访问限制,实际运维页面须接入应用自己的权限校验。
364
+
365
+ ## Node.js 的 OOM 取证
366
+
367
+ master 创建 HTTP 子进程时已经传入 `--heapsnapshot-near-heap-limit=3`。V8 堆接近上限时,Node.js 会尝试保存最多三份堆快照;这个机制不等待监控的持续异常确认,也不受 `heapSnapshot=false` 控制。该选项不能保证保存满三份快照,生成快照本身也需要额外时间和内存,详见 [Node.js 启动参数文档](https://nodejs.org/api/cli.html#--heapsnapshot-near-heap-limitmax_count)。这些 Node.js 自动生成的快照目前没有关联到监控的 `event.json`。
368
+
369
+ `heapSnapshot=false` 只关闭监控在确认 RSS 异常后主动采集的堆快照。它不表示关闭了 Node.js 在堆接近上限时自动生成的快照。
370
+
371
+ 监控按阈值主动生成诊断报告,与 Node.js 在 fatal OOM 时自动生成报告是两种触发方式。框架源码目前没有显式启用 `--report-on-fatalerror` 或 `process.report.reportOnFatalError`;运行环境额外传入的启动参数另行生效。fatal 自动报告的用途见 [Node.js 诊断报告文档](https://nodejs.org/api/report.html)。
372
+
373
+ V8 堆耗尽与系统/容器因进程内存超限而终止进程需要分别判断。Buffer 或原生内存增长不一定使 V8 堆接近上限;系统直接发送 `SIGKILL` 时,Node.js 无法执行退出前的采集,需要结合系统/容器的 OOM 记录复盘。
374
+
375
+ ## 复盘文件
376
+
377
+ 诊断目录位于运行项目的 `log/monitor/YYYY/MM/DD/`,各事件以时间、PID 和毫秒时间戳区分。目录权限为 `0700`,诊断文件为 `0600`。CPU Profile 的开始、停止和写入均由 Worker 执行,主线程再次阻塞不会拖延 Profile 的停止计时。
378
+
379
+ - `event.json`:主线程确认的事件。保存首次观察与确认时间、阈值、确认前一分钟的采样、事件中的采样与峰值、活跃请求、最近完成的请求、恢复快照,以及每次重型诊断的状态、文件路径和失败原因。
380
+ - `blocked-event.json`:Worker 在心跳中断时独立保存的现场。包括独立 CPU/RSS 采样、心跳中断时间、请求,以及 `lastMainSnapshot`;该快照的 `time` 是主线程最后成功提供上下文的时间,不代表阻塞中的最新 JS 堆数据。
381
+ - `report-*.json`:Node.js 诊断报告,移除命令行、环境变量、网络接口和网络端点后保存。
382
+ - `cpu-*.cpuprofile`、`blocked-cpu-*.cpuprofile`:可用 Chrome DevTools 的 Performance 面板读取的 CPU Profile。
383
+ - `blocked-stack-*.txt`:Worker 采集的主线程暂停调用栈。
384
+ - `profile-*.json`:Worker 独立保存的 Profile 结果。主线程仍在阻塞时,也可查看是否成功保存及失败原因。
385
+ - `heap-*.heapsnapshot`:明确开启 `heapSnapshot` 后,内存异常时按需采集的主线程 JS 堆快照。
386
+
387
+ 主线程事件中的 `diagnostics` 会关联 Worker 的实际文件和采集结果。只有 Worker 确实保存了本次阻塞的调用栈或 Profile,主线程恢复后才省略重复 Profile;没有成功采集时会记录补救尝试,并注明无法还原已经结束的阻塞调用栈。
388
+
389
+ 同一次持续异常的重型诊断间隔至少 60 秒,新增异常指标或某个指标恢复后再次升高,可以提前补充采集;每次采集都会附上当时的请求快照。新的独立事件会单独记录,不受上一事件的冷却时间限制。Inspector 正被占用时,事件摘要仍然保存,持续异常约 5 秒后重试。事件摘要每约 5 秒更新一次,恢复或采集结束后更新;正常恢复与监控被停止分别记录。
390
+
391
+ 保留数据有界:确认前最多 60 次采样、事件内最近 300 次采样及累计峰值、最多 100 条活跃请求详情、最近一分钟内最多 100 条完成请求、最近 60 次重型诊断结果。诊断文件不会自动清理,应纳入项目既有日志保留策略。
392
+
393
+ ## 解释边界
394
+
395
+ - 采样无法保证捕获任意短暂峰值。Profile 从异常被确认或心跳中断被发现时开始,不包含过去的执行;它能定位采集期间的热点,不能倒放异常开始前的执行。
396
+ - CPU 使用率覆盖整个进程,所采 Profile 面向主线程。原生线程池和其他 Worker 的 CPU 热点不一定出现在主线程 Profile 中。
397
+ - 请求的 CPU/RSS 增量是请求存续期间**整个进程**的增量。并发请求、后台任务、Worker 和 GC 都可能参与,不能直接把资源增量归因给单个 URL。请求参数、片段和请求体不保存。
398
+ - RSS 高不等于 JS 堆泄漏。默认的报告与内存采样用于区分堆、external、arrayBuffers 和 RSS;要分析 JS 对象保留关系,需要堆快照。堆快照不包含其他 Worker 的堆,也不能完整解释原生分配。
399
+ - 监控主动采集的堆快照同步阻塞主线程,还需要大量额外内存(见 [Node.js V8 文档](https://nodejs.org/api/v8.html#v8writeheapsnapshotfilenameoptions)),默认关闭;可用内存明显不足时跳过并记录原因。监控不会把自己主动采集的同步 Report/HeapSnapshot 开销再次当成业务异常。
400
+ - Inspector 可能无法及时中断原生调用或在 OOM 前完成采集。Worker 会保存采样及失败/超时原因,并释放采集状态;进程被 OOM killer 或强制终止时,进程内监控无法保证留下完整文件。
401
+ - `--inspect` 调试模式跳过异常确认与阻塞采集,避免干扰断点;系统时钟调整不影响 CPU 比例、持续确认与心跳计时。
402
+
275
403
  index/index.md
276
404
  ---
277
405
 
@@ -1589,7 +1717,7 @@ index/variables/VER.md
1589
1717
 
1590
1718
  # Variable: VER
1591
1719
 
1592
- > `const` **VER**: `"9.21.0"` = `'9.21.0'`
1720
+ > `const` **VER**: `"9.21.1"` = `'9.21.1'`
1593
1721
 
1594
1722
  Defined in: [index.ts:10](https://github.com/maiyunnet/kebab/blob/master/index.ts#L10)
1595
1723
 
@@ -3579,7 +3707,7 @@ lib/core/functions/clone.md
3579
3707
 
3580
3708
  > **clone**\<`T`\>(`obj`): `T`
3581
3709
 
3582
- Defined in: [lib/core.ts:1409](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1409)
3710
+ Defined in: [lib/core.ts:1541](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1541)
3583
3711
 
3584
3712
  完整的克隆一份数组/对象
3585
3713
 
@@ -3643,7 +3771,7 @@ lib/core/functions/debug.md
3643
3771
 
3644
3772
  > **debug**(`message?`, ...`optionalParams`): `void`
3645
3773
 
3646
- Defined in: [lib/core.ts:1455](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1455)
3774
+ Defined in: [lib/core.ts:1587](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1587)
3647
3775
 
3648
3776
  打印调试信息,线上环境不会打印
3649
3777
 
@@ -3678,7 +3806,7 @@ lib/core/functions/display.md
3678
3806
 
3679
3807
  > **display**(`message?`, ...`optionalParams`): `void`
3680
3808
 
3681
- Defined in: [lib/core.ts:1468](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1468)
3809
+ Defined in: [lib/core.ts:1600](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1600)
3682
3810
 
3683
3811
  向控制台直接显示内容,一般情况下禁止使用
3684
3812
 
@@ -3846,6 +3974,131 @@ Defined in: [lib/core.ts:1321](https://github.com/maiyunnet/kebab/blob/master/li
3846
3974
 
3847
3975
  `Promise`\<`false` \| \{ `list`: `any`[] \| `string`[][]; `total`: `number`; \}\>
3848
3976
 
3977
+ lib/core/functions/getMonitorEvent.md
3978
+ ---
3979
+
3980
+ [**Documents for @maiyunnet/kebab**](../../../index.md)
3981
+
3982
+ ***
3983
+
3984
+ [Documents for @maiyunnet/kebab](../../../index.md) / [lib/core](../index.md) / getMonitorEvent
3985
+
3986
+ # Function: getMonitorEvent()
3987
+
3988
+ > **getMonitorEvent**(`opt`): `Promise`\<`false` \| [`IMonitorEvent`](../interfaces/IMonitorEvent.md) \| `null`\>
3989
+
3990
+ Defined in: [lib/core.ts:1457](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1457)
3991
+
3992
+ 读取事件详情和文件清单;只解析事件记录,不解析 Profile 或堆快照
3993
+
3994
+ ## Parameters
3995
+
3996
+ ### opt
3997
+
3998
+ path 使用 getMonitorEvents 返回的事件路径;host 默认本机
3999
+
4000
+ #### host?
4001
+
4002
+ `string`
4003
+
4004
+ #### path
4005
+
4006
+ `string`
4007
+
4008
+ ## Returns
4009
+
4010
+ `Promise`\<`false` \| [`IMonitorEvent`](../interfaces/IMonitorEvent.md) \| `null`\>
4011
+
4012
+ 事件详情;不存在时返回 null,参数、配置或读取错误时返回 false
4013
+
4014
+ lib/core/functions/getMonitorEvents.md
4015
+ ---
4016
+
4017
+ [**Documents for @maiyunnet/kebab**](../../../index.md)
4018
+
4019
+ ***
4020
+
4021
+ [Documents for @maiyunnet/kebab](../../../index.md) / [lib/core](../index.md) / getMonitorEvents
4022
+
4023
+ # Function: getMonitorEvents()
4024
+
4025
+ > **getMonitorEvents**(`opt?`): `Promise`\<`false` \| \{ `list`: [`IMonitorEventSummary`](../interfaces/IMonitorEventSummary.md)[]; `total`: `number`; \}\>
4026
+
4027
+ Defined in: [lib/core.ts:1430](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1430)
4028
+
4029
+ 获取某天已保存的监控事件,按目录时间倒序分页
4030
+
4031
+ ## Parameters
4032
+
4033
+ ### opt?
4034
+
4035
+ path 为 YYYY/MM/DD,默认目标服务器的当天;offset 默认 0,limit 默认 20、最多 100
4036
+
4037
+ #### host?
4038
+
4039
+ `string`
4040
+
4041
+ 与 getLog 相同,使用目标服务器的 RPC 端口和密钥
4042
+
4043
+ #### limit?
4044
+
4045
+ `number`
4046
+
4047
+ #### offset?
4048
+
4049
+ `number`
4050
+
4051
+ #### path?
4052
+
4053
+ `string`
4054
+
4055
+ ## Returns
4056
+
4057
+ `Promise`\<`false` \| \{ `list`: [`IMonitorEventSummary`](../interfaces/IMonitorEventSummary.md)[]; `total`: `number`; \}\>
4058
+
4059
+ 事件列表和总数;无事件时返回空列表,参数、配置或读取错误时返回 false
4060
+
4061
+ lib/core/functions/getMonitorFile.md
4062
+ ---
4063
+
4064
+ [**Documents for @maiyunnet/kebab**](../../../index.md)
4065
+
4066
+ ***
4067
+
4068
+ [Documents for @maiyunnet/kebab](../../../index.md) / [lib/core](../index.md) / getMonitorFile
4069
+
4070
+ # Function: getMonitorFile()
4071
+
4072
+ > **getMonitorFile**(`opt`): `Promise`\<`false` \| [`Response`](../../undici/response/classes/Response.md) \| `null`\>
4073
+
4074
+ Defined in: [lib/core.ts:1481](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1481)
4075
+
4076
+ 获取监控原始文件的响应,可使用 getStream() 下载;小文件可用 getText()/getJson() 预览
4077
+
4078
+ ## Parameters
4079
+
4080
+ ### opt
4081
+
4082
+ path 使用事件 files 中的文件路径;preview=true 只允许 1 MiB 内的 JSON/调用栈文本;host 默认本机
4083
+
4084
+ #### host?
4085
+
4086
+ `string`
4087
+
4088
+ #### path
4089
+
4090
+ `string`
4091
+
4092
+ #### preview?
4093
+
4094
+ `boolean`
4095
+
4096
+ ## Returns
4097
+
4098
+ `Promise`\<`false` \| [`Response`](../../undici/response/classes/Response.md) \| `null`\>
4099
+
4100
+ 文件响应;不存在时返回 null,参数、预览限制、配置或读取错误时返回 false;流消费或销毁由调用方负责
4101
+
3849
4102
  lib/core/functions/ipLimit.md
3850
4103
  ---
3851
4104
 
@@ -3963,7 +4216,7 @@ lib/core/functions/loadEnv.md
3963
4216
 
3964
4217
  > **loadEnv**(`dir`): `Promise`\<`void`\>
3965
4218
 
3966
- Defined in: [lib/core.ts:1539](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1539)
4219
+ Defined in: [lib/core.ts:1671](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1671)
3967
4220
 
3968
4221
  加载 .env 文件到 process.env,若文件不存在则跳过
3969
4222
 
@@ -4033,7 +4286,7 @@ lib/core/functions/ls.md
4033
4286
 
4034
4287
  > **ls**(`opt`): `Promise`\<`object`[]\>
4035
4288
 
4036
- Defined in: [lib/core.ts:1370](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1370)
4289
+ Defined in: [lib/core.ts:1502](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1502)
4037
4290
 
4038
4291
  获取目录内文件/文件夹列表
4039
4292
 
@@ -4438,7 +4691,7 @@ lib/core/functions/resolveEnvVars.md
4438
4691
 
4439
4692
  > **resolveEnvVars**(`obj`): `void`
4440
4693
 
4441
- Defined in: [lib/core.ts:1569](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1569)
4694
+ Defined in: [lib/core.ts:1701](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1701)
4442
4695
 
4443
4696
  将配置对象中的 ${ENV_VAR} 占位符替换为 process.env 的值
4444
4697
 
@@ -4913,7 +5166,7 @@ lib/core/functions/writeEventStreamHead.md
4913
5166
 
4914
5167
  > **writeEventStreamHead**(`res`): `void`
4915
5168
 
4916
- Defined in: [lib/core.ts:1509](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1509)
5169
+ Defined in: [lib/core.ts:1641](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1641)
4917
5170
 
4918
5171
  提交服务器发送事件(SSE)响应头
4919
5172
 
@@ -4948,7 +5201,7 @@ lib/core/functions/writeHead.md
4948
5201
 
4949
5202
  > **writeHead**(`res`, `statusCode`, `headers?`): `void`
4950
5203
 
4951
- Defined in: [lib/core.ts:1488](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1488)
5204
+ Defined in: [lib/core.ts:1620](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1620)
4952
5205
 
4953
5206
  提交 HTTP 响应状态和头部,兼容 HTTP/1.1 与 HTTP/2
4954
5207
 
@@ -4998,7 +5251,7 @@ lib/core/functions/write.md
4998
5251
 
4999
5252
  > **write**(`res`, `data`): `void`
5000
5253
 
5001
- Defined in: [lib/core.ts:1521](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1521)
5254
+ Defined in: [lib/core.ts:1653](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1653)
5002
5255
 
5003
5256
  向 res 发送数据
5004
5257
 
@@ -5039,6 +5292,9 @@ lib/core/index.md
5039
5292
 
5040
5293
  - [ICookieOptions](interfaces/ICookieOptions.md)
5041
5294
  - [ILogOptions](interfaces/ILogOptions.md)
5295
+ - [IMonitorEvent](interfaces/IMonitorEvent.md)
5296
+ - [IMonitorEventSummary](interfaces/IMonitorEventSummary.md)
5297
+ - [IMonitorFile](interfaces/IMonitorFile.md)
5042
5298
 
5043
5299
  ## Type Aliases
5044
5300
 
@@ -5072,6 +5328,9 @@ lib/core/index.md
5072
5328
  - [emptyObject](functions/emptyObject.md)
5073
5329
  - [exec](functions/exec.md)
5074
5330
  - [getLog](functions/getLog.md)
5331
+ - [getMonitorEvent](functions/getMonitorEvent.md)
5332
+ - [getMonitorEvents](functions/getMonitorEvents.md)
5333
+ - [getMonitorFile](functions/getMonitorFile.md)
5075
5334
  - [ip](functions/ip.md)
5076
5335
  - [ipLimit](functions/ipLimit.md)
5077
5336
  - [ips](functions/ips.md)
@@ -5246,6 +5505,173 @@ Defined in: [lib/core.ts:1198](https://github.com/maiyunnet/kebab/blob/master/li
5246
5505
 
5247
5506
  Defined in: [lib/core.ts:1193](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1193)
5248
5507
 
5508
+ lib/core/interfaces/IMonitorEvent.md
5509
+ ---
5510
+
5511
+ [**Documents for @maiyunnet/kebab**](../../../index.md)
5512
+
5513
+ ***
5514
+
5515
+ [Documents for @maiyunnet/kebab](../../../index.md) / [lib/core](../index.md) / IMonitorEvent
5516
+
5517
+ # Interface: IMonitorEvent
5518
+
5519
+ Defined in: [lib/core.ts:1387](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1387)
5520
+
5521
+ 事件原始数据与可读取的文件;data 为 null 时可下载原始记录复盘
5522
+
5523
+ ## Properties
5524
+
5525
+ ### data
5526
+
5527
+ > **data**: `Record`\<`string`, `unknown`\> \| `null`
5528
+
5529
+ Defined in: [lib/core.ts:1389](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1389)
5530
+
5531
+ ***
5532
+
5533
+ ### files
5534
+
5535
+ > **files**: [`IMonitorFile`](IMonitorFile.md)[]
5536
+
5537
+ Defined in: [lib/core.ts:1391](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1391)
5538
+
5539
+ ***
5540
+
5541
+ ### recordStatus
5542
+
5543
+ > **recordStatus**: `"loaded"` \| `"invalid"` \| `"missing"` \| `"too-large"` \| `"unreadable"`
5544
+
5545
+ Defined in: [lib/core.ts:1390](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1390)
5546
+
5547
+ ***
5548
+
5549
+ ### summary
5550
+
5551
+ > **summary**: [`IMonitorEventSummary`](IMonitorEventSummary.md)
5552
+
5553
+ Defined in: [lib/core.ts:1388](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1388)
5554
+
5555
+ lib/core/interfaces/IMonitorEventSummary.md
5556
+ ---
5557
+
5558
+ [**Documents for @maiyunnet/kebab**](../../../index.md)
5559
+
5560
+ ***
5561
+
5562
+ [Documents for @maiyunnet/kebab](../../../index.md) / [lib/core](../index.md) / IMonitorEventSummary
5563
+
5564
+ # Interface: IMonitorEventSummary
5565
+
5566
+ Defined in: [lib/core.ts:1367](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1367)
5567
+
5568
+ 已保存监控事件的简短摘要,path 相对于 log/monitor/
5569
+
5570
+ ## Properties
5571
+
5572
+ ### path
5573
+
5574
+ > **path**: `string`
5575
+
5576
+ Defined in: [lib/core.ts:1368](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1368)
5577
+
5578
+ ***
5579
+
5580
+ ### pid
5581
+
5582
+ > **pid**: `number`
5583
+
5584
+ Defined in: [lib/core.ts:1369](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1369)
5585
+
5586
+ ***
5587
+
5588
+ ### reasons
5589
+
5590
+ > **reasons**: `string`[]
5591
+
5592
+ Defined in: [lib/core.ts:1373](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1373)
5593
+
5594
+ ***
5595
+
5596
+ ### source
5597
+
5598
+ > **source**: `"main"` \| `"watchdog"`
5599
+
5600
+ Defined in: [lib/core.ts:1371](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1371)
5601
+
5602
+ ***
5603
+
5604
+ ### status
5605
+
5606
+ > **status**: `string`
5607
+
5608
+ Defined in: [lib/core.ts:1372](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1372)
5609
+
5610
+ ***
5611
+
5612
+ ### time
5613
+
5614
+ > **time**: `number`
5615
+
5616
+ Defined in: [lib/core.ts:1370](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1370)
5617
+
5618
+ lib/core/interfaces/IMonitorFile.md
5619
+ ---
5620
+
5621
+ [**Documents for @maiyunnet/kebab**](../../../index.md)
5622
+
5623
+ ***
5624
+
5625
+ [Documents for @maiyunnet/kebab](../../../index.md) / [lib/core](../index.md) / IMonitorFile
5626
+
5627
+ # Interface: IMonitorFile
5628
+
5629
+ Defined in: [lib/core.ts:1377](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1377)
5630
+
5631
+ 监控文件元数据;复杂格式或超过 1 MiB 的文件不提供预览
5632
+
5633
+ ## Properties
5634
+
5635
+ ### mtime
5636
+
5637
+ > **mtime**: `number`
5638
+
5639
+ Defined in: [lib/core.ts:1382](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1382)
5640
+
5641
+ 最后修改时间,单位 ms
5642
+
5643
+ ***
5644
+
5645
+ ### name
5646
+
5647
+ > **name**: `string`
5648
+
5649
+ Defined in: [lib/core.ts:1379](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1379)
5650
+
5651
+ ***
5652
+
5653
+ ### path
5654
+
5655
+ > **path**: `string`
5656
+
5657
+ Defined in: [lib/core.ts:1378](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1378)
5658
+
5659
+ ***
5660
+
5661
+ ### preview
5662
+
5663
+ > **preview**: `"text"` \| `"json"` \| `null`
5664
+
5665
+ Defined in: [lib/core.ts:1383](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1383)
5666
+
5667
+ ***
5668
+
5669
+ ### size
5670
+
5671
+ > **size**: `number`
5672
+
5673
+ Defined in: [lib/core.ts:1380](https://github.com/maiyunnet/kebab/blob/master/lib/core.ts#L1380)
5674
+
5249
5675
  lib/core/namespaces/v/classes/ValiError.md
5250
5676
  ---
5251
5677
 
package/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * --- 本文件用来定义每个目录实体地址的常量 ---
6
6
  */
7
7
  /** --- 当前系统版本号 --- */
8
- export declare const VER = "9.21.0";
8
+ export declare const VER = "9.21.1";
9
9
  /** --- 框架根目录,以 / 结尾 --- */
10
10
  export declare const ROOT_PATH: string;
11
11
  /** --- 框架的 LIB,以 / 结尾 --- */
package/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * --- 本文件用来定义每个目录实体地址的常量 ---
7
7
  */
8
8
  /** --- 当前系统版本号 --- */
9
- export const VER = '9.21.0';
9
+ export const VER = '9.21.1';
10
10
  // --- 服务端用的路径 ---
11
11
  const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
12
12
  /** --- /xxx/xxx --- */
package/lib/core.d.ts CHANGED
@@ -331,6 +331,65 @@ export declare function getLog(opt: {
331
331
  'list': string[][] | kebab.Json[];
332
332
  'total': number;
333
333
  } | false>;
334
+ /** --- 已保存监控事件的简短摘要,path 相对于 log/monitor/ --- */
335
+ export interface IMonitorEventSummary {
336
+ 'path': string;
337
+ 'pid': number;
338
+ 'time': number;
339
+ 'source': 'main' | 'watchdog';
340
+ 'status': string;
341
+ 'reasons': string[];
342
+ }
343
+ /** --- 监控文件元数据;复杂格式或超过 1 MiB 的文件不提供预览 --- */
344
+ export interface IMonitorFile {
345
+ 'path': string;
346
+ 'name': string;
347
+ 'size': number;
348
+ /** --- 最后修改时间,单位 ms --- */
349
+ 'mtime': number;
350
+ 'preview': 'json' | 'text' | null;
351
+ }
352
+ /** --- 事件原始数据与可读取的文件;data 为 null 时可下载原始记录复盘 --- */
353
+ export interface IMonitorEvent {
354
+ 'summary': IMonitorEventSummary;
355
+ 'data': Record<string, unknown> | null;
356
+ 'recordStatus': 'loaded' | 'missing' | 'too-large' | 'invalid' | 'unreadable';
357
+ 'files': IMonitorFile[];
358
+ }
359
+ /**
360
+ * --- 获取某天已保存的监控事件,按目录时间倒序分页 ---
361
+ * @param opt path 为 YYYY/MM/DD,默认目标服务器的当天;offset 默认 0,limit 默认 20、最多 100
362
+ * @returns 事件列表和总数;无事件时返回空列表,参数、配置或读取错误时返回 false
363
+ */
364
+ export declare function getMonitorEvents(opt?: {
365
+ 'path'?: string;
366
+ 'offset'?: number;
367
+ 'limit'?: number;
368
+ /** --- 与 getLog 相同,使用目标服务器的 RPC 端口和密钥 --- */
369
+ 'host'?: string;
370
+ }): Promise<{
371
+ 'list': IMonitorEventSummary[];
372
+ 'total': number;
373
+ } | false>;
374
+ /**
375
+ * --- 读取事件详情和文件清单;只解析事件记录,不解析 Profile 或堆快照 ---
376
+ * @param opt path 使用 getMonitorEvents 返回的事件路径;host 默认本机
377
+ * @returns 事件详情;不存在时返回 null,参数、配置或读取错误时返回 false
378
+ */
379
+ export declare function getMonitorEvent(opt: {
380
+ 'path': string;
381
+ 'host'?: string;
382
+ }): Promise<IMonitorEvent | null | false>;
383
+ /**
384
+ * --- 获取监控原始文件的响应,可使用 getStream() 下载;小文件可用 getText()/getJson() 预览 ---
385
+ * @param opt path 使用事件 files 中的文件路径;preview=true 只允许 1 MiB 内的 JSON/调用栈文本;host 默认本机
386
+ * @returns 文件响应;不存在时返回 null,参数、预览限制、配置或读取错误时返回 false;流消费或销毁由调用方负责
387
+ */
388
+ export declare function getMonitorFile(opt: {
389
+ 'path': string;
390
+ 'preview'?: boolean;
391
+ 'host'?: string;
392
+ }): Promise<lUndiciResponse.Response | null | false>;
334
393
  /**
335
394
  * --- 获取目录内文件/文件夹列表 ---
336
395
  * @param opt 参数