失敗したタスクの情報をdigdagコマンドとシェルスクリプトで取得する

失敗した attempt の ID まで分かっていて、その attempt の失敗したタスクについて ID やタスク名を知りたい。


find_failed_task.sh

#!/bin/bash

buf=""
found="false"
count=

# 標準入力から読む
while IFS= read -r line; do
  if [ "$line" = "" ]; then
    if [ "$found" = "true" ]; then
      printf "${buf}\n"
      exit
    fi
    buf=""
  else
    if [ "$buf" != "" ]; then
      buf="${buf}\n"
    fi
    buf="${buf}${line}"
  fi

  if [ "$line" = "   state: error" ]; then
    found=true
  fi
done

# echo "no error" >&2
exit 1

使い方と出力例:

$ digdag tasks 18 | ./find_failed_task.sh
2020-06-04 20:49:23 +0900: Digdag v0.9.39 ... これは標準エラー出力に出ている
   id: 134
   name: +wf_test+task3
   state: error
   started: 2020-06-04 20:00:03 +0900
   updated: 2020-06-04 20:00:04 +0900
   config: {"sh>":"exit 1"}
   parent: 127
   upstreams: [131]
   export params: {}
   store params: {}
   state params: {}

たとえばタスク名だけ欲しければ下記のような感じで。

$ digdag tasks 18 | ./find_failed_task.sh \
  | grep '^   name: ' | sed -e 's/^   name: //'
2020-06-04 20:53:18 +0900: Digdag v0.9.39
+wf_test+task3

追記 2020-06-06

とりあえずちゃんと動いてるっぽいしまあいいかという感じだったのですが、なんかこう、手続き的すぎてシェルスクリプトっぽくないというか……などと思って別解を考えてみました。

それと、上のスクリプトは失敗するタスクが1つだけという想定で書いてましたが、たとえば次のように並列に実行している部分があると複数のタスクが失敗する場合があります。

+task:
  _parallel: true
  +sub1:
    sh>: exit 1
  +sub2:
    sh>: exit 1

なので、複数の場合にも対応しておきます。 なんだかシェルスクリプトの練習問題みたいになってきましたね。

#!/bin/bash

# ti: task index

add_ti(){
  local ti=0

  while IFS= read -r line; do
    if [ "$line" = "" ]; then
      ti=$(($ti + 1))
    else
      echo "${ti}:${line}"
    fi
  done
}

# 標準入力から読む
# 前後の行を少し多めに抽出する
tmp="$(
  add_ti | egrep -C 20 '^[0-9]+: +state: error$'
)"

failed_tis=$(
  echo "$tmp" | egrep '^[0-9]+: +state: error$' | cut -d ':' -f 1
)
if [ "$failed_tis" = "" ]; then
  # echo "no error" >&2
  exit 1
fi

for failed_ti in $failed_tis; do
  echo "$tmp" | egrep "^${failed_ti}:"
done

使い方と出力例:

$ digdag tasks 62 | ./select_failed_tasks.sh
8:   id: 535
8:   name: +wf_test+task3+sub5
8:   state: error
8:   started: 2020-06-06 13:17:38 +0900
8:   updated: 2020-06-06 13:17:38 +0900
8:   config: {"sh>":"exit 1"}
8:   parent: 534
8:   upstreams: []
8:   export params: {}
8:   store params: {}
8:   state params: {}
12:   id: 539
12:   name: +wf_test+task3+sub9
12:   state: error
12:   started: 2020-06-06 13:17:38 +0900
12:   updated: 2020-06-06 13:17:38 +0900
12:   config: {"sh>":"exit 1"}
12:   parent: 534
12:   upstreams: []
12:   export params: {}
12:   store params: {}
12:   state params: {}

あとは同様に grep なり sed なりで適当に。

コマンド&パイプな処理で対応しづらいのは上記でいえば add_ti() なので、 この部分を共通処理として切り出しておくと他のサブコマンドでも使えて便利かもしれません。