微信小程序页面迁移校验之前 P5任务处理之前
This commit is contained in:
130
apps/admin-web/src/utils/taskLogParser.ts
Normal file
130
apps/admin-web/src/utils/taskLogParser.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* 任务日志解析与分组工具函数。
|
||||
*
|
||||
* 解析 TaskLogBuffer 输出的日志格式:[TASK_CODE] timestamp level message
|
||||
* 将扁平日志行按任务代码分组,提取时间线信息。
|
||||
*/
|
||||
|
||||
/** 单条解析后的日志条目 */
|
||||
export interface ParsedLogEntry {
|
||||
/** 原始行文本 */
|
||||
raw: string;
|
||||
/** 任务代码(如 ODS_MEMBER) */
|
||||
taskCode: string;
|
||||
/** 时间戳字符串(原始格式) */
|
||||
timestamp: string;
|
||||
/** 日志级别:INFO / WARNING / ERROR / DEBUG */
|
||||
level: string;
|
||||
/** 日志消息正文 */
|
||||
message: string;
|
||||
}
|
||||
|
||||
/** 按任务分组后的日志集合 */
|
||||
export interface TaskLogGroup {
|
||||
taskCode: string;
|
||||
entries: ParsedLogEntry[];
|
||||
/** 该任务第一条日志的时间戳 */
|
||||
startTime: string | null;
|
||||
/** 该任务最后一条日志的时间戳 */
|
||||
endTime: string | null;
|
||||
/** 推断的任务状态:success / failed / running / unknown */
|
||||
status: "success" | "failed" | "running" | "unknown";
|
||||
/** 各级别日志计数 */
|
||||
counts: { info: number; warning: number; error: number; debug: number };
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配 TaskLogBuffer 输出格式:[TASK_CODE] 2024-01-01 12:00:00 INFO 消息内容
|
||||
* 也兼容:[TASK_CODE] 2024-01-01 12:00:00,123 INFO 消息内容
|
||||
*/
|
||||
const LOG_LINE_REGEX =
|
||||
/^\[([A-Z][A-Z0-9_]*)\]\s+(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}(?:[.,]\d+)?)\s+(DEBUG|INFO|WARNING|ERROR|CRITICAL)\s+(.*)$/;
|
||||
|
||||
/**
|
||||
* 解析单行日志。无法解析时返回 null。
|
||||
*/
|
||||
export function parseLogLine(line: string): ParsedLogEntry | null {
|
||||
const match = LOG_LINE_REGEX.exec(line.trim());
|
||||
if (!match) return null;
|
||||
return {
|
||||
raw: line,
|
||||
taskCode: match[1],
|
||||
timestamp: match[2],
|
||||
level: match[3],
|
||||
message: match[4],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 将日志行数组按任务代码分组。
|
||||
* 无法解析的行归入 "_UNKNOWN" 分组。
|
||||
*/
|
||||
export function groupLogsByTask(lines: string[]): TaskLogGroup[] {
|
||||
const groupMap = new Map<string, ParsedLogEntry[]>();
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line.trim()) continue;
|
||||
const parsed = parseLogLine(line);
|
||||
const code = parsed?.taskCode ?? "_UNKNOWN";
|
||||
const entry: ParsedLogEntry = parsed ?? {
|
||||
raw: line,
|
||||
taskCode: "_UNKNOWN",
|
||||
timestamp: "",
|
||||
level: "INFO",
|
||||
message: line,
|
||||
};
|
||||
const arr = groupMap.get(code);
|
||||
if (arr) {
|
||||
arr.push(entry);
|
||||
} else {
|
||||
groupMap.set(code, [entry]);
|
||||
}
|
||||
}
|
||||
|
||||
const groups: TaskLogGroup[] = [];
|
||||
for (const [taskCode, entries] of groupMap) {
|
||||
const counts = { info: 0, warning: 0, error: 0, debug: 0 };
|
||||
for (const e of entries) {
|
||||
const lvl = e.level.toLowerCase();
|
||||
if (lvl === "info") counts.info++;
|
||||
else if (lvl === "warning" || lvl === "critical") counts.warning++;
|
||||
else if (lvl === "error") counts.error++;
|
||||
else if (lvl === "debug") counts.debug++;
|
||||
}
|
||||
|
||||
// 推断状态:有 ERROR 级别 → failed;否则看最后一条消息
|
||||
let status: TaskLogGroup["status"] = "unknown";
|
||||
if (counts.error > 0) {
|
||||
status = "failed";
|
||||
} else if (entries.length > 0) {
|
||||
const lastMsg = entries[entries.length - 1].message.toLowerCase();
|
||||
if (lastMsg.includes("完成") || lastMsg.includes("success") || lastMsg.includes("finished")) {
|
||||
status = "success";
|
||||
}
|
||||
}
|
||||
|
||||
const timestamps = entries.map((e) => e.timestamp).filter(Boolean);
|
||||
groups.push({
|
||||
taskCode,
|
||||
entries,
|
||||
startTime: timestamps[0] ?? null,
|
||||
endTime: timestamps.length > 0 ? timestamps[timestamps.length - 1] : null,
|
||||
status,
|
||||
counts,
|
||||
});
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按任务代码过滤分组。空关键词返回全部。
|
||||
*/
|
||||
export function filterTaskGroups(
|
||||
groups: TaskLogGroup[],
|
||||
keyword: string,
|
||||
): TaskLogGroup[] {
|
||||
const kw = keyword.trim().toUpperCase();
|
||||
if (!kw) return groups;
|
||||
return groups.filter((g) => g.taskCode.toUpperCase().includes(kw));
|
||||
}
|
||||
Reference in New Issue
Block a user