ecFlow笔记:ecFlow日志解析 - 状态变化记录

目录

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

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

本文介绍如何解析状态变化记录(StatusLogRecord)类型的 ecFlow 日志条目。

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

介绍

ecFlow 实现工作流的核心机制就是跟踪任务(Task)节点的状态,并定时根据状态决定工作流应采取的下一步动作。

正常情况下,ecFlow 任务的正常状态变化如下:

排队(queued)-> 提交(submitted)-> 运行(active)-> 完成(complete)

当出错时,节点会进入出错(aborted)状态。另外, 节点也可以被挂起(suspended),阻止任务运行。

ecFlow 中任务(Task)节点的状态变化

节点状态的每次变化,都会在 ecFlow 日志中记录相应的条目。 容器节点(Family 和 Suite)的状态是其所有子节点的状态种类中权重最大的状态。 所以 Task 节点状态变化通常会导致一系列父节点状态改变。 表现在日志中就是有一串关联的节点状态同时改变,如下所示

MSG:[11:08:52 3.6.2020] chd:init /grapes_tym/grapes_d01/06/prods/grib2/grib2_003
LOG:[11:08:52 3.6.2020]  active: /grapes_tym/grapes_d01/06/prods/grib2/grib2_003
LOG:[11:08:52 3.6.2020]  active: /grapes_tym/grapes_d01/06/prods/grib2
LOG:[11:08:52 3.6.2020]  active: /grapes_tym/grapes_d01/06/prods

权重列表如下,其中最后两个状态仅限于 ecFlow 服务节点。

状态说明
Unknown权重最小
Complete
Queued
Submitted
Active
Suspend
Aborted对于 task 是最重要的状态
Shutdown仅限于 ecFlow 服务节点
Halted最重要的状态,仅限于 ecFlow 服务节点

日志示例

下面举例说明各个状态的日志。

排队(queued)

通常情况下,queued 是任务的默认状态。 当系统中最后一个任务完成时,系统会自动滚动到下一天,并将所有任务的状态设为 queued。

下面示例中 /NWP_HAZE_ext_v3.2/housekeep/housekeeping 任务完成后,NWP_HAZE_ext_v3.2 系统的所有任务都已完成,ecFlow 会自动将所有的节点设置为 queued。

MSG:[23:45:04 22.5.2020] chd:complete /NWP_HAZE_ext_v3.2/housekeep/housekeeping
LOG:[23:45:04 22.5.2020]  complete: /NWP_HAZE_ext_v3.2/housekeep/housekeeping
LOG:[23:45:04 22.5.2020]  complete: /NWP_HAZE_ext_v3.2/housekeep
LOG:[23:45:04 22.5.2020]  complete: /NWP_HAZE_ext_v3.2
LOG:[23:45:04 22.5.2020]  queued: /NWP_HAZE_ext_v3.2
LOG:[23:45:04 22.5.2020]  queued: /NWP_HAZE_ext_v3.2/00
LOG:[23:45:04 22.5.2020]  queued: /NWP_HAZE_ext_v3.2/00/regridder
LOG:[23:45:04 22.5.2020]  queued: /NWP_HAZE_ext_v3.2/00/interpf
LOG:[23:45:04 22.5.2020]  queued: /NWP_HAZE_ext_v3.2/00/fcst
LOG:[23:45:04 22.5.2020]  queued: /NWP_HAZE_ext_v3.2/00/fcstmonitor

提交(submitted)

提交(submitted)和运行(active)都表示任务开始运行,但具体含义不同。

submitted 表示 ecFlow 服务执行任务运行命令(由 ECF_JOB_CMD 定义),状态改变由 ecFlow 服务直接完成。但如果将作业提交到类似 Slurm 的作业调度系统,那么执行命令后,任务不一定立即运行。

所以,任务在开始运行时需要使用 ecflow_client --init 命令告诉 ecFlow 服务自己已经开始运行,也就是将节点状态变为 active。

submitted 与 active 状态的区别与关联见下图。

submitted 与 active 状态的关系

在 ecFlow 日志中,submitted 状态没有相关的 child 命令记录。如下所示:

LOG:[04:10:00 31.5.2020]  submitted: /mosaic_v3/03/get job_size:8151
LOG:[04:10:00 31.5.2020]  submitted: /mosaic_v3/03
LOG:[04:10:00 31.5.2020]  submitted: /mosaic_v3
LOG:[04:10:00 31.5.2020]  submitted: /

运行(active)

运行(active)表示任务已实际开始运行。日志如下所示:

MSG:[04:10:01 31.5.2020] chd:init /mosaic_v3/03/get
LOG:[04:10:01 31.5.2020]  active: /mosaic_v3/03/get
LOG:[04:10:01 31.5.2020]  active: /mosaic_v3/03
LOG:[04:10:01 31.5.2020]  active: /mosaic_v3
LOG:[04:10:01 31.5.2020]  active: /

完成(complete)

完成(complete)表示任务运行结束。 通常来自任务脚本执行的 ecflow_client --complete 命令。

MSG:[01:30:03 4.6.2020] chd:complete /env_grib_pi_v1_0/env_grib_pi/GMF_ENV/gmf/housekeep
LOG:[01:30:03 4.6.2020]  complete: /env_grib_pi_v1_0/env_grib_pi/GMF_ENV/gmf/housekeep
LOG:[01:30:03 4.6.2020]  complete: /env_grib_pi_v1_0/env_grib_pi/GMF_ENV/gmf
LOG:[01:30:03 4.6.2020]  complete: /env_grib_pi_v1_0/env_grib_pi/GMF_ENV

也可能来自用户执行强制设为完成(force complete)操作。

MSG:[00:32:59 4.6.2020] --force=complete recursive /grapes_emer_v1_2/12_3  :nwp
LOG:[00:32:59 4.6.2020]  complete: /grapes_emer_v1_2/12_3
LOG:[00:32:59 4.6.2020]  complete: /grapes_emer_v1_2/12_3/typhoon
LOG:[00:32:59 4.6.2020]  complete: /grapes_emer_v1_2/12_3/typhoon/tcreport_get

或者节点的默认状态就是 complete,在系统进入下一天的循环时,会自动将该节点设置为 complete 状态。

LOG:[02:01:47 3.6.2020]  queued: /meso_post/06/meso_chartos/rundir_area_3h/area_grapes_meso_conv_prep_v2/area_grapes_meso_conv_prep_v2_sep_030
LOG:[02:01:47 3.6.2020]  queued: /meso_post/06/meso_chartos/rundir_area_6h
LOG:[02:01:47 3.6.2020]  complete: /meso_post/06/meso_chartos/rundir_area_6h
LOG:[02:01:47 3.6.2020]  queued: /meso_post/06/meso_chartos/housekeep_chartos

出错(aborted)

出错(aborted)状态表示任务运行出错,需要运维人员额外关注,在 ecflow_ui 界面中会弹出提示窗口。

通常情况下,aborted 状态由任务脚本执行 ecflow_client --aborted [+reason] 命令而触发。 日志会记录任务的运行序号和出错的原因。NWPC 业务系统脚本中出错原因均设为 trap

MSG:[05:20:57 19.5.2020] chd:abort /meso_post/03/uploadAll/upload_chartos/3h/prep_3hr/upload_prep_3hr_020  trap
LOG:[05:20:57 19.5.2020]  aborted: /meso_post/03/uploadAll/upload_chartos/3h/prep_3hr/upload_prep_3hr_020 try-no: 1 reason: trap
LOG:[05:20:57 19.5.2020]  aborted: /meso_post/03/uploadAll/upload_chartos/3h/prep_3hr
LOG:[05:20:57 19.5.2020]  aborted: /meso_post/03/uploadAll/upload_chartos/3h
LOG:[05:20:57 19.5.2020]  aborted: /meso_post/03/uploadAll/upload_chartos
LOG:[05:20:57 19.5.2020]  aborted: /meso_post/03/uploadAll
LOG:[05:20:57 19.5.2020]  aborted: /meso_post/03
LOG:[05:20:57 19.5.2020]  aborted: /meso_post
LOG:[05:20:57 19.5.2020]  aborted: /

也可能来自用户执行的 kill 命令。

MSG:[00:20:26 29.5.2020] --kill /grapes_tym_post/18/data/000/shanxi  :nwp_pd
MSG:[00:20:26 29.5.2020] --force=aborted /grapes_tym_post/18/data/000/shanxi  :nwp_pd
LOG:[00:20:26 29.5.2020]  aborted: /grapes_tym_post/18/data/000/shanxi try-no: 1 reason: 

或者来自用户执行强制设置 aborted 状态的操作

MSG:[01:30:52 12.6.2020] --force=aborted /grapes_tym_post/18/data/000/shanxi  :nwp_pd
LOG:[01:30:52 12.6.2020]  aborted: /grapes_tym_post/18/data/000/shanxi try-no: 2 reason: 
LOG:[01:30:52 12.6.2020]  aborted: /grapes_tym_post/18/data/000
LOG:[01:30:52 12.6.2020]  aborted: /grapes_tym_post/18/data
LOG:[01:30:52 12.6.2020]  aborted: /grapes_tym_post/18
LOG:[01:30:52 12.6.2020]  aborted: /grapes_tym_post
LOG:[01:30:52 12.6.2020]  aborted: /

挂起(suspended)

挂起(suspended)状态用于阻止任务执行。 不过笔者发现日志中仅有 --suspend 命令的记录,而没有 suspended 状态的条目,暂不给出示例。

结构

状态变化记录(StatusLogRecord)的结构继承自通用日志结构(EcflowLogRecord), 将 Event 字段设置为状态变化 EventType.Status。 同时增加状态(Status)字段,记录变化后的状态。 对于不同的状态,在附加信息(Additional Information)字段中会记录额外的信息,例如:submitted 状态记录作业脚本大小,aborted 状态记录出错原因。

StatusLogRecord 结构

解析

在经过通用解析后,将 command 字段设置为状态字段(Status)。 并根据状态值进行相应的解析。

对于 queued,active 和 complete 三种状态,仅需解析节点路径。

对于 aborted 和 submitted 两种状态,在解析节点路径基础上,还需解析额外信息。

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

状态变化日志(StatusLogRecord)解析

实现

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

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

complete: /env_grib_pi_v1_0/env_grib_pi/GMF_ENV/gmf/housekeep

获取状态

查找 :,获取状态

start_pos = 0
end_pos = status_line.find(":", start_pos)
event = status_line[start_pos:end_pos]
self.event = event
self.status = NodeStatus[event]

获取节点路径

查找 " ",获取节点路径

start_pos = end_pos + 2
end_pos = status_line.find(" ", start_pos)
self.node_path = status_line[start_pos:].strip()

获取附加信息

如果 event == "aborted"

self.additional_attrs["reason"] = status_line[end_pos + 1:]

如果 event == "submitted"

if end_pos == -1:
    self.node_path = status_line[start_pos:]
else:
    self.node_path = status_line[start_pos:end_pos]
    start_pos = end_pos + 1
    end_pos = status_line.find(":", start_pos)

参考

ecFlow 官方文档:

Status of a task

Status of a suite,family or server

项目:

nwpc-oper/nwpc-workflow-log-model