CL

46. 想定外のエラー処理をすべてモニターする CLP

エンド・ユーザーにリリースした適用業務の実行において何か予測できなかったエラーが

発生したときに、エラー・メッセージが報告されていても真のエラー原因を掴むことが

できずに悩んだことはないだろうか ?

真のエラー原因を突き止めるためにデータを調べたり、ダンプ解析をしていたのでは

時間がかかってしまう。

特に弊社のようにソフトウェア・パッケージとして配布しているプログラムで問題が

発生したときは調査に時間をかけることはあまりできない。

ここで紹介する CLP は単に SBMJOB するだけのCLプログラムであるが

想定できなかった、すべてのエラーの発生に備えて情報が収集できるようになっている。

最初に CLPソースの全容を紹介する。

0001.00              PGM        PARM(&PFRTIME &TIMEDEF)                         
0002.00 /*-------------------------------------------------------------*/       
0003.00 /*   STRPFRMON :   パフォーマンス・モニター開始                */       
0004.00 /*-------------------------------------------------------------*/       
0005.00              DCL        VAR(&PFRTIME) TYPE(*DEC) LEN(5 0)               
0006.00              DCL        VAR(&TIMEDEF) TYPE(*DEC) LEN(5 0)               
0007.00              DCL        VAR(&MSG) TYPE(*CHAR) LEN(80)                   
0008.00              DCL        VAR(&MSGID) TYPE(*CHAR) LEN(7)                  
0009.00              DCL        VAR(&MSGDTA) TYPE(*CHAR) LEN(132)               
0010.00              DCL        VAR(&MSGID) TYPE(*CHAR) LEN(7)                  
0011.00              DCL        VAR(&MSGF) TYPE(*CHAR) LEN(10)                  
0012.00              DCL        VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)               
0013.00              DCL        VAR(&JOB) TYPE(*CHAR) LEN(10)                   
0014.00              DCL        VAR(&USER) TYPE(*CHAR) LEN(10)                  
0015.00              DCL        VAR(&NBR) TYPE(*CHAR) LEN(6)                    
0016.00              DCL        VAR(&TYPE) TYPE(*CHAR) LEN(1)                   
0017.00              DCL        VAR(&SEV) TYPE(*DEC) LEN(2 0)                   
0018.00              MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))         
0019.00                                                                         
0020.00              RTVJOBA    JOB(&JOB) USER(&USER) NBR(&NBR) TYPE(&TYPE)     
0021.00              SBMJOB     CMD(CALL PGM(ASNET.COM/PFRMON) PARM(&PFRTIME +  
0022.00                           &TIMEDEF)) JOB(PFRMONTOR) +                   
0023.00                           JOBQ(ASNET.COM/ENTPRSSVR)                     
0024.00                                                                         
0025.00  ERROR:      RCVMSG     MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +             
0026.00                           MSGDTA(&MSGDTA) MSGID(&MSGID) SEV(&SEV) +     
0027.00                           MSGF(&MSGF) MSGFLIB(&MSGFLIB)                 
0028.00  SNDMSG:                                                                
0029.00              IF         COND(&TYPE *EQ '0') THEN(DO) /*  バッチ JOB */  
0030.00              IF         COND(&SEV *GE 10) THEN(DO)                      
0031.00              DMPCLPGM                                                   
0032.00              SNDPGMMSG  MSG(' ダンプを QEZDEBUG に出力しました。 ') +   
0033.00                           TOMSGQ(*SYSOPR)                               
0034.00              SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +            
0035.00                           MSGDTA(&MSGDTA) TOMSGQ(*SYSOPR)               
0036.00              SNDPGMMSG  MSG('STRPFRMON- ジョブ ' *CAT &JOB *TCAT +      
0037.00                           '/' *CAT &USER *TCAT '/' *CAT &NBR +          
0038.00                           *TCAT +                                       
0039.00                           ' で次のエラーが発生しました。 ') +           
0040.00                           TOMSGQ(*SYSOPR)                               
0041.00              ENDDO                                                      
0042.00              ELSE       CMD(DO)                                
0043.00              SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +   
0044.00                           MSGDTA(&MSGDTA) TOMSGQ(*SYSOPR) +    
0045.00                           MSGTYPE(*COMP)                       
0046.00              ENDDO                                             
0047.00              ENDDO      /*  バッチ JOB */                      
0048.00              ELSE       CMD(DO) /*  対話式  */                 
0049.00              SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +   
0050.00                           MSGDTA(&MSGDTA) TOMSGQ(*TOPGMQ) +    
0051.00                           MSGTYPE(*DIAG)                       
0052.00              ENDDO      /*  対話式  */                         
0053.00              ENDPGM
【 解説 】

最初に

0020.00              RTVJOBA    JOB(&JOB) USER(&USER) NBR(&NBR) TYPE(&TYPE)

によって、このジョブのジョブ情報とジョブのタイプを調べている。

&TYPE0 であれば、このジョブはバッチ・ジョブとして実行されているし、

&TYPE1 であれば、このジョブは対話式ジョブとして実行されていることがわかる。

次に

0018.00              MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))

によって、例外的なエラーが発生したときは、すべて制御は ERROR: タグへジャンプする

また、

0021.00              SBMJOB     CMD(CALL PGM(ASNET.COM/PFRMON) PARM(&PFRTIME +
0022.00                           &TIMEDEF)) JOB(PFRMONTOR) +
0023.00                           JOBQ(ASNET.COM/ENTPRSSVR)

の直後には RETURN 命令がないことからわかるように、正常に処理された場合でも

完了メッセージを受信して表示することが必要であるので、やはり制御は ERROR: タグ

渡される。

>ERROR: タグでは RCVMSG によってメッセージを受信しているのであるが

メッセージ・データ (&MSGDTA) とメッセージ・ファイル( &MSGF, &MSGFLIB) と

メッセージ識別コード (&MSGID) の受信を主体としてメッセージを検索している。

これらを組み合わせてから SNDPGMMSG を行うとローレベル・メッセージと

メッセージ識別までをできるからである。

含むすべてのメッセージ情報を完全な形で復元して、メッセージとして出力することが

単にエラー・メッセージを出力するたけであれば、エラーの詳細までを知ることができないからである。

また、この CLP がバッチ・ジョブとして実行されているときは、

0031.00              DMPCLPGM
0032.00              SNDPGMMSG  MSG(' ダンプを QEZDEBUG に出力しました。 ') +
0033.00                           TOMSGQ(*SYSOPR)

とあるように実行時のダンプが OUTQ: QEZDEBUG に出力されるので、エラーが発生したときの

CLP 内の変数の値やエラー・ステートメントも後で調べることができるようになっている。

もちろん、

0036.00              SNDPGMMSG  MSG('STRPFRMON- ジョブ ' *CAT &JOB *TCAT +
0037.00                           '/' *CAT &USER *TCAT '/' *CAT &NBR +
0038.00                           *TCAT +
0039.00                           ' で次のエラーが発生しました。 ') +
0040.00                           TOMSGQ(*SYSOPR)

にあるように、エラー・メッセージだけでなく、この CLP 自身の名前も通知しておくことも必要である。

簡単な処理であるので、エラーも発生することなく動作するであろうと期待していた CLP でも

このようにしっかりとエラー・モニターしておけば障害のときの調査がよりわかりやすく

短時間のうちに調査することができるようになる。

プログラムの品質の向上のためにエラー・モニターのしっかりした体制を作っておきたいものである。