@hyzyn/dsh-docker 0.13.7 → 0.15.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.
@@ -0,0 +1,571 @@
1
+ /** verdict / findings 排序权重(数字越小越严重)。 */
2
+ const SEVERITY_ORDER = { critical: 0, warning: 1, info: 2, ok: 3 };
3
+ /** suggestions 上限(契约 §1.2:0~5 条)。 */
4
+ const MAX_SUGGESTIONS = 5;
5
+ /** 证据片段上限(契约:每条 ≤ 200 字,超出截断并带 `…`)。 */
6
+ const EVIDENCE_CLIP = 200;
7
+ /** 内存逼近上限的判据阈值(%)。 */
8
+ const MEM_PRESSURE_PERCENT = 90;
9
+ /** CPU 逼近占满的判据阈值(%)。 */
10
+ const CPU_PRESSURE_PERCENT = 90;
11
+ /** 「反复重启」的判定门槛(次数)。与 `attention()` 的 D11 阈值同口径:合法重部署也会重启一两次。 */
12
+ const CRASH_LOOP_RESTARTS = 3;
13
+ /**
14
+ * 疑似报错行的判据。刻意**不做**「日志级别解析」:日志格式千差万别(logfmt /
15
+ * JSON / 纯文本 / 带方括号的级别),这里只找最通用的几个词。误报的代价是一条
16
+ * info 级 finding(detail 里原样给出第一条命中行,用户自己判),漏报的代价是
17
+ * 一条线索都没有——所以宁宽勿窄,但「stderr」这种包含 err 的词不算(靠 \b)。
18
+ */
19
+ const ERROR_LINE_RE = /\b(?:error|err|fatal|panic|exception|traceback|failed|failure)\b/i;
20
+ /* ------------------------------------------------------------------ *
21
+ * 文案与数值的格式化(都给用户看,不出现 docker 字段名)
22
+ * ------------------------------------------------------------------ */
23
+ /** 把证据片段压成单行并截断到 200 字(超出带 `…`)。 */
24
+ function clip(text, max = EVIDENCE_CLIP) {
25
+ if (text === null)
26
+ return '';
27
+ const flat = text.replace(/\s+/g, ' ').trim();
28
+ const chars = [...flat];
29
+ if (chars.length <= max)
30
+ return flat;
31
+ return chars.slice(0, max - 1).join('') + '…';
32
+ }
33
+ const BYTE_UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
34
+ /** `536870912` → `512MiB`(二进制单位,与 docker 的显示口径一致)。 */
35
+ function formatBytes(bytes) {
36
+ let value = Math.max(bytes, 0);
37
+ let unit = 0;
38
+ while (value >= 1024 && unit < BYTE_UNITS.length - 1) {
39
+ value /= 1024;
40
+ unit += 1;
41
+ }
42
+ const rounded = unit === 0 ? Math.round(value) : Math.round(value * 10) / 10;
43
+ return `${String(rounded)}${BYTE_UNITS[unit]}`;
44
+ }
45
+ /** `96.5` → `96.5%`(保留一位小数,去掉多余的 `.0`)。 */
46
+ function formatPercent(percent) {
47
+ return `${String(Math.round(percent * 10) / 10)}%`;
48
+ }
49
+ /** CPU 上限(纳核)→ `0.5 核` / `2 核`。 */
50
+ function formatCpuLimit(nanoCpus) {
51
+ const cores = Math.round(nanoCpus / 1e8) / 10;
52
+ return `${String(cores)} 核`;
53
+ }
54
+ const SECOND_MS = 1000;
55
+ const MINUTE_MS = 60 * SECOND_MS;
56
+ const HOUR_MS = 60 * MINUTE_MS;
57
+ const DAY_MS = 24 * HOUR_MS;
58
+ /**
59
+ * 相对时长的人类可读文案(`docker ps` 的 STATUS 列用)。
60
+ *
61
+ * 照着 docker 的 `units.HumanDuration` 分档复刻:**秒 → 分 → 时 → 天 → 周 → 月 → 年**,
62
+ * 其中 1 分钟 / 1 小时给 "About a minute" / "About an hour"(docker 就是这么念的),
63
+ * 「1 秒」单独成一档。刻意保留英文形态:用户从 `docker ps` 看到的是同一句话,
64
+ * 两处长得一样才不用在脑子里换算。
65
+ */
66
+ export function humanDuration(ms) {
67
+ if (!Number.isFinite(ms) || ms < 0)
68
+ return '';
69
+ const seconds = Math.floor(ms / SECOND_MS);
70
+ if (seconds < 1)
71
+ return 'Less than a second';
72
+ if (seconds === 1)
73
+ return '1 second';
74
+ if (seconds < 60)
75
+ return `${String(seconds)} seconds`;
76
+ const minutes = Math.floor(ms / MINUTE_MS);
77
+ if (minutes === 1)
78
+ return 'About a minute';
79
+ if (minutes < 60)
80
+ return `${String(minutes)} minutes`;
81
+ const hours = Math.round(ms / HOUR_MS);
82
+ if (hours === 1)
83
+ return 'About an hour';
84
+ if (hours < 48)
85
+ return `${String(hours)} hours`;
86
+ if (hours < 24 * 7 * 2)
87
+ return `${String(Math.floor(hours / 24))} days`;
88
+ if (hours < 24 * 30 * 2)
89
+ return `${String(Math.floor(hours / 24 / 7))} weeks`;
90
+ if (hours < 24 * 365 * 2)
91
+ return `${String(Math.floor(hours / 24 / 30))} months`;
92
+ return `${String(Math.floor(hours / 24 / 365))} years`;
93
+ }
94
+ /** 解析 ISO 时间;docker 的零值时间(公元 1 年)与非法值一律当「不知道」。 */
95
+ function isoMs(iso) {
96
+ if (iso === null || iso === '')
97
+ return null;
98
+ const ms = Date.parse(iso);
99
+ return Number.isFinite(ms) ? ms : null;
100
+ }
101
+ /**
102
+ * ps 风格的 STATUS 文案(`evidence.status` 用)。
103
+ *
104
+ * **为什么不直接用 `ContainerDetail.status`**:它实测就是 inspect 的 `State.Status`
105
+ * (`running` / `exited`),而 `docker ps` 的 STATUS 是另一列(`Up 4 hours (healthy)` /
106
+ * `Exited (137) 2 minutes ago`)——契约 §1.2 的 evidence 例子要的是后者。为了这一行
107
+ * 再跑一条 `docker ps` 不划算(诊断已经有 inspect 的权威字段),所以按 docker ps 的
108
+ * 口径现算:判据用 inspect,展示文案顺手推出来(一条事实一个来源)。
109
+ *
110
+ * `nowMs` 缺席时不给相对时长(不编「多久以前」),退化成 `Up` / `Exited (137)`。
111
+ */
112
+ export function containerStatusText(detail, nowMs) {
113
+ const now = typeof nowMs === 'number' && Number.isFinite(nowMs) ? nowMs : null;
114
+ const healthSuffix = detail.health === null || detail.health === 'none'
115
+ ? ''
116
+ : detail.health === 'starting'
117
+ ? ' (health: starting)'
118
+ : ` (${detail.health})`;
119
+ const since = (from) => {
120
+ if (now === null)
121
+ return '';
122
+ const at = isoMs(from);
123
+ if (at === null)
124
+ return '';
125
+ const text = humanDuration(now - at);
126
+ return text === '' ? '' : ` ${text}`;
127
+ };
128
+ const code = detail.exitCode === null ? '' : ` (${String(detail.exitCode)})`;
129
+ switch (detail.state) {
130
+ case 'running':
131
+ return `Up${since(detail.startedAt)}${healthSuffix}`;
132
+ case 'paused':
133
+ return `Up${since(detail.startedAt)} (Paused)`;
134
+ case 'exited': {
135
+ const ago = since(detail.finishedAt);
136
+ return `Exited${code}${ago === '' ? '' : `${ago} ago`}`;
137
+ }
138
+ case 'restarting': {
139
+ const ago = since(detail.finishedAt);
140
+ return `Restarting${code}${ago === '' ? '' : `${ago} ago`}`;
141
+ }
142
+ case 'created':
143
+ return 'Created';
144
+ case 'dead':
145
+ return 'Dead';
146
+ case 'removing':
147
+ return 'Removing';
148
+ default:
149
+ return detail.state;
150
+ }
151
+ }
152
+ /** 退出码的常见含义(判据 2 的 detail 用)。只收「用户能据此行动」的那几个。 */
153
+ const EXIT_MEANING = {
154
+ 1: '应用自己报错退出(最常见的一类失败,具体原因看日志)',
155
+ 126: '命令无法执行(多半是启动脚本没有执行权限)',
156
+ 127: '命令不存在(镜像里找不到要启动的可执行文件,命令名或路径写错了)',
157
+ 137: '进程被强制杀死(收到 SIGKILL:被内存限制打死,或被 docker stop 强杀)',
158
+ 139: '进程段错误退出(收到 SIGSEGV,应用自身崩溃)',
159
+ 143: '进程收到终止信号后退出(SIGTERM,多为 docker stop 主动停)',
160
+ };
161
+ /** 未在字典里的退出码:只说「非零」,不猜。 */
162
+ function exitMeaning(code) {
163
+ return EXIT_MEANING[code] ?? '非零退出(没有对应到常见退出码,看退出前的日志定位)';
164
+ }
165
+ /** `created` / `paused` / `dead` 的中文状态(判据 7 的标题与 summary 用)。 */
166
+ const STATE_LABEL = {
167
+ created: '已创建但没启动',
168
+ paused: '已暂停',
169
+ dead: '已死亡(运行时异常,容器无法再启动)',
170
+ };
171
+ /** 容器是不是「在运行」(判据 11/12 的「容器在运行」口径)。 */
172
+ function isRunning(state) {
173
+ return state === 'running';
174
+ }
175
+ /**
176
+ * 事件 → 给人看的一句话(契约:`kind` 原样,`text` 中文)。
177
+ * 未知动作原样返回——猜出来的中文比英文动作名更容易误导。
178
+ */
179
+ function timelineText(event) {
180
+ const action = event.action;
181
+ const base = (action.split(':')[0] ?? '').trim();
182
+ switch (base) {
183
+ case 'start':
184
+ return '启动';
185
+ case 'die':
186
+ return event.exitCode === null ? '退出' : `退出(码 ${String(event.exitCode)})`;
187
+ case 'stop':
188
+ return '停止';
189
+ case 'kill':
190
+ return '被信号杀死';
191
+ case 'oom':
192
+ return '内存不足被系统杀掉';
193
+ case 'destroy':
194
+ return '被删除';
195
+ case 'rename':
196
+ return '改名';
197
+ case 'update':
198
+ return '配置更新';
199
+ case 'health_status': {
200
+ // `health_status: healthy|unhealthy|starting`
201
+ const suffix = (action.split(':')[1] ?? '').trim();
202
+ return suffix === '' ? '健康状态变化' : `健康检查结果:${suffix}`;
203
+ }
204
+ default:
205
+ return action;
206
+ }
207
+ }
208
+ /** Unix 秒 → ISO 8601(秒级,去掉 `.000`;无时间给 null)。 */
209
+ function eventTimeIso(time) {
210
+ if (time === null)
211
+ return null;
212
+ const iso = new Date(time * 1000).toISOString();
213
+ return iso.replace(/\.\d{3}Z$/, 'Z');
214
+ }
215
+ /** `ContainerStats` 里数值字段的安全取值(字段可缺 / 可为 null)。 */
216
+ function statNumber(value) {
217
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
218
+ }
219
+ const RULES = [
220
+ /* 1. OOM */
221
+ {
222
+ code: 'oom-killed',
223
+ severity: 'critical',
224
+ test: (ctx) => ctx.detail.oomKilled,
225
+ title: () => '被 OOM 杀掉',
226
+ detail: (ctx) => {
227
+ const limit = ctx.limitText === '' ? '' : `(${ctx.limitText})`;
228
+ const code = ctx.detail.exitCode === null ? '' : `,退出码 ${String(ctx.detail.exitCode)}`;
229
+ return `进程被内核强制终止:内存用量打到上限${limit}后被系统杀掉${code}。`;
230
+ },
231
+ summary: () => '内存打到上限,容器被系统强制杀掉',
232
+ suggestions: () => [
233
+ '调高内存上限(docker update --memory 后重启容器)',
234
+ '排查内存泄漏:用 docker top 看进程常驻内存是否持续上涨',
235
+ '限制应用自己的堆 / 缓存大小(容器内存上限要留余量给运行时)',
236
+ ],
237
+ },
238
+ /* 2. 非零退出(OOM 已单独成条,不重复报) */
239
+ {
240
+ code: 'exit-nonzero',
241
+ severity: 'critical',
242
+ test: (ctx) => ctx.detail.exitCode !== null && ctx.detail.exitCode !== 0 && !ctx.detail.oomKilled,
243
+ title: (ctx) => `以非零退出码 ${String(ctx.detail.exitCode)} 结束`,
244
+ detail: (ctx) => {
245
+ const code = ctx.detail.exitCode ?? 0;
246
+ return `容器已退出,退出码 ${String(code)} —— ${exitMeaning(code)}。`;
247
+ },
248
+ summary: (ctx) => `容器以退出码 ${String(ctx.detail.exitCode)} 退出`,
249
+ suggestions: (ctx) => {
250
+ const code = ctx.detail.exitCode;
251
+ if (code === 126)
252
+ return ['检查入口脚本是否有执行权限(容器内 chmod +x)'];
253
+ if (code === 127)
254
+ return ['确认镜像里有要启动的可执行文件:命令名或路径写错了?'];
255
+ if (code === 137)
256
+ return ['先确认是不是 docker stop 主动停的;不是就按内存不足排查(看是否被 OOM 杀掉)'];
257
+ if (code === 143)
258
+ return ['确认是不是 docker stop / 部署流程主动停的'];
259
+ if (code === 139)
260
+ return ['看日志里崩溃前的堆栈:多为应用自身缺陷(空指针 / 段错误)'];
261
+ return ['用 docker_logs 看退出前最后的输出定位失败原因'];
262
+ },
263
+ },
264
+ /* 3. 反复重启 */
265
+ {
266
+ code: 'crash-loop',
267
+ severity: 'critical',
268
+ test: (ctx) => ctx.detail.state === 'restarting' || (ctx.detail.restartCount !== null && ctx.detail.restartCount >= CRASH_LOOP_RESTARTS),
269
+ title: () => '反复重启',
270
+ detail: (ctx) => {
271
+ const count = ctx.detail.restartCount;
272
+ const times = count === null ? '重启次数未知' : `已重启 ${String(count)} 次`;
273
+ if (ctx.detail.state === 'restarting')
274
+ return `容器正在反复重启(${times},此刻仍在重启中):启动后很快就退出,重启策略又在把它拉起来。`;
275
+ return `容器在反复重启(${times}):说明启动后很快就退出,只是还没轮到时看到它停着。`;
276
+ },
277
+ summary: (ctx) => {
278
+ const count = ctx.detail.restartCount;
279
+ return count === null ? '容器正在反复重启' : `反复重启(已重启 ${String(count)} 次)`;
280
+ },
281
+ suggestions: () => [
282
+ '看 docker_logs 里每次启动后立刻打出的报错(多为配置错误 / 依赖服务连不上)',
283
+ '先止血:把重启策略改成 no 停止重启风暴(docker update --restart no)',
284
+ ],
285
+ },
286
+ /* 4. 健康检查不通过 */
287
+ {
288
+ code: 'unhealthy',
289
+ severity: 'critical',
290
+ test: (ctx) => ctx.detail.health === 'unhealthy',
291
+ title: () => '健康检查不通过',
292
+ detail: (ctx) => {
293
+ const output = clip(ctx.detail.healthLogTail);
294
+ return output === '' ? '健康检查持续失败:探针一直没通过,服务对外可能已经不可用。' : `健康检查持续失败;最后一次输出:${output}。`;
295
+ },
296
+ summary: () => '健康检查持续失败,服务可能不可用',
297
+ suggestions: () => [
298
+ '在容器里手动跑一次健康检查命令,确认它本身是否可用',
299
+ '检查健康检查的间隔 / 超时 / 启动等待时间是否设得太紧',
300
+ '看 docker_logs 里健康检查前后的报错,区分「探针不通」与「服务真挂了」',
301
+ ],
302
+ },
303
+ /* 5. 健康检查进行中 */
304
+ {
305
+ code: 'health-starting',
306
+ severity: 'info',
307
+ test: (ctx) => ctx.detail.health === 'starting',
308
+ title: () => '健康检查进行中',
309
+ detail: () => '容器刚启动,健康检查还没得出结果(starting)。这是启动期的正常状态,不是故障。',
310
+ summary: () => '刚启动,健康检查还在进行',
311
+ suggestions: () => ['稍等一会儿再诊断一次,确认它转为 healthy'],
312
+ },
313
+ /* 6. 正常退出 */
314
+ {
315
+ code: 'stopped-ok',
316
+ severity: 'info',
317
+ test: (ctx) => ctx.detail.state === 'exited' && ctx.detail.exitCode === 0,
318
+ title: () => '已正常退出',
319
+ detail: (ctx) => {
320
+ const at = ctx.detail.finishedAt;
321
+ return `容器以退出码 0 结束${at === null ? '' : `(${at})`},属于正常退出,多半是手动停的或任务本来就该跑完。`;
322
+ },
323
+ summary: () => '容器已正常退出(退出码 0)',
324
+ suggestions: () => ['要它继续运行就 start 容器;一次性任务可以忽略'],
325
+ },
326
+ /* 7. 没在运行(created / paused / dead) */
327
+ {
328
+ code: 'not-running',
329
+ severity: 'warning',
330
+ test: (ctx) => ctx.detail.state === 'created' || ctx.detail.state === 'paused' || ctx.detail.state === 'dead',
331
+ title: (ctx) => `容器${STATE_LABEL[ctx.detail.state] ?? `处于 ${ctx.detail.state} 状态`}`,
332
+ detail: (ctx) => {
333
+ const label = STATE_LABEL[ctx.detail.state] ?? ctx.detail.state;
334
+ return `容器当前没有在运行:状态 ${ctx.detail.state}(${label})。`;
335
+ },
336
+ summary: (ctx) => `容器没有在运行(${STATE_LABEL[ctx.detail.state] ?? ctx.detail.state})`,
337
+ suggestions: (ctx) => {
338
+ if (ctx.detail.state === 'paused')
339
+ return ['容器被暂停了:恢复(unpause)后再看'];
340
+ if (ctx.detail.state === 'dead')
341
+ return ['容器已死亡:只能删除后重建(先确认数据卷还在)'];
342
+ return ['容器创建后还没启动:start 一下确认能不能起来'];
343
+ },
344
+ },
345
+ /* 8. 内存逼近上限(没设上限时不判:百分比的分母是宿主机内存,说「逼近上限」不成立) */
346
+ {
347
+ code: 'mem-pressure',
348
+ severity: 'warning',
349
+ test: (ctx) => {
350
+ const percent = statNumber(ctx.stats?.memPercent);
351
+ return percent !== null && percent >= MEM_PRESSURE_PERCENT && ctx.memoryLimitBytes !== null;
352
+ },
353
+ title: () => '内存接近上限',
354
+ detail: (ctx) => {
355
+ const percent = statNumber(ctx.stats?.memPercent);
356
+ const bytes = statNumber(ctx.stats?.memUsed);
357
+ const parts = [
358
+ percent === null ? '' : `内存已用 ${formatPercent(percent)}`,
359
+ ctx.limitText === '' ? '' : `上限 ${ctx.limitText}`,
360
+ bytes === null ? '' : `当前 ${formatBytes(bytes)}`,
361
+ ].filter((part) => part !== '');
362
+ return `${parts.join(',')}。再涨就会被系统杀掉(变成 OOM)。`;
363
+ },
364
+ summary: (ctx) => {
365
+ const percent = statNumber(ctx.stats?.memPercent);
366
+ return `内存已用 ${percent === null ? '?' : formatPercent(percent)}(上限 ${ctx.limitText === '' ? '?' : ctx.limitText})`;
367
+ },
368
+ suggestions: () => [
369
+ '调高内存上限,或降低并发 / 缓存大小',
370
+ '排查内存泄漏:用 docker top 看进程常驻内存是否持续上涨',
371
+ ],
372
+ },
373
+ /* 9. CPU 逼近占满 */
374
+ {
375
+ code: 'cpu-pressure',
376
+ severity: 'warning',
377
+ test: (ctx) => {
378
+ const percent = statNumber(ctx.stats?.cpuPercent);
379
+ return percent !== null && percent >= CPU_PRESSURE_PERCENT;
380
+ },
381
+ title: () => 'CPU 接近占满',
382
+ detail: (ctx) => {
383
+ const percent = statNumber(ctx.stats?.cpuPercent);
384
+ const limit = ctx.cpuQuota === null ? '' : `(上限 ${formatCpuLimit(ctx.cpuQuota)})`;
385
+ return `CPU 占用 ${percent === null ? '?' : formatPercent(percent)}${limit}。持续打满时请求会排队、健康检查也可能跟着超时。`;
386
+ },
387
+ summary: (ctx) => {
388
+ const percent = statNumber(ctx.stats?.cpuPercent);
389
+ return `CPU 已用 ${percent === null ? '?' : formatPercent(percent)}`;
390
+ },
391
+ suggestions: () => [
392
+ '用 docker top 看是哪个进程在吃 CPU:业务高峰还好,死循环要修',
393
+ '持续打满要给容器设 CPU 上限或扩容',
394
+ ],
395
+ },
396
+ /* 10. 日志里有报错 */
397
+ {
398
+ code: 'log-errors',
399
+ severity: 'info',
400
+ test: (ctx) => ctx.errorLines !== null && ctx.errorLines >= 1,
401
+ title: () => '日志里有报错',
402
+ detail: (ctx) => {
403
+ const first = clip(ctx.firstErrorLine);
404
+ const count = ctx.errorLines ?? 0;
405
+ return `最近抓取的日志里有 ${String(count)} 行疑似报错${first === '' ? '' : `;第一条:${first}`}。`;
406
+ },
407
+ summary: (ctx) => `日志里有 ${String(ctx.errorLines ?? 0)} 行疑似报错`,
408
+ suggestions: () => ['用 docker_logs_grep 带 pattern 检索完整报错上下文(本工具只抓尾部若干行)'],
409
+ },
410
+ /* 11. 没有健康检查(只在运行中才有意义:已退出的容器「探不到活」是废话) */
411
+ {
412
+ code: 'no-healthcheck',
413
+ severity: 'info',
414
+ test: (ctx) => ctx.detail.health === null && isRunning(ctx.detail.state),
415
+ title: () => '没有健康检查',
416
+ detail: () => '容器没有配置健康检查:进程活着不等于服务真的可用,出问题时只能靠日志与调用方报错判断。',
417
+ summary: () => '没有健康检查,无法判断服务是否可用',
418
+ suggestions: () => ['给镜像加 HEALTHCHECK,或让调用方做应用层探活'],
419
+ },
420
+ /*
421
+ * 12–14. 三路采集失败(`*-unavailable`)。
422
+ *
423
+ * 为什么必须有判据:没有它,「日志没采到」在 evidence 里只是一个 null,而 verdict
424
+ * 可能还是 running-ok——用户读到的是「一切正常」,排障方向当场被带偏。严重度是
425
+ * info(容器本身没坏,是这次诊断的证据不全),但**结论不再是 ok**。
426
+ */
427
+ {
428
+ code: 'logs-unavailable',
429
+ severity: 'info',
430
+ test: (ctx) => ctx.logText === null,
431
+ title: () => '本次没能取到日志',
432
+ detail: (ctx) => `日志采集失败${ctx.logError === null ? '' : `:${clip(ctx.logError)}`}。下面的结论不含日志证据,别当成「日志是空的」。`,
433
+ summary: () => '本次没能取到日志,结论不含日志证据',
434
+ suggestions: () => ['重试一次;仍然失败就用 docker_logs 单独读日志(它会给出具体原因)'],
435
+ },
436
+ {
437
+ code: 'events-unavailable',
438
+ severity: 'info',
439
+ test: (ctx) => ctx.eventCount === null,
440
+ title: () => '本次没能取到事件',
441
+ detail: (ctx) => `事件采集失败${ctx.eventError === null ? '' : `:${clip(ctx.eventError)}`},时间线为空不代表这段时间没发生过重启。`,
442
+ summary: () => '本次没能取到事件,时间线可能不完整',
443
+ suggestions: () => ['重试一次;仍然失败就用 docker_events 单独读事件(它会给出具体原因)'],
444
+ },
445
+ {
446
+ code: 'stats-unavailable',
447
+ severity: 'info',
448
+ test: (ctx) => ctx.stats === null,
449
+ title: () => '本次没能取到资源占用',
450
+ detail: (ctx) => `资源统计采集失败${ctx.statsError === null ? '' : `:${clip(ctx.statsError)}`},所以没有 CPU / 内存数据(容器已退出时取不到属正常)。`,
451
+ summary: () => '本次没能取到资源占用数据',
452
+ suggestions: () => ['容器要在运行中才有统计;在跑还取不到就用 docker_stats 单独取一次'],
453
+ },
454
+ ];
455
+ /**
456
+ * 纯函数入口:把已采好的四路数据判成一份诊断。
457
+ *
458
+ * 顺序稳定:findings 按 severity 降序,同级按上表的编号顺序;verdict 取最高 severity
459
+ * 的那条(同级取最靠前),一条都不命中且容器在运行时给 `running-ok`。
460
+ */
461
+ export function diagnose(input) {
462
+ const detail = input.detail;
463
+ const scan = input.logText === null ? { count: null, first: null } : scanErrorLines(input.logText);
464
+ const ctx = {
465
+ detail,
466
+ stats: input.stats,
467
+ logText: input.logText,
468
+ logError: typeof input.logError === 'string' && input.logError.trim() !== '' ? input.logError.trim() : null,
469
+ eventError: typeof input.eventError === 'string' && input.eventError.trim() !== '' ? input.eventError.trim() : null,
470
+ statsError: typeof input.statsError === 'string' && input.statsError.trim() !== '' ? input.statsError.trim() : null,
471
+ errorLines: scan.count,
472
+ firstErrorLine: scan.first,
473
+ eventCount: input.events === null ? null : input.events.length,
474
+ memoryLimitBytes: input.memoryLimitBytes,
475
+ cpuQuota: input.cpuQuota,
476
+ limitText: input.memoryLimitBytes === null ? '' : formatBytes(input.memoryLimitBytes),
477
+ };
478
+ const matched = [];
479
+ RULES.forEach((rule, order) => {
480
+ if (!rule.test(ctx))
481
+ return;
482
+ matched.push({
483
+ rule,
484
+ order,
485
+ finding: { code: rule.code, severity: rule.severity, title: rule.title(ctx), detail: rule.detail(ctx) },
486
+ });
487
+ });
488
+ matched.sort((a, b) => SEVERITY_ORDER[a.finding.severity] - SEVERITY_ORDER[b.finding.severity] || a.order - b.order);
489
+ const findings = matched.map((row) => row.finding);
490
+ const verdict = matched.length > 0
491
+ ? {
492
+ severity: matched[0].finding.severity,
493
+ code: matched[0].finding.code,
494
+ summary: matched[0].rule.summary(ctx),
495
+ }
496
+ : isRunning(detail.state)
497
+ ? { severity: 'ok', code: 'running-ok', summary: '容器在运行,未发现明确问题' }
498
+ : { severity: 'ok', code: 'ok', summary: '未发现明确问题' };
499
+ const suggestions = [];
500
+ for (const row of matched) {
501
+ for (const item of row.rule.suggestions(ctx)) {
502
+ if (suggestions.length >= MAX_SUGGESTIONS)
503
+ break;
504
+ if (item.trim() === '' || suggestions.includes(item))
505
+ continue;
506
+ suggestions.push(item);
507
+ }
508
+ if (suggestions.length >= MAX_SUGGESTIONS)
509
+ break;
510
+ }
511
+ return {
512
+ id: detail.id,
513
+ name: detail.name,
514
+ verdict,
515
+ findings,
516
+ evidence: {
517
+ state: detail.state,
518
+ status: containerStatusText(detail, input.nowMs),
519
+ health: detail.health,
520
+ // 空串归一成 null(可缺字段给 null,客户端据此渲染 `—`):parseInspectJson 对
521
+ // 「有健康检查但从未输出过」给的是 '',与「没有这条记录」在这里是同一种「没东西可看」。
522
+ healthLastOutput: detail.healthLogTail === '' ? null : detail.healthLogTail,
523
+ exitCode: detail.exitCode,
524
+ oomKilled: detail.oomKilled,
525
+ restartCount: detail.restartCount,
526
+ startedAt: detail.startedAt,
527
+ finishedAt: detail.finishedAt,
528
+ memoryLimitBytes: input.memoryLimitBytes,
529
+ cpuQuota: input.cpuQuota,
530
+ logLines: input.logLines,
531
+ errorLines: scan.count,
532
+ eventCount: ctx.eventCount,
533
+ cpuPercent: input.stats === null ? null : input.stats.cpuPercent,
534
+ memBytes: input.stats === null ? null : input.stats.memUsed,
535
+ memPercent: input.stats === null ? null : input.stats.memPercent,
536
+ },
537
+ timeline: buildTimeline(input.events),
538
+ logTail: input.logText ?? '',
539
+ suggestions,
540
+ };
541
+ }
542
+ /** 时间线:按 Unix 秒**升序**,`at` 转 ISO 8601;没有时间的事件排最前(信息仍在,不丢)。 */
543
+ function buildTimeline(events) {
544
+ if (events === null)
545
+ return [];
546
+ return events
547
+ .map((event) => ({
548
+ sort: event.time ?? 0,
549
+ entry: { at: eventTimeIso(event.time), kind: event.action, text: timelineText(event) },
550
+ }))
551
+ .sort((a, b) => a.sort - b.sort)
552
+ .map((row) => row.entry);
553
+ }
554
+ /** 扫疑似报错行:返回行数与第一条命中行(原文,截断交给调用处)。 */
555
+ function scanErrorLines(text) {
556
+ if (text === '')
557
+ return { count: 0, first: null };
558
+ let count = 0;
559
+ let first = null;
560
+ for (const line of text.split('\n')) {
561
+ if (line.trim() === '')
562
+ continue;
563
+ if (!ERROR_LINE_RE.test(line))
564
+ continue;
565
+ count += 1;
566
+ if (first === null)
567
+ first = line;
568
+ }
569
+ return { count, first };
570
+ }
571
+ //# sourceMappingURL=diagnose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../src/diagnose.ts"],"names":[],"mappings":"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"}