ecFlow笔记:ecFlow日志解析 - child 命令记录

目录

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

之前的文章《ecFlow笔记:ecFlow日志解析 - 通用字段》介绍如何解析 ecFlow 日志的通用字段。

本文介绍如何解析 child 命令记录(ChildLogRecord)类型的 ecFlow 日志条目。

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

介绍

ecFlow 服务并不负责监控任务的运行状态,而是要求任务自身将运行状态告知给 ecFlow 服务,这就需要使用到 child 命令。

child 命令是 ecflow_client 的一组子命令,主要用于实现任务脚本与 ecFlow 服务之间的通讯,修改 ecFlow 服务中与某个任务节点相关的属性。

目前,NWPC 的数值预报业务系统中使用的 child 命令主要包括以下两种类型:

  • 修改任务节点状态:initcompleteabort,命令调用不需要额外的参数,全部由环境变量指定
  • 修改任务节点的属性子节点:eventmeterlabel,任务节点可能有多个同一类的属性子节点,所以命令调用时需要指定属性的名称

child 命令示意图如下所示:

child 命令记录

示例

下面举例说明各个命令的日志。

init

init 命令用于告知 ecFlow 服务任务已实际开始运行。 执行 init 命令后,节点状态会变为 active

MSG:[13:25:26 14.5.2020] chd:init /grapes_emer_v1_2/00_2/upload/upload_plot_ty
LOG:[13:25:26 14.5.2020]  active: /grapes_emer_v1_2/00_2/upload/upload_plot_ty

complete

complete 命令用于告知 ecFlow 服务任务已经正常结束。 执行 complete 命令后,节点状态会变为 complete

MSG:[13:25:27 14.5.2020] chd:complete /grapes_emer_v1_2/00_2/typhoon/check_plot_typhoon
LOG:[13:25:27 14.5.2020]  complete: /grapes_emer_v1_2/00_2/typhoon/check_plot_typhoon

abort

abort 命令用于告知 ecFlow 服务任务运行出错。调用 abort 命令是可以附带出错原因。 执行 abort 命令后,节点状态会变为 aborted

如果任务节点配置了自动重新运行,那么 ecFlow 会根据当前的 try no 确定是否自动重新提交该任务。

MSG:[23:13:17 14.5.2020] chd:abort /meso_post/21/uploadAll/upload_chartos/3h/conv_prep_3hr/upload_conv_prep_3hr_011  trap
LOG:[23:13:17 14.5.2020]  aborted: /meso_post/21/uploadAll/upload_chartos/3h/conv_prep_3hr/upload_conv_prep_3hr_011 try-no: 1 reason: trap

event

event 命令设置属于某个节点的事件,一般用于触发后续任务。

ecFlow 日志仅记录 event 命令的执行记录。

MSG:[23:13:18 14.5.2020] chd:event grapes_postvar_019 /grapes_meso_3km_post/18/initial

meter

meter 命令用于修改属于某个节点的标尺的值,一般用于指示任务执行进度,并触发后续任务。

ecFlow 日志仅记录 meter 命令的执行记录。

MSG:[23:18:44 14.5.2020] chd:meter progress 70 /meso_post/21/meso_chartos/rundir_area_diag1/diag1_grapes_meso_reg_850_div_wind/diag1_grapes_meso_reg_850_div_wind_sep_022

label

label 命令用于修改属于某个节点的标签内容,一般用于向运维人员提供额外消息。

ecFlow 日志仅记录 label 命令的执行记录。

MSG:[23:18:39 14.5.2020] chd:label info 'checking for 009...' /gmf_grapes_gfs_post/18/initial_togrib2

结构

child 命令记录(ChildLogRecord)的结构继承自通用日志结构(EcflowLogRecord), 将 Event 字段设置为状态变化 EventType.Child。 同时增加命令(Command)字段,记录执行的命令。 对于不同的命令,在附加信息(Additional Information)字段中会记录额外的信息,例如:Abort 命令记录出错原因,Meter 命令记录标尺名称和值。

child 命令记录的结构

解析

在经过通用解析后,从 command 字段中提取 child 命令设置为命令字段(Command)。 并根据命令进行相应的解析。

对于 init 和 complete 两种每个命令,仅需解析节点路径。

对于 aborted,event,meter 和 label 几种命令,在解析节点路径基础上,还需解析附加信息。

其他情况的条目直接被忽略。

child 命令记录的解析

实现

请参考 nwpc-workflow-log-model 项目的 ChildLogRecord 类的 parse_record 函数

以下代码来自该函数,其中 self 表示 EcflowLogParser 类,line 是解析过通用字段后剩余的日志条目字符串。即

label info 'checking for 009...' /gmf_grapes_gfs_post/18/initial_togrib2

获取命令

查找 " ",获取命令

start_pos = 0
end_pos = line.find(" ", start_pos)
if end_pos == -1:
    if debug:
        logger.error(f"[ERROR] child record: event not found => {self.log_record}")
    return
event = line[start_pos:end_pos]
self.event = event
self.command = self.event

init/complete/abort

这三种命令都修改节点的状态,abort 命令会附带出错原因字段

start_pos = end_pos + 1
end_pos = line.find(" ", start_pos)
if end_pos == -1:
    # MSG:[08:17:04 29.6.2018] chd:complete /gmf_grapes_025L60_v2.2_post/18/typhoon/post/tc_post
    self.node_path = line[start_pos:].strip()
else:
    # MSG:[12:22:53 19.10.2018] chd:abort /3km_post/06/3km_togrib2/grib2WORK/030/after_data2grib2_030  trap
    self.node_path = line[start_pos:end_pos]
    self.additional_attrs["reason"] = line[end_pos + 1:]

event

event 命令包含名称和节点路径,均由 " " 分割

start_pos = end_pos + 1
line = line[start_pos:]
tokens = line.split(" ")
if len(tokens) == 2:
    self.node_path = tokens[1]
    self.additional_attrs["name"] = tokens[0]

meter

meter 命令包含名称,值和节点路径,均由 " " 分割

start_pos = end_pos + 1
line = line[start_pos:]
tokens = line.split(" ")
if len(tokens) == 3:
    self.node_path = tokens[2]
    self.additional_attrs["name"] = tokens[0]
    self.additional_attrs["value"] = int(tokens[1])

label

label 命令包含名称,值和节点路径,均由 " " 分割

start_pos = end_pos + 1
line = line[start_pos:]
line = line.rstrip()
name_end_pos = line.find(" ")
self.additional_attrs["name"] = line[:name_end_pos]
node_start_pos = line.rfind(" ")
self.node_path = line[node_start_pos+1:]
self.additional_attrs["value"] = line[name_end_pos+2: node_start_pos-1]

参考

项目:

nwpc-oper/nwpc-workflow-log-model