ecFlow笔记:ecFlow日志解析 - 通用字段

目录

本文属于介绍 NWPC 工作流日志工具的系列文章。

上一篇文章《ecFlow笔记:ecFlow日志分类》介绍 ecFlow 日志的几种常见类型。 本文介绍如何解析日志条目的通用字段。

本文代码均来自 nwpc-oper/nwpc-workflow-log-model 项目。

通用结构

ecFlow 日志条目有相似的结构。

下面是 4 种主要类型的日志条目示例,并用不同的颜色区分不同的字段。

ecFlow 日志字段结构示例

可以看到,所有条目的开头都有相同格式,包含日志级别(Log type / Log level)和时间(Datetime)两个字段。 而不同类型的日志由 Command(Event Type)字段区分。 大部分日志包含节点路径(Node path)。 少部分日志包含与命令相关的附加信息(Additional Information)。

ecFlow 日志条目的通用对象包含如下字段:

  • 日志级别(Log Type)
  • 日期(Date)
  • 时间(Time)
  • 日志事件(Event)
  • 节点路径(Node Path)
  • 附加信息(Additional Information)

不同类型的日志对象可有自己特定的字段。 如下图所示

ecFlow 日志条目对象

通用解析

ecFlow 的所有日志,都以日志层次和时间开头。所以解析日志时首先寻找 : 符号,获取日志层次;再寻找 ] 符号,获取日志的日期和时间。

然后根据 ] 后续的少量字符来判断日志的类型。

] 后面如果有一个空格,表明条目是状态变化记录。例如

LOG:[17:24:11 8.6.2020]  complete: /grapes_tym/grapes_d01/12/prods/plot/plot_036

] 后面是 chd:,表明条目是 child 命令记录。例如

MSG:[17:24:11 8.6.2020] chd:complete /grapes_tym/grapes_d01/12/prods/plot/plot_036

] 后面是 --,表明条目是 client 命令记录。例如

MSG:[17:24:11 8.6.2020] --sync=0 3804359 182  :nwp_pd

] 后面是 svr:,表明条目是服务端记录。例如

MSG:[17:25:17 8.6.2020] svr:check_pt in 0 seconds

根据日志类型,再执行与其相关的解析。

整个解析过程如下图所示:

ecFlow 日志条目通用解析

目前 NWPC 工作流日志工具只支持上述 4 种类型的日志解析,其余日志会被忽略。

实现

请参考 nwpc-workflow-log-model 项目的 EcflowLogParser 类的 parse 函数

以下代码来自该函数,其中 self 表示 EcflowLogParser 类,line 是日志条目字符串。

日志层次

搜索 :,获取日志层次字符串,并使用 _parse_log_type 函数转换。

log_record = EcflowLogRecord(log_record=line)
start_pos = 0
end_pos = line.find(":")
log_type_token = line[start_pos:end_pos]
log_type = self._parse_log_type(log_type_token)
log_record.log_type = log_type

时间戳

继续搜索 ],获取日期时间字符串。

start_pos = end_pos + 2
end_pos = line.find("]", start_pos)
if end_pos == -1:
    logger.warning(f"can't find date and time => {line}")
    return None
date_time_token = line[start_pos:end_pos]

注意:这里没有立即解析时间戳,因为解析时间比较耗时,如果日志条目被忽略,解析时间会造成资源浪费。

判断日志类型

根据后续 1 - 4 位字符判断日志类型。下面代码省略具体的解析步骤。

start_pos = end_pos + 2
if line[start_pos: start_pos + 1] == " ":
    # status event
    pass
elif line[start_pos: start_pos + 2] == "--":
    # client event
    pass
elif line[start_pos: start_pos + 4] == "chd:":
    # child event
    pass
elif line[start_pos: start_pos + 4] == "svr:":
    # server event
    # MSG:[05:41:25 2.2.2020] svr:check_pt in 0 seconds
    pass
else:
    # other
    pass

调用类型相关解析

使用具体的日志条目对象,解析提取过日志层次和时间戳后剩余的字符串。

date_time = self._parse_datetime(date_time_token)
log_record = StatusLogRecord(
    log_type=log_type,
    date=date_time.date(),
    time=date_time.time(),
    log_record=line,
)
start_pos += 1
log_record.parse_record(
    line[start_pos:],
    debug=self.options[EventType.Status]["debug"],
)
return log_record

后续文章会详细介绍各个类型的解析,这里仅作简要说明。

参考

nwpc-oper/nwpc-workflow-log-model