タスク実行時間超過の検出方法について

お世話になります。

zabbixを利用してタスク実行の想定時間を超えた場合に警告を出したいのですが、どのように設定すればいいか御教示下さい。

前提として
タスク開始時にAというログが記録されます。
タスク終了時にBというログが記録されます。

Aが記録されてから、10分たってもBが記録されない場合警告を出すのが目的です。
このような場合、トリガーの記述としてはどのようにすればよろしいでしょうか?

コメント表示オプション

お好みのコメント表示方法を選び「設定の保存」をクリックすると変更が反映されます。
ユーザー fripper の写真

長くなります。ごめんなさい

ログ監視の場合に限らず、"AAAA" が記録されて、一定時間以内に
"BBBB" が記録されない‥といった条件を判定するようなトリガーを作ることは
非常に厄介です

単純なログアイテム項目と、トリガー条件式だけで設定する場合だと
色々な制約があるため、難しいと思います

いくつかの理由‥

◆トリガー判定処理の制約
トリガーの判定は、アイテムに対して新しいデータが届いた時点で
行われるのが zabbix の基本的な動作です
(nodata など、一部のトリガー関数を利用している場合を除く)

そのため、タスク開始時点の "AAAA" が記録された時点はともかくとして
それ以降に何らかのデータが届かない限りは、トリガーの判定処理そのものが
行われず、過去時点の "AAAA" の存在や、直近データ内の "BBBB" の存在を
確かめられないため、異常だと判定することができません

通常のアイテムであれば、60秒間隔など、アイテム側に設定した監視間隔で
定期的にデータ更新が掛かり、その結果として定期的にトリガー判定されるので
ほとんど気にならないのですが、ログアイテムの場合は、新しいログが
出力されない限りはトリガー判定されないので、このような動作になってしまう次第です

対象となっているログアイテムが、"AAAA","BBBB" に相当するログ以外にも
多数のログが頻繁に記録されるようなアイテムだった場合には、
何らかのログが出力された時点で毎回トリガーの判定処理が実施されるので、
障害として検知させることができるのではないか‥とも言えます

しかし、プログラム側がハングアップした‥等の要因によって、ログが全く出力
されなくなってしまった場合には、障害の判定漏れが発生してしまうことになってしまいます

◆ nodata 関数を利用する場合の制約
トリガーの条件式に nodata 関数を用いた場合には、新規データの有無に関わらず
30秒に1度、トリガーの判定処理が行われるようになります

nodata 関数を使えば、新しいログ出力がなくても、定期的にトリガー
判定してくれるのは便利なのですが、
逆に言うと、ログ出力が全く無い状態であっても、30秒毎トリガー判定するので
常時、zabbix サーバ側に少し負荷が掛かることになります

   長くなりすぎるので複数投稿に分けます。すみません

ユーザー fripper の写真

 前投稿の続きです‥

◆過去データでの条件成立を伴うような判定条件式による制約
過去の収集データを絡めるようなトリガー判定式を作る場合、
「どこまで過去のデータを遡って判定させるか」が、案外キモになります

遡る範囲が重要となるのは、「障害」として判定したあと、
いつ「正常」に戻るかが変わってしまうためです

実際の条件式を例として挙げたほうが説明しやすいので、以下いくつか例を‥

★例1
({host:item[param].count(10m,"AAAA","like",10m)}>0) and ({host:item[param].count(10m,"BBBB","like")}=0)

第1の条件として
 10分前の時点を基準に、過去10分間の収集データ内に "AAAA" が1件以上含まれている
  (判定式の評価時点で、10分前~20分前までの記録データを判定させる)
としています
第2の条件として
 直近10分間の収集データ内に "BBBB" が含まれていない
としています

うまく判定できそうに見えますが‥
"AAAA" の記録から5分後に "BBBB" が記録されたような「正常」と判定すべき場合で
"AAAA" 記録から16分経過した時点を考えてみると
・16分前に "AAAA" があるので第1条件が成立
・"BBBB" 記録からは11分経過しているので、直近10分間には "BBBB" がなく、第2条件も成立
   →「障害」として誤検知されてしまう

★例2:前述の場合もカバーできるように‥と、時間の判定範囲を修正
({host:item[param].count(10m,"AAAA","like",10m)}>0) and ({host:item[param].count(20m,"BBBB","like")}=0)

第2の条件として
 直近20分間の収集データ内に "BBBB" が含まれていない
と修正しています

同様に、"AAAA" の記録から5分後に "BBBB" が記録されたような「正常」と判定すべき場合で
"AAAA" 記録から16分経過した時点を考えてみると
・16分前に "AAAA" があるので第1条件が成立
・"BBBB" 記録からは11分しか経過していないので、直近20分間には "BBBB" があり、第2条件は不成立
  →誤検知せず、「正常」として判定できている

"AAAA" の記録から10分経過しても、"BBBB" が記録されていない「異常」と判定すべき場合で
"AAAA" 記録から11分経過した時点を考えてみると
・11分前に "AAAA" があるので第1条件が成立
・直近20分間には "BBBB" がなく、第2条件も成立
   →「障害」として正しく検知

ここまではうまく行って嬉しいのですが‥

"AAAA" の記録から10分経過しても、"BBBB" が記録されていない「異常」と判定すべき場合で
"AAAA" 記録から21分経過した時点を考えてみると
・10分前~20分前までの記録データに "AAAA" がないので第1条件が不成立
   →「障害」として検知していたのが「正常」として戻ってしまう

トリガー判定からのアクションでメール通知をしているような場合だと
「障害発生」が通知されているので気づくことができますが
単に、時々 WebUI のダッシュボードを見ているだけだと
「障害」として検知していた「11分経過時点~20分経過時点」の間に
WebUI を見ていない限り、異常の発生に気づく手立てがありません
  トリガーの発生履歴など、別の Web 画面から参照すれば
  障害発生→復旧の記録として、気づくことができますが‥

★例3:「正常」に戻るのを遅くしようと、さらに判定範囲を修正
({host:item[param].count(600m,"AAAA","like",10m)}>0) and ({host:item[param].count(610m,"BBBB","like")}=0)

「障害」の検知から「正常」に戻るまで、10時間ほどにしてみました

この設定だと、10時間以内に WebUI のダッシュボードを見れば、気づくことができます

しかし、この設定だと、新しいログが届くたびに「過去10時間分のログをチェック」となるので
サーバに負荷が掛かってしまいます

これらが、さまざまな制約事項です‥

タスクの処理内容となっているプログラム側で、10分以上経過してしまっている時に
異常を示す別のログ "CCCC" を出力するなど、別のアプローチができるならば良いのですが‥

ユーザー heya の写真

fripper さんの書かれている通り、これを Zabbix の機能だけでやろうと思うと、かなり複雑か、あるいは無理、ということになると思います。
なので、私ならこうします。

(1) Zabbixトラッパーのアイテムを作っておく(仮にキーを task.finished とする)。
(2) task.finished の値が 0 なら障害扱いにするトリガーを作る。
(3) ログ監視のアイテムで A が出てくるのを監視し、トリガーも設定しておく。
  そして A が出てきたらアクションでスクリプトを実行する。
(4) スクリプトはこんな動きをする。
  (4-1) ログファイルの一番最後に出てくる A の行数 (n) を数える。
  (4-2) 10分間待つ(sleep 600 など)。
  (4-3) ログファイルの n 行目以降に B があるかを調べる。
      あれば zabbix_sender を使って task.finished に 1 を送る。
      無ければ zabbix_sender を使って task.finished に 0 を送る。

細かい条件により、スクリプトはもう少し複雑になるかもしれません。
・ログのローテーションを考える?
・A と B の間に別の A や B が出ることもある?
・ログ監視のアイテム取得~アクションでのスクリプト実行までの短時間に B が出たり、さらに別の A が出たりする可能性も考える必要がある?

ユーザー funimaru の写真

御回答ありがとうございます。

御二方のご回答をもとにログをさらに調査したところ、出力されてい内容は
処理開始ログAAAA

この間、処理途中のログが出力される

処理終了ログBBBB
となっており、AAAAとBBBBの間に別のAAAAやBBBBはなく、
1バッチ処理ごとに必ずAAAAとBBBBがセットで出力される仕組みとなっていました。
またログはzabbixサーバーにsyslogサーバーを同居させてログを常時受信する仕組みになっていました。

しかしながら御意見を見てかなり難しいとの印象を受けました。
何かしらいい方法がないか考えてみます。

ユーザー mocha の写真

もう見てないかもですが わたしの場合の作戦
タスク開始時にはAAAAが 終了時にはBBBBが記録され かつ次回のAAAAが10分以上記録されないのが前提

アイテム: log[対象.log,"AAAA|BBBB"]
※アイテムに記録する対象をAAAAとBBBBだけに絞る

トリガ: ({TRIGGER.VALUE}=0 and {log[対象.log,"AAAA|BBBB"].count(#1,"AAAA","like")}=1 and {log[対象.log,"AAAA|BBBB"].nodata(600)) and ({TRIGGER.VALUE}=1 and {log[対象.log,"AAAA|BBBB"].count(#1,"AAAA","like")}=1)
※前半: 発報前のときは 検知対象のログが最後で かつ過去10分間あたらしいログがなければ発報
※後半: 発報後のときは 最後のログが「AAAA」の状態なら発報状態を維持 == BBBBが記録されればその時点で復旧
※状態監視のトリガなので アイテムはlog[]でも複数イベント生成のフラグはoffで

おうちからなので細かいところ微妙ですが だいたいこんな発想で仕込んだやつをつかってます
実機でためして いろいろ調整してみてください

ユーザー funimaru の写真

mocha様

ご回答ありがとうございます。
検証環境で試してみながら調整をしたいと思います。