TRY-CATCH メカニズム
InterSystems IRIS は、エラー処理のために TRY-CATCH メカニズムをサポートします。このメカニズムを使用すると、それぞれが TRY ブロックと呼ばれる区切られたコードのブロックを作成できます。TRY ブロック中にエラーが発生した場合、TRY ブロックに関連付けられた、例外処理のコードを含む CATCH ブロックに制御が渡されます。TRY ブロックには THROW コマンドを含めることもできます。これらのコマンドはそれぞれ、TRY ブロック内から明示的に例外を発行し、実行を CATCH ブロックに移します。
最も基本的な形式でこのメカニズムを使用するには、ObjectScript コード内に TRY ブロックを含めます。このブロック内で例外が発生する場合、関連付けられた CATCH ブロック内のコードが実行されます。TRY-CATCH ブロックの形式は以下のとおりです。
TRY {
protected statements
} CATCH [ErrorHandle] {
error statements
}
further statements
以下はその説明です。
-
TRY コマンドは、中括弧で囲まれた ObjectScript のコード文を識別します。TRY は引数を取りません。このコード・ブロックは、構造化された例外処理のための保護されたコードです。TRY ブロック内で例外が発生した場合、InterSystems IRIS は例外プロパティ (oref.Name、oref.Code、oref.Data、oref.Location)、$ZERROR、および $ECODE を設定し、CATCH コマンドによって識別される、例外ハンドラに実行を移します。これは、例外のスローとして知られています。
-
protected statementsは、通常の実行の一部である、ObjectScript 文です。(これらの文には、THROW コマンドへの呼び出しを含めることができます。このシナリオについては、以下のセクションで説明します。)
-
CATCH コマンドは、例外ハンドラを定義します。これは、TRY ブロックで例外が発生したときに実行されるコードのブロックです。
-
ErrorHandle 変数は、例外オブジェクトへのハンドルです。これは、InterSystems IRIS が実行時エラーに対して生成した例外オブジェクト、または THROW コマンド (以下のセクションで説明します) の呼び出しにより明示的に発行された例外オブジェクトのいずれかとなります。
-
error statements は、例外が発生したときに呼び出される ObjectScript 文です。
-
further statements は、例外がない場合に protected statements の実行の後に続く、または例外が発生して CATCH ブロックから制御が渡される場合に error statements の実行の後に続く、ObjectScript 文です。
protected statements の実行中のイベントに応じて、以下のイベントのいずれかが発生します。
TRY-CATCH と一緒に THROW を使用する
InterSystems IRIS は、実行時エラーの発生時に暗黙的な例外を発行します。明示的な例外を発行するには、THROW コマンドを使用できます。THROW コマンドは、TRY ブロックから CATCH 例外ハンドラへ実行を移します。THROW コマンドの構文は以下のとおりです。
THROW expression
expression は、例外処理のために InterSystems IRIS に用意されている %Exception.AbstractExceptionOpens in a new tab クラスから継承するクラスのインスタンスです。%Exception.AbstractExceptionOpens in a new tab の詳細は、以下のセクションを参照してください。
TRY/CATCH ブロックと THROW を一緒に発行する場合の形式は以下のとおりです。
TRY {
protected statements
THROW expression
protected statements
}
CATCH exception {
error statements
}
further statements
ここで、THROW コマンドは明示的に例外を発行します。TRY-CATCH ブロックの他の要素については、前のセクションで説明しています。
THROW の動作は、スローが発生する場所と THROW の引数によって異なります。
-
TRY ブロック内の THROW は、CATCH ブロックに制御を渡します。
-
CATCH ブロック内の THROW は、実行スタックの制御を次のエラー・ハンドラに渡します。例外が %Exception.SystemException オブジェクトの場合、次のエラー・ハンドラは、どのタイプ (CATCH または従来のエラー処理) でもかまいません。それ以外の場合は、CATCH による例外処理が必要となります。そうしないと、<NOCATCH> エラーがスローされます。
引数付きの THROW のために、制御が CATCH ブロックに渡される場合、ErrorHandle には引数からの値が含まれています。システム・エラーのために制御が CATCH ブロックに渡される場合、ErrorHandle は %Exception.SystemExceptionOpens in a new tab オブジェクトです。ErrorHandle が指定されていない場合、制御が CATCH ブロックに渡された理由が示されません。
例えば、以下のように 2 つの数字を除算するコードがあるとします。
div(num,div) public {
TRY {
SET ans=num/div
} CATCH errobj {
IF errobj.Name="<DIVIDE>" { SET ans=0 }
ELSE { THROW errobj }
}
QUIT ans
}
0 による除算エラーが発生すると、このコードは結果として 0 を返すように特別に設計されています。 この他のエラーの場合、THROW はスタック上のエラーを次のエラー・ハンドラに送信します。
$$$ThrowOnError および $$$ThrowStatus マクロの使用法
InterSystems IRIS は、例外処理で使用するために、マクロを提供します。これらのマクロは、呼び出されると CATCH ブロックに例外オブジェクトをスローします。
以下の例は、%Prepare() メソッドによりエラー・ステータスが返されると、$$$ThrowOnError マクロを呼び出します。
#include %occStatus
TRY {
SET myquery = "SELECT TOP 5 Name,Hipness,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
$$$ThrowOnError(status)
WRITE "%Prepare succeeded",!
RETURN
}
CATCH sc {
WRITE "In Catch block",!
WRITE "error code: ",sc.Code,!
WRITE "error location: ",sc.Location,!
WRITE "error data:",$LISTGET(sc.Data,2),!
RETURN
}
以下の例は、%Prepare() メソッドにより返されたエラー・ステータスの値をテストした後に$$$ThrowStatus を呼び出します。
#include %occStatus
TRY {
SET myquery = "SELECT TOP 5 Name,Hipness,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
IF ($System.Status.IsError(status)) {
WRITE "%Prepare failed",!
$$$ThrowStatus(status) }
ELSE {WRITE "%Prepare succeeded",!
RETURN }
}
CATCH sc {
WRITE "In Catch block",!
WRITE "error code: ",sc.Code,!
WRITE "error location: ",sc.Location,!
WRITE "error data:",$LISTGET(sc.Data,2),!
RETURN
}
システム指定のマクロについては、このドキュメントの “ObjectScript マクロとマクロ・プリプロセッサ” の章で説明します。
TRY-CATCH を使用する際の他の考慮事項
TRY-CATCH ブロックを使用する際に発生する可能性がある状況を、以下に説明します。
TRY-CATCH ブロック内での QUIT
TRY または CATCH ブロック内の QUIT コマンドは、TRY-CATCH ブロック全体の後で、ブロックから次の文に制御を渡します。
TRY-CATCH と実行スタック
TRY ブロックは、実行スタックで新しいレベルを導入しません。つまり、NEW コマンドのアクセス範囲境界ではありません。error statements は、そのエラーと同じレベルで実行されます。この結果として、protected statements 内に DO コマンドがあり、DO のターゲットも protected statements 内にある場合には、予期しない結果が発生する可能性があります。このような場合には、$ESTACK 特殊変数が、相対的な実行レベルに関する情報を提供できます。
従来のエラー処理で TRY-CATCH を使用する
TRY-CATCH エラー処理は、実行スタックの異なるレベルで使用される $ZTRAP エラー・トラップと互換性があります。例外は、$ZTRAP を TRY 節の protected statements 内で使用できないことです。THROW コマンドでは、ユーザ定義のエラーは TRY-CATCH のみに制限されます。ZTRAP コマンドを使用したユーザ定義のエラーは、任意のタイプのエラー処理で使用できます。
%Status エラー処理
InterSystems IRIS クラス・ライブラリのメソッドの多くは、%StatusOpens in a new tab データ型を使用して、成功、または失敗の情報を返します。例えば、%PersistentOpens in a new tab オブジェクトのインスタンスを保存するときに使用される %Save() メソッドは、オブジェクトが保存されたか否かを示す %StatusOpens in a new tab 値を返します。
%SYSTEM.StatusOpens in a new tab クラス・メソッドを使用すれば、%StatusOpens in a new tab の値を検査および操作できます。
InterSystems IRIS には、%StatusOpens in a new tab でエンコードされた文字列をさまざまな形式で表示 (書き込み) するための複数のオプションがあります。詳細は、このドキュメントの “コマンド” の章の “表示 (書き込み) コマンド” を参照してください。
以下の例では、myquery テキストのエラーによって %Prepare が失敗します (“ZOP” は “TOP” とすべき)。このエラーは IsError()Opens in a new tab メソッドにより検出され、他の %SYSTEM.StatusOpens in a new tab がエラー・コードとテキストを表示します。
SET myquery = "SELECT ZOP 5 Name,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
IF ($System.Status.IsError(status)) {
WRITE "%Prepare failed",!
DO StatusError() }
ELSE {WRITE "%Prepare succeeded",!
RETURN }
StatusError()
WRITE "Error #",$System.Status.GetErrorCodes(status),!
WRITE $System.Status.GetOneStatusText(status,1),!
WRITE "end of error display"
QUIT
下の例は上の例と同じですが、ステータス・エラーが %occStatus インクルード・ファイルの $$$ISERR() マクロによって検出される点で異なります。$$$ISERR() (およびその反転型である $$$ISOK()) は、%StatusOpens in a new tab =1 であるかどうかをチェックします。エラー・コードは $$$GETERRORCODE() マクロによって返されます。
#include %occStatus
SET myquery = "SELECT ZOP 5 Name,DOB FROM Sample.Person"
SET tStatement = ##class(%SQL.Statement).%New()
SET status = tStatement.%Prepare(myquery)
IF $$$ISERR(status) {
WRITE "%Prepare failed",!
DO StatusError() }
ELSE {WRITE "%Prepare succeeded",!
RETURN}
StatusError()
WRITE "Error #",$$$GETERRORCODE(status),!
WRITE $System.Status.GetOneStatusText(status,1),!
WRITE "end of error display"
QUIT
システム指定のマクロについては、このドキュメントの “ObjectScript マクロとマクロ・プリプロセッサ” の章で説明します。
%New() など、%StatusOpens in a new tab を生成しても返さないメソッドもあります。%New() は、成功時にはクラスのインスタンスに oref を返し、失敗時には NULL 文字列を返します。以下の例で示すように、%objlasterror システム変数にアクセスして、この種のメソッドのステータス値を取得することができます。
SET session = ##class(%CSP.Session).%New()
IF session="" {
WRITE "session oref not created",!
WRITE "%New error is ",!,$System.Status.GetErrorText(%objlasterror),! }
ELSE {WRITE "session oref is ",session,! }
詳細は、%SYSTEM.StatusOpens in a new tab のクラスを参照してください。
%Status エラーの作成
Error()Opens in a new tab メソッドを使用すれば、ユーザ独自のメソッドからシステム定義の %Status エラーを呼び出すことができます。この場合、返したいエラー・メッセージに対応するエラー番号を指定します。
WRITE "Here my method generates an error",!
SET status = $System.Status.Error(20)
WRITE $System.Status.GetErrorText(status),!
以下の例で示すように、返すエラー・メッセージに %1、%2、%3 パラメータを含むことができます。
WRITE "Here my method generates an error",!
SET status = $System.Status.Error(214,"3","^fred","BedrockCode")
WRITE $System.Status.GetErrorText(status),!
エラー・メッセージをローカライズして、ユーザの優先言語で表示することもできます。
SET status = $System.Status.Error(30)
WRITE "In English:",!
WRITE $System.Status.GetOneStatusText(status,1,"en"),!
WRITE "In French:",!
WRITE $System.Status.GetOneStatusText(status,1,"fr"),!
エラー・コードとメッセージ (英語) の一覧については、"InterSystems IRIS エラー・リファレンス" の “一般的なエラー・メッセージ” の章を参照してください。
一般的なエラー・コード 83 および 5001 を使用すれば、いずれの一般エラー・メッセージにも対応していないカスタム・メッセージを指定することができます。
また、AppendStatus()Opens in a new tab メソッドを使用して、複数のエラー・メッセージの一覧を作成することができます。さらに、GetOneErrorText()Opens in a new tab または GetOneStatusText()Opens in a new tab を使用して、この一覧のそれぞれの位置ごとの各エラー・メッセージを取得することもできます。
CreateCustomErrors
SET st1 = $System.Status.Error(83,"my unique error")
SET st2 = $System.Status.Error(5001,"my unique error")
SET allstatus = $System.Status.AppendStatus(st1,st2)
DisplayErrors
WRITE "All together:",!
WRITE $System.Status.GetErrorText(allstatus),!!
WRITE "One by one",!
WRITE "First error format:",!
WRITE $System.Status.GetOneStatusText(allstatus,1),!
WRITE "Second error format:",!
WRITE $System.Status.GetOneStatusText(allstatus,2),!
従来のエラー処理
このセクションでは、InterSystems IRIS を使用した従来のエラー処理のさまざまな側面について説明します。以下の内容が含まれます。
従来のエラー処理の概要
InterSystems IRIS には、アプリケーションでエラー・ハンドラを使用して従来のエラー処理を実行できるようにするための機能が備わっています。エラー・ハンドラは、アプリケーションの実行中に発生するあらゆるエラーを処理します。エラー発生時に実行する ObjectScript コマンドは、特殊変数で指定します。 これらのコマンドは、エラーを直接処理するか、エラーを処理するルーチンを呼び出します。
エラー・ハンドラの作成には、以下の基本的な処理を実行します。
-
エラー処理を実行する 1 つ以上のルーチンを生成します。エラー処理を実行するコードを作成します。このコードは、アプリケーション全体に対する一般的なコードであっても、特定の処理における特定のエラー状態に対するものであってもかまいません。これにより、アプリケーションの特定個所で、カスタマイズされたエラー処理を実行できます。
-
アプリケーション内に 1 つ以上のエラー・ハンドラを設定し、それぞれのエラー・ハンドラで固有の適切なエラー処理を使用します。
エラーが発生してもエラー・ハンドラが設定されていなかった場合の振る舞いは、その InterSystems IRIS セッションの開始方法によって異なります。
-
ターミナル・プロンプトで InterSystems IRIS にサインオンし、エラー・トラップは設定していない場合、InterSystems IRIS は主デバイスにエラー・メッセージを表示し、プログラム・スタックの設定を変更せずにターミナル・プロンプトに戻ります。プログラマは、プログラムの実行を後で再開できます。
-
アプリケーション・モードで InterSystems IRIS を実行し、エラー・トラップを設定していない場合、InterSystems IRIS は主デバイスにエラー・メッセージを表示し、HALT コマンドを実行します。
内部的なエラー・トラップの振る舞い
特殊変数 $ZTRAP (および $ETRAP) による InterSystems IRIS のエラー処理とその有効範囲を最大限に活用するには、InterSystems IRIS が制御をあるルーチンから別のルーチンに移す方法を理解すると役立ちます。
InterSystems IRIS は、以下のいずれかが発生するたびに、“コンテキスト・フレーム” というデータ構造を構築します。
-
ルーチンが Do コマンドで別のルーチンを呼び出す場合 (この種類のフレームは “DO フレーム” とも呼ばれます)。
-
XECUTE コマンド引数により、ObjectScript コードが実行される場合 (この種類のフレームは “XECUTE フレーム” とも呼ばれます)。
-
ユーザ定義関数を実行した場合
プロセスのアドレス部にあるプライベート・データ構造の 1 つ、コール・スタックにフレームが構築されます。InterSystems IRIS はルーチン用として、フレームに以下の要素を格納します。
-
$ZTRAP 特殊変数の値 (存在する場合)
-
$ETRAP 特殊変数の値 (存在する場合)
-
サブルーチンから返される位置情報
例えば、ルーチン A がルーチン B を DO ^B で呼び出すと、InterSystems IRIS は、コール・スタックに A のコンテキストを保持する DO フレームを構築します。また、ルーチン B がルーチン C を呼び出すと、コール・スタックに B のコンテキストを保持する DO フレームを追加します。
コール・スタックのフレーム
上図のルーチン A がターミナル・プロンプトで DO コマンドを使用して呼び出される場合、図にはありませんが、追加の DO フレームがコール・スタックの一番下に存在しています。
現在のコンテキスト・レベル
現在のコンテキスト・レベルに関する情報を返すために以下を使用できます。
-
$STACK 特殊変数は、現在の相対スタック・レベルを含みます。
-
$ESTACK 特殊変数は、現在のスタック・レベルを含みます。任意のユーザ定義のポイントで、0 (レベル・ゼロ) に初期化できます。
-
$STACK 関数は、現在のコンテキストと、コール・スタックに格納されているコンテキストに関する情報を返します。
$STACK 特殊変数
$STACK 特殊変数は、プロセスのコール・スタックに現在保存されているフレームの数を含みます。$STACK 値は、基本的に、現在実行しているコンテキストの (ゼロ・ベースの) レベル番号です。したがって、イメージが開始されるとき、コマンドが処理されるまで、$STACK の値は 0 です。
詳細は、"ObjectScript リファレンス" の "$STACK" 特殊変数を参照してください。
$ESTACK 特殊変数
$ESTACK 特殊変数は、$STACK 特殊変数に類似していますが、New コマンドで変数を 0 にリセットできるため (また以前の値を保存できます)、エラー処理には $ESTACK の方が便利です。したがって、プロセスは、特定のコンテキストで $ESTACK をリセットし、$ESTACK レベル 0 のコンテキストとしてマークすることができます。その後エラーが発生した場合、エラー・ハンドラは $ESTACK 値をテストし、コール・スタックをそのコンテキストまで戻すことができます。
詳細は、"ObjectScript リファレンス" の "$ESTACK" 特殊変数を参照してください。
$STACK 関数
$STACK 関数は、現在のコンテキストと、コール・スタックに格納されているコンテキストに関する情報を返します。各コンテキストで、$STACK 関数は以下の情報を提供します。
-
コンテキスト・タイプ (Do、Xecute、ユーザ定義関数)
-
コンテキストで処理された最後のコマンドのエントリ参照とコマンド番号
-
コンテキストで処理された最後のコマンドを含むソース・ルーチン行あるいは XECUTE 文字列
-
コンテキストで発生した任意のエラーの $ECODE 値 ($ECODE が NULL でない場合、エラー処理中にのみ利用可能)
エラー発生時、すべてのコンテキスト情報はプロセス・エラー・スタックに即座に格納されます。その後、コンテキスト情報は、エラー・ハンドラが $ECODE 値をクリアするまで $STACK 関数によりアクセスできます。つまり、$ECODE 値が NULL でない場合、$STACK 関数は、エラー・スタックに保存されたコンテキストと同じ指定されたコンテキスト・レベルのアクティブなコンテキストではなく、エラー・スタックに保存されたコンテキストの情報を返します。
詳細は、"ObjectScript リファレンス" の "$STACK" 関数を参照してください。
エラーが発生し、エラー・スタックが既に存在している場合、InterSystems IRIS は、エラー・スタックの同じコンテキスト・レベルに別のエラーに関する情報が存在しない限り、コンテキスト・レベルで新しいエラーに関する情報を記録します。この場合、エラー情報は、(エラー情報が既に記録されているか否かにかかわらず) エラー・スタックの次のレベルに配置されます。
したがって、新規エラーのコンテキスト・レベルによっては、エラー・スタックは拡張される (1 つ以上のコンテキスト・レベルを追加される) か、あるいは、既存のエラー・スタックのコンテキスト・レベルに存在する情報が新規エラー情報を格納するために上書きされることがあります。
$ECODE 特殊変数をクリアすると、プロセス・エラー・スタックが消去されることに注意してください。
エラー・コード
エラー発生時、InterSystems IRIS は $ZERROR 特殊変数と $ECODE 特殊変数に、エラーを示す値を設定します。$ZERROR および $ECODE の値は、エラーの直後に使用することを目的としています。これらの値は複数のルーチン呼び出しにわたっては保持されない可能性があるため、後で使用するために値を保持したい場合は、この値を変数にコピーする必要があります。
$ZERROR 値
InterSystems IRIS は、$ZERROR に以下を含む文字列を設定します。
-
山括弧で囲まれた InterSystems IRIS のエラー・コード
-
エラー発生場所のラベル、オフセットおよびルーチン名
-
一部のエラーでは、エラーの原因となった項目の名前などの追加情報
%Exception.SystemExceptionOpens in a new tab クラスの AsSystemError()Opens in a new tab メソッドは、$ZERROR と同じ形式で同じ値を返します。
以下の例では、InterSystems IRIS がエラーに遭遇した際に、$ZERROR に設定されるメッセージ・タイプを示します。以下の例では、未定義のローカル変数 abc が、ルーチン MyTest のラベル PrintResult より行オフセット 2 の位置で呼び出されます。$ZERROR は以下を含みます。
<UNDEFINED>PrintResult+2^MyTest *abc
存在しないクラスが行オフセット 3 の位置で実行されると、以下のエラーが発生します。
<CLASS DOES NOT EXIST>PrintResult+3^MyTest *%SYSTEM.XXQL
既存クラスの存在しないメソッドが行オフセット 4 の位置で実行されると、以下のエラーが発生します。
<METHOD DOES NOT EXIST>PrintResult+4^MyTest *BadMethod,%SYSTEM.SQL
128 文字までの任意の文字列として、特殊変数 $ZERROR を明示的に設定することもできます。以下はその例です。
SET $ZERROR="Any String"
$ZERROR 値は、エラーの直後に使用することを目的としています。$ZERROR 値は複数のルーチン呼び出しにわたっては保持されない可能性があるため、後で使用するために $ZERROR 値を保持したいユーザはこの値を変数にコピーする必要があります。ユーザは $ZERROR を使用したらすぐに NULL 文字列 ("") に設定することを強くお勧めします。詳細は、"ObjectScript リファレンス" の "$ZERROR" 特殊変数を参照してください。$ZERROR エラーの取り扱いについての詳細は、"インターシステムズ・クラス・リファレンス" の %SYSTEM.ErrorOpens in a new tab クラス・メソッドを参照してください。
$ECODE 値
エラー発生時、コンマに囲まれた文字列値を InterSystems IRIS は $ECODE に設定します。この値は、エラーに対応する ANSI 標準エラー・コードを含んでいます。例えば、未定義のグローバル変数を参照する場合、InterSystems IRIS は $ECODE セットに以下の文字列を設定します。
,M7,
エラーに対応 ANSI 標準エラー・コードを持たない場合、コンマに囲まれた文字列値 (文字 Z が先頭についた InterSystems IRIS エラー・コードが含まれる) に $ECODE を InterSystems IRIS は設定します。例えば、プロセスがシンボル・テーブルの領域をすべて使用した場合、InterSystems IRIS は $ZERROR 特殊変数にエラー・コード <STORE> を格納し、$ECODE に以下の文字列を設定します。
,ZSTORE,
エラー発生後、エラー・ハンドラは $ZERROR 特殊変数あるいは $ECODE 特殊変数を検証して、特定のエラー・コードをテストできます。
Note:
エラー・ハンドラは、特定のエラーに関し、$ECODE 特殊変数ではなく $ZERROR 特殊変数を検証する必要があります。
詳細は、"ObjectScript リファレンス" の "$ECODE" 特殊変数を参照してください。
$ZTRAP でのエラー処理
$ZTRAP でエラーを処理するには、$ZTRAP 特殊変数を location に設定し、引用符で囲まれた文字列として指定します。$ZTRAP 特殊変数はエントリ参照に対して設定します。このエントリ参照によって、エラー発生時における制御の移管先となる location を指定します。次にその場所に $ZTRAP コードを記述します。
$ZTRAP を空以外の値に設定すると、これは既存のどの $ETRAP エラー・ハンドラよりも優先されます。InterSystems IRIS は暗黙的に NEW $ETRAP コマンドを実行し、$ETRAP を "" に設定します。
プロシージャでの $ZTRAP の設定
プロシージャ内では、そのプロシージャ内の行ラベル (プライベート・ラベル) にのみ $ZTRAP 特殊変数を設定できます。プロシージャ・ブロック内から $ZTRAP を外部ルーチンに設定することはできません。
$ZTRAP 値を表示するとき、InterSystems IRIS はプライベート・ラベルの名前を返しません。代わりに、プロシージャの先頭からのそのプライベート・ラベルがある場所までのオフセットを返します。
詳細は、"ObjectScript リファレンス" の "$ZTRAP" 特殊変数を参照してください。
ルーチンでの $ZTRAP の設定
ルーチン内では、$ZTRAP 特殊変数を現在のルーチンのラベル、外部ルーチン、または外部ルーチン内のラベルに設定できます。外部ルーチンを参照できるのは、そのルーチンがプロシージャ・ブロック・コードではない場合だけです。以下の例では、LogErr^ErrRou をエラー・ハンドラとして構築します。エラー発生時には、InterSystems IRIS が ^ErrRou ルーチン内の LogErr ラベルにあるコードを実行します。
SET $ZTRAP="LogErr^ErrRou"
$ZTRAP 値を表示するとき、InterSystems IRIS はラベル名と (該当する場合には) ルーチン名を表示します。
ラベル名は最初の 31 文字内で一意である必要があります。ラベル名およびルーチン名では、大文字と小文字が区別されます。
ルーチン内では、$ZTRAP には 3 つの形式があります。
-
SET $ZTRAP="location"
-
SET $ZTRAP="*location"。この形式では、この関数を呼び出したエラーの発生元であるコンテキストで実行されます。
-
SET $ZTRAP="^%ETN" は、システムで提供されるエラー・ルーチン %ETN を実行します。このルーチンはルーチンを呼び出すエラーが発生したコンテキストにおいて実行されます。プロシージャ・ブロック内から ^%ETN (またはいずれかの外部ルーチン) を実行することはできません。コードが [Not ProcedureBlock] であることを指定するか、%ETN エントリポイント BACK^%ETN を呼び出す以下のようなルーチンを使用してください。
ClassMethod MyTest() as %Status
{
SET $ZTRAP="Error"
SET ans = 5/0 /* divide-by-zero error */
WRITE "Exiting ##class(User.A).MyTest()",!
QUIT ans
Error
SET err=$ZERROR
SET $ZTRAP=""
DO BACK^%ETN
QUIT $$$ERROR($$$CacheError,err)
}
%ETN およびそのエントリポイントの詳細は、"アプリケーション・エラーのログ作成" を参照してください。$ZTRAP と共に使用する際の処理の詳細は、"SET $ZTRAP=^%ETN" を参照してください。
詳細は、"ObjectScript リファレンス" の "$ZTRAP" 特殊変数を参照してください。
$ZTRAP コードの記述
$ZTRAP が指し示す location はさまざまな操作を実行して、エラーを表示、ログ記録、または修正することができます。実行したいエラー処理操作の如何にかかわらず、$ZTRAP コードは以下の 2 つのタスクの実行により開始する必要があります。
-
$ZTRAP を他の値、すなわちエラー・ハンドラの location または空文字列 ("") のいずれかに設定します。(KILL $ZTRAP. とすることはできないので、SET を使用する必要があります。)これを行う理由は、エラー処理中に別のエラーが発生した場合において、そのエラーが現在の $ZTRAP エラー・ハンドラを呼び出してしまうためです。現在のエラー・ハンドラがユーザの関わるエラー・ハンドラである場合、無限ループとなってしまいます。
-
ある変数を $ZERROR に設定します。後でコード内で $ZERROR 値を参照する場合は、$ZERROR 自体ではなく、この変数を参照します。これを行う理由は、$ZERROR には最新のエラーが含まれているうえ、$ZERROR 値が、内部ルーチン呼び出しなどの複数のルーチン呼び出しにわたって保持されない可能性があるからです。エラー処理中に別のエラーが発生した場合、$ZERROR の値がその新しいエラーによって上書きされることになります。
ユーザは $ZERROR を使用したらすぐに NULL 文字列 ("") に設定することを強くお勧めします。
以下の例では、これらの不可欠な $ZTRAP コード文を示します。
MyErrHandler
SET $ZTRAP=""
SET err=$ZERROR
/* error handling code
using err as the error
to be handled */
$ZTRAP の使用法
アプリケーションの各ルーチンは、$ZTRAP を設定して、独自の $ZTRAP エラー・ハンドラを作成できます。エラー・トラップの発生時、InterSystems IRIS は以下の手順を実行します。
-
特殊変数 $ZERROR にエラー・メッセージを設定します。
-
プログラム・スタックを、エラー・トラップが設定された時点 (SET $ZTRAP= の実行時) の状態にリセットします。つまり、システムは、エラー・トラップが設定された時点まで、スタックに存在するすべてのエントリを削除します。($ZTRAP がアスタリスク (*) で始まる文字列に設定されている場合、プログラム・スタックはリセットされません。)
-
$ZTRAP の値により指定された位置でプログラムを再開します。$ZTRAP の値は保持されます。
Note:
$ZERROR 変数を、128 文字までの文字列として明示的に設定できます。通常、$ZERROR は NULL 文字列にのみ設定しますが、$ZERROR を値に設定してもかまいません。
エラー・トラップによる New コマンドの削除
エラー・トラップが発生しプログラム・スタック・エントリが削除されると、InterSystems IRIS は、スタックされたすべての NEW コマンドも削除し、SET $ZTRAP= を含むサブルーチン・レベルに戻します。しかし、NEW コマンドが $ZTRAP の設定前あるいは設定後にスタックに追加されたかどうかにかかわらず、そのサブルーチン・レベルで実行されたすべての NEW コマンドは維持されます。
以下はその例です。
Main
SET A=1,B=2,C=3,D=4,E=5,F=6
NEW A,B
SET $ZTRAP="ErrSub"
NEW C,D
DO Sub1
RETURN
Sub1()
NEW E,F
WRITE 6/0 // Error: division by zero
RETURN
ErrSub()
WRITE !,"Error is: ",$ZERROR
WRITE
RETURN
Sub1 のエラーがエラー・トラップを起動した場合、Sub1 にスタックされた E と F における以前の値は削除されます。しかし、A、B、C、D はスタックされたままになります。
$ZTRAP フロー制御オプション
$ZTRAP エラー・ハンドラがエラー処理のために呼び出され、クリーンアップとエラー記録処理を実行した後、このエラー・ハンドラには 3 つのフロー制御オプションがあります。
-
エラーを処理し、アプリケーションを継続します。
-
制御を別のエラー・ハンドラに渡します。
-
アプリケーションを終了します。
アプリケーションの継続
$ZTRAP がエラーを処理した後には、GOTO の発行によりアプリケーションを続行することができます。通常のアプリケーション処理を継続するために、$ZERROR または $ECODE 特殊変数値をクリアする必要はありません。しかし、$ZTRAP をクリアし (空の文字列を設定)、別のエラーが発生した際に無限のエラー処理ループに入らないようにする必要があります。詳細は、“エラー・ハンドラによるエラー処理” を参照してください。
エラー処理を実行した後、$ZTRAP エラー・ハンドラは GOTO コマンドを使用して、アプリケーション内で事前設定されたリスタートまたは継続ポイントに制御を移し、通常のアプリケーション処理を再開できます。
エラー・ハンドラがエラーを処理すると、$ZERROR 特殊変数が値に設定されます。エラー・ハンドラが処理を終了すると、この値は必ずしもクリアされるわけではありません。ルーチンによっては、$ZERROR を NULL 文字列に設定し直すものがあります。エラー・ハンドラを呼び出すエラーが次に発生したときに、$ZERROR は上書きされます。この理由から、$ZERROR 値はエラー・ハンドラのコンテキスト内でのみ使用する必要があります。この値を保持する場合は、これを変数にコピーして、$ZERROR 自体ではなくその変数を参照します。その他のコンテキストで $ZERROR を使用すると、信頼できる結果が生成されません。
別のエラー・ハンドラへの制御の移動
エラー条件を $ZTRAP エラー・ハンドラで修正できない場合、特殊な形式の ZTRAP コマンドを使用して、別のエラー・ハンドラに制御を移すことができます。 コマンド ZTRAP $ZERROR は、エラー条件を再度示し、エラー・ハンドラを使って、InterSystems IRIS で次のコール・スタック・レベルまでコール・スタックが戻るようにします。 InterSystems IRIS で次のエラー・ハンドラのレベルにコール・スタックを戻したら、そのエラー・ハンドラで処理が続行します。次のエラー・ハンドラは、$ZTRAP または $ETRAP で設定された可能性があります。
下図は、$ZTRAP エラー処理ルーチンのフロー制御を示しています。
$ZTRAP エラー・ハンドラ
$ETRAP でのエラー処理
エラー・トラップの発生時に $ETRAP が設定されている場合、InterSystems IRIS は以下の手順を実行します。
-
$ECODE および $ZERROR の値を設定します。
-
$ETRAP の値であるコマンドを処理します。
既定で、DO、XECUTE、またはユーザ定義の各関数コンテキストは、それを呼び出したフレームの $ETRAP エラー・ハンドラを継承します。つまり、どのコンテキスト・レベルであっても、指定された $ETRAP エラー・ハンドラが最終的に $ETRAP として定義されます。その定義が現在のレベルよりもいくつか低いスタック・レベルで行われていた場合でも同様です。
$ETRAP エラー・ハンドラ
$ETRAP 特殊変数には、エラーの発生時に実行される 1 つ以上の ObjectScript コマンドを含めることができます。SET コマンドを使用して、$ETRAP を、制御をエラー処理ルーチンに移す 1 つ以上の InterSystems IRIS コマンドを含む文字列に設定します。以下の例では、制御が LogError コード・ラベル (ルーチン ErrRoutine の一部) に移されます。
SET $ETRAP="DO LogError^ErrRoutine"
$ETRAP 特殊変数内のコマンドの後ろには常に、暗黙の QUIT コマンドが続きます。引数付きの QUIT コマンドを必要とするユーザ定義の関数コンテキストで $ETRAP エラー・ハンドラが呼び出されると、暗黙の QUIT コマンドは NULL 文字列の引数で終了します。
$ETRAP はグローバル・スコープを持ちます。 これは、通常、$ETRAP の設定の前には NEW $ETRAP が必要であることを意味します。 そうしなければ、現在のコンテキストで $ETRAP の値が設定されている場合、その値がそのコンテキストの範囲を超えて渡された後、制御は上位レベルのコンテキストにあるのに、$ETRAP に格納された値は存在し続けることになります。 このため、NEW $ETRAP を指定しないと、$ETRAP が設定されたときのコンテキストがもう存在しない場合、$ETRAP が予期しないタイミングで実行される可能性があります。
詳細は、"ObjectScript リファレンス" の "$ETRAP" 特殊変数を参照してください。
コンテキスト固有の $ETRAP エラー・ハンドラ
以下の手順を実行することで、あらゆるコンテキストでコンテキスト固有の $ETRAP エラー・ハンドラを作成できます。
-
NEW コマンドを使用して、$ETRAP の新しいコピーを作成します。
-
$ETRAP を新しい値に設定します。
ルーチンで最初に $ETRAP の新しいコピーを作成せずに $ETRAP を設定すると、現在のコンテキスト、それを呼び出したコンテキスト、およびコール・スタックに保存されている可能性のあるその他のコンテキストに、新しい $ETRAP エラー・ハンドラが作成されます。このため、$ETRAP を設定する前に、その新しいコピーを作成することをお勧めします。
$ETRAP の新しいコピーを作成することで $ETRAP はクリアされないことに注意してください。$ETRAP の値は、NEW コマンドによって変更されないまま保持されます。
以下の図は、$ETRAP エラー・ハンドラのスタックを作成する $ETRAP 割り当てのシーケンスを示しています。この図が示している内容は次のとおりです。
-
ルーチン A は、$ETRAP の新しいコピーを作成して、それを “GOTO ^ERR” に設定し、ルーチン B を呼び出すための DO コマンドを含んでいます。
-
ルーチン B は、$ETRAP に対して何も行わず (その結果、ルーチン A の $ETRAP エラー・ハンドラを継承し)、ルーチン C を呼び出すための DO コマンドを含んでいます。
-
ルーチン C は $ETRAP の新しいコピーを作成して、それを “GOTO ^CERR” に設定し、ルーチン D を呼び出すための DO コマンドを含んでいます。
-
ルーチン D は、$ETRAP の新しいコピーを作成した後、それをクリアして、コンテキストに $ETRAP エラー・ハンドラを残しません。
ルーチン D でエラーが発生した場合 ($ETRAP エラー・ハンドラが定義されていないコンテキスト)、InterSystems IRIS はルーチン D の DO フレームをコール・スタックから削除して、制御をルーチン C の $ETRAP エラー・ハンドラに移します。ルーチン C の $ETRAP エラー・ハンドラはさらに ^CERR にディスパッチしてエラーが処理されます。ルーチン C でエラーが発生した場合、InterSystems IRIS は制御をルーチン C の $ETRAP エラー・ハンドラに移しますが、エラーが発生しているのは $ETRAP エラー・ハンドラが定義されているコンテキストであるため、スタックを戻すことはしません。
$ETRAP エラー・ハンドラ
$ETRAP フロー制御オプション
$ETRAP エラー・ハンドラが、エラーを処理し、クリーンアップまたはエラー・ログ処理を実行するために呼び出された場合、次のフロー制御オプションがあります。
-
エラーを処理し、アプリケーションを継続します。
-
制御を別のエラー・ハンドラに渡します。
-
アプリケーションを終了します。
エラーの処理とアプリケーションの継続
エラーを処理するために $ETRAP エラー・ハンドラが呼び出されると、InterSystems IRIS は、エラー状態が解除されるまでそのエラー状態がアクティブであると見なします。エラー状態を解除するには、$ECODE 特殊変数を NULL 文字列に設定します。
SET $ECODE=""
$ECODE のクリアによって、プロセスのエラー・スタックもクリアされます。
エラー状態が解除されたら、通常は、GOTO コマンドを使用して、アプリケーションで事前設定されている再起動または継続のポイントに制御を移します。場合によっては、エラー状態の解除後に、終了して前のコンテキスト・レベルに戻る方が簡単なこともあります。
別のエラー・ハンドラへの制御の移動
エラー状態が解除されていない場合、$ETRAP エラー・ハンドラが呼び出されたコンテキストを QUIT コマンドが終了すると、InterSystems IRIS はコール・スタック上の別のエラー・ハンドラに制御を渡します。このため、$ECODE をクリアせずに、$ETRAP コンテキストから QUIT を実行することで、前のレベルのエラー・ハンドラに制御を渡すことができます。
ルーチン C から呼び出されたルーチン D に、制御を ^CERR に移すエラーが含まれる場合、前もって $ECODE が "" (空の文字列) に設定されていない ^CERR の QUIT コマンドは、前のコンテキスト・レベルの $ETRAP エラー・ハンドラに制御を移します。一方、$ECODE のクリアによってエラー状態が解除された場合、^CERR の QUIT は、ルーチン B の DO ^C コマンドに続く文に制御を移します。
アプリケーションの終了
コール・スタックに前のレベルのエラー・ハンドラが存在しておらず、$ETRAP エラー・ハンドラがエラー状態を解除せずに QUIT を実行した場合、アプリケーションが終了します。アプリケーション・モードでは その後 InterSystems IRIS は停止し、制御がオペレーティング・システムに渡されます。それに続いて、ターミナル・プロンプトが表示されます。
エラー状態が解除されているかどうかにかかわらず、$ETRAP エラー・ハンドラのコンテキストを終了するには、QUIT コマンドを使用することに留意してください。引数なしの QUIT が必要なコンテキスト・レベルと引数ありの QUIT が必要なコンテキスト・レベル (ユーザ定義関数のコンテキスト) で、同じ $ETRAP エラー・ハンドラを呼び出すことができるため、特定のコンテキスト・レベルで必要とされる QUIT コマンド形式を示すために $QUIT 特殊変数が指定されます。
$QUIT 特殊変数は、引数ありの QUIT が必要なコンテキストの場合は 1 を返し、引数なしの QUIT が必要なコンテキストの場合は 0 を返します。
$ETRAP エラー・ハンドラは、$QUIT を使用することで、以下のようにどちらの状況にも対処できます。
Quit:$QUIT "" Quit
該当する場合、$ETRAP エラー・ハンドラは、HALT コマンドを使用してアプリケーションを終了することができます。
エラー・ハンドラによるエラー処理
エラー・ハンドラでエラーが発生するとき、実行フローは、現在実行中のエラー・ハンドラ・タイプにより異なります。
$ZTRAP エラー・ハンドラでのエラー
$ZTRAP エラー・ハンドラで新規エラーが発生すると、InterSystems IRIS は、最初に検出したエラー・ハンドラに制御を渡し、必要に応じてコール・スタックを戻します。したがって、$ZTRAP エラーが現在のスタック・レベルで $ZTRAP をクリアせず、別のエラーが同じエラー・ハンドラで続けて発生した場合、$ZTRAP ハンドラが同じコンテキスト・レベルで再度呼び出されるため、無限ループの原因となります。これを回避するには、エラー・ハンドラの開始時点において $ZTRAP に他の値を設定します。
$ETRAP エラー・ハンドラでのエラー
$ETRAP エラー・ハンドラで新しいエラーが発生すると、InterSystems IRIS は、$ETRAP エラー・ハンドラが呼び出されたコンテキスト・レベルが削除されるまでコール・スタックを戻します。その後、InterSystems IRIS はコール・スタック上の次のエラー・ハンドラ (存在する場合) に制御を渡します。
$ZERROR 特殊変数と $ECODE 特殊変数のエラー情報
元のエラーの処理中に別のエラーが発生した場合、2 番目のエラー情報により、$ZERROR 特殊変数の最初のエラー情報が置き換えられます。しかし、InterSystems IRIS は、$ECODE 特殊変数に新規情報を追加します。2 番目のエラーのコンテキスト・レベルによっては、InterSystems IRIS は新しい情報をプロセス・エラー・スタックに追加する場合もあります。
$ECODE 特殊変数の既存の値が NULL 以外の場合、InterSystems IRIS は、新しいコンマ区切りの部分として、新規エラー・コードを現在の $ECODE 値に追加します。以下のいずれかの状況が発生するまで、$ECODE 特殊変数にエラー・コードが追加されます。
その後、次の新規エラー・コードにより、$ECODE にある現在のエラー・コード・リストが置き換えられます。
エラーが発生し、エラー・スタックが既に存在している場合、InterSystems IRIS は、エラー・スタックの同じコンテキスト・レベルに別のエラーに関する情報が存在しない限り、コンテキスト・レベルで新しいエラーに関する情報を記録します。この場合、エラー情報は、(エラー情報が既に記録されているかどうかにかかわらず) エラー・スタックの次のレベルに配置されます。
したがって、新規エラーのコンテキスト・レベルによっては、エラー・スタックは拡張される (1 つ以上のコンテキスト・レベルを追加される) か、あるいは、既存のエラー・スタックのコンテキスト・レベルに存在する情報が新規エラー情報を格納するために上書きされることがあります。
$ECODE 特殊変数をクリアすると、プロセス・エラー・スタックが消去されることに注意してください。
詳細は、"ObjectScript リファレンス" の "$ECODE" 特殊変数と "$ZERROR" 特殊変数を参照してください。$ZERROR エラーの取り扱いについての詳細は、"インターシステムズ・クラス・リファレンス" の %SYSTEM.ErrorOpens in a new tab クラス・メソッドを参照してください。
強制エラー
$ECODE 特殊変数を設定、あるいは ZTRAP コマンドを使用して、制御環境でエラーを発生させます。
$ECODE の設定
$ECODE 特殊変数に NULL 以外の文字列を設定し、エラーを発生させることができます。ルーチンで $ECODE に NULL 以外の文字列を設定すると、InterSystems IRIS は $ECODE に特定の文字列を設定し、その後、エラー状態を生成します。この状況で $ZERROR 特殊変数は、以下のエラー・テキストと共に設定されます。
<ECODETRAP>
その後、通常のアプリケーション・エラーのように、エラー・ハンドラに制御を渡します。
エラー・ハンドラにロジックを追加し、$ECODE の設定により発生させるエラーをチェックできます。エラー・ハンドラは、<ECODETRAP> エラー (例えば、“$ZE["ECODETRAP"” に対して $ZERROR をチェックするか、または選択する特定の文字列値に対して $ECODE をチェックできます。
アプリケーション固有エラーの生成
$ECODE の ANSI 標準フォーマットは、1 つ以上のコンマに囲まれたエラー・コードのリストです。
エラー・ハンドラで $ECODE に接頭語 “U” を持つ適切なエラー・メッセージを設定し、ANSI 標準に合う独自のエラー・コードを生成できます。
SET $ECODE=",Upassword expired,"
ターミナル・プロンプトでのエラー処理
エラー・ハンドラ・セットを持たないターミナル・プロンプトで InterSystems IRIS にサインオンした後エラーを生成する場合、InterSystems IRIS は、入力したコード行でエラーが発生すると、以下の手順を実行します。
-
InterSystems IRIS は、プロセスの主デバイスで、エラー・メッセージを表示します。
-
エラーが発生したコール・スタック・レベルでプロセスを中断します。
-
プロセスをターミナル・プロンプトに戻します。
エラー・メッセージ形式の理解
エラー・メッセージとして、InterSystems IRIS は以下の 3 行を表示します。
-
エラーが発生したすべてのソース・コード行
-
ソース・コードの行の下で、エラーが発生したコマンドを指定するキャレット (^)
-
$ZERROR のコンテンツを含む行
以下のターミナル・プロンプトの例では、2 番目の SET コマンドに未定義のローカル変数エラーがあります。
USER>WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED> *zzz
USER>
以下の例では、ターミナル・プロンプトから実行される mytest という名前のプログラムにコードと同じ行があります。
USER>DO ^mytest
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>
この場合、$ZERROR は、mytest の中で WriteOut という名前のラベルから 2 行のオフセット位置でエラーが発生したことを示しています。プロンプトが変更され、新規のプログラム・スタック・レベルが開始されたことを示している点に注意してください。
ターミナル・プロンプトの理解
既定で、ターミナル・プロンプトは現在のネームスペース名を示します。トランザクションが 1 つ以上開いている場合、$TLEVEL トランザクション・レベル・カウントも含まれます。ZNSPACE コマンドの説明に従って、既定のプロンプトを異なる内容で構成することができます。以下の例は、それらの既定の設定を示します。
ルーチンの実行中にエラーが発生すると、システムは、現在のプログラム・スタックを保存して、新規スタック・フレームを開始します。以下のような拡張プロンプトが表示されます。
この拡張プロンプトは、プログラム・スタックに 2 つのエントリがあり、その最後の方が DO (d で示されています) の呼び出しであることを示しています。このエラーにより、プログラム・スタックに 2 つのエントリが置かれることに注意してください。次の DO 実行エラーにより、以下のプロンプト結果となります。
説明の詳細は、“コマンド行ルーチンのデバッグ” の章の "ターミナル・プロンプトのプログラム・スタック情報表示" を参照してください。
エラーのリカバリ
以下のいずれかの手順を実行できます。
-
ターミナル・プロンプトからコマンドを発行します。
-
変数とグローバル・データを表示、修正します。
-
エラーと他のルーチンを含むルーチンを編集します。
-
他のルーチンを実行します。
これらの手順により、別のエラーを発生させる可能性もあります。
これらの手順の実行後、実行を再開する、あるいはプログラム・スタックの一部/すべてを削除することをお勧めします。
次に続くコマンドでの実行の再開
ターミナル・プロンプトから引数なしの GOTO を入力すれば、エラーを引き起こしたコマンドの次のコマンドで実行を再開できます。
USER>DO ^mytest
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>GOTO
world
USER>
別の行での実行の再開
ターミナル・プロンプトからラベル引数付きの GOTO を発行すると、別の行で実行を再開できます。
プログラム・スタックの削除
ターミナル・プロンプトから引数なしの QUIT コマンドを発行すると、プログラム・スタック全体を削除できます。
プログラム・スタックの部分削除
ターミナル・プロンプトから整数の引数付きの QUIT n コマンドを発行すると、最後の (または最後にある複数の) プログラム・スタック・エントリを削除できます。
USER 8d0>QUIT 1
USER 7E0>QUIT 3
USER 4d0>QUIT 1
USER 3E0>QUIT 1
USER 2d0>QUIT 1
USER 1S0>QUIT 1
USER>
この例では、プログラム・エラーによって 2 つのプログラム・スタック・エントリが作成されているので、GOTO を発行して実行を再開するには、“d” スタック・エントリに移動している必要があります。他に発生する内容に応じて、“d” スタック・エントリは偶数 (USER 2d0>) または奇数 (USER 3d0>) となります。
NEW $ESTACK を使用すれば、指定のプログラム・スタック・レベルで終了できます。
USER 4d0>NEW $ESTACK
USER 5E1>
/* more errors create more stack frames */
USER 11d7>QUIT $ESTACK
USER 4d0>
NEW $ESTACK コマンドにて、エントリが 1 つプログラム・スタックに追加されます。
アプリケーション・エラーのログ作成
InterSystems IRIS には、例外をアプリケーション・エラー・ログに記録する方法がいくつか用意されています。
%ETN を使用したアプリケーション・エラーのログ作成
%ETN ユーティリティは、例外をアプリケーション・エラー・ログに記録した後、終了します。%ETN (またはそのエントリポイントのいずれか) をユーティリティとして呼び出すことができます。
DO ^%ETN
または、$ZTRAP 特殊変数を %ETN (またはそのエントリポイントのいずれか) に設定することができます。
SET $ZTRAP="^%ETN"
%ETN またはそのエントリポイントのいずれかを指定できます。
-
FORE^%ETN (フォアグラウンド) は、例外を標準アプリケーション・エラー・ログに記録した後、HALT によって終了します。これは、ロールバック処理を起動します。これは、%ETN と同じ処理です。
-
BACK^%ETN (バックグラウンド) は、例外を標準アプリケーション・エラー・ログに記録した後、QUIT によって終了します。これは、ロールバック処理を起動しません。
-
LOG^%ETN は、例外を標準アプリケーション・エラー・ログに記録した後、QUIT によって終了します。これは、ロールバック処理を起動しません。この例外は、標準の %Exception.SystemExceptionOpens in a new tab またはユーザ定義の例外です。
例外を定義するには、LOG^%ETN を呼び出す前に $ZERROR を意味のある値に設定します。この値は、ログ・エントリのエラー・メッセージ・フィールドとして使用されます。ユーザ定義の例外を直接 LOG^%ETN: DO LOG^%ETN("This is my custom exception") に指定することもできます。この値は、ログ・エントリのエラー・メッセージ・フィールドとして使用されます。$ZERROR を NULL 文字列に設定すると (SET $ZERROR="")、LOG^%ETN は <LOG ENTRY> エラーを記録します。$ZERROR を <INTERRUPT> に設定すると (SET $ZERROR="<INTERRUPT>")、LOG^%ETN は <INTERRUPT LOG> エラーを記録します。
LOG^%ETN は、$HOROLOG 日付とエラー番号の 2 つの要素を持つ %List 構造を返します。
以下の例では、$ZERROR を変数に即座にコピーするお勧めのコーディング方法を使用しています。LOG^%ETN は %List 値を返します。
SET err=$ZERROR
/* error handling code */
SET rtn = $$LOG^%ETN(err)
WRITE "logged error date: ",$LIST(rtn,1),!
WRITE "logged error number: ",$LIST(rtn,2)
LOG^%ETN または BACK^%ETN を呼び出すと、使用可能なプロセス・メモリが自動的に増加し、処理が実行されて、$ZSTORAGE の元の値がリストアされます。ただし、<STORE> エラーの発生後に LOG^%ETN または BACK^%ETN を呼び出した場合、$ZSTORAGE の元の値をリストアすることによって別の <STORE> エラーがトリガされる可能性があります。このため、<STORE> エラーに対してこれらの %ETN エントリポイントが呼び出された場合は、増加した使用可能メモリが維持されます。
管理ポータルを使用したアプリケーション・エラー・ログの表示
管理ポータルで、[システム処理]→[システムログ]→[アプリケーションエラーログ] の順に選択します。これにより、アプリケーション・エラー・ログが発生したネームスペースの [ネームスペース] リストが表示されます。ヘッダを使用して、リストをソートできます。
ネームスペースの [日付] を選択すると、アプリケーション・エラー・ログが発生した日付と、その日付で記録されているエラーの数が表示されます。ヘッダを使用して、リストをソートできます。[フィルタ] を使用して、[日付] と [数量] の値に文字列をマッチングできます。
日付の [エラー] を選択すると、その日付のエラーが表示されます。[エラー#] の整数は、時系列順にエラーに割り当てられます。[エラー#] の *COM は、対象の日付のすべてのエラーに適用されるユーザ・コメントです。ヘッダを使用して、リストをソートできます。[フィルタ] を使用して、文字列をマッチングできます。
エラーの [詳細] を選択すると、[エラー詳細] ウィンドウが表示され、特殊変数の値や [スタック] の詳細など、エラー発生時の状態に関する情報が示されます。個々のエラーにユーザ・コメントを指定できます。
[ネームスペース]、[日付]、および [エラー] のリストにはチェックボックスが含まれており、これを使用して対応する 1 つ以上のエラーのエラー・ログを削除できます。削除するものにチェックを付けて、[削除] ボタンを選択します。
%ERN を使用したアプリケーション・エラー・ログの表示
%ERN ユーティリティは、%ETN エラー・トラップ・ユーティリティによって記録されたアプリケーション・エラーを検証します。%ERN は、現在のネームスペースについて記録されているすべてのエラーを返します。
%ERN ユーティリティを使用するには、以下の手順を実行します。
-
ターミナル・プロンプトで「DO ^%ERN」と入力します。このユーティリティの名前では大文字と小文字が区別されます。ユーティリティ内でのプロンプトへの応答では、大文字と小文字は区別されません。いずれのプロンプトでも、「?」を入力すると、そのプロンプトの構文オプションが一覧表示され、「?L」を入力すると、定義されている値がすべて一覧表示されます。Enter キーを押すと、前のレベルに戻ることができます。
-
For Date: プロンプトには、エラーが発生した日付を入力します。%DATE ユーティリティに使用可能ないずれの日付形式でも使用できます。年を省略すると、現在の年であると見なされます。このプロンプトからは、日付とその日付で記録されているエラーの数が返されます。または、以下の構文を使用して、このプロンプトからエラーのリストを取得できます。
-
「?L」を入力すると、エラーが生じた日付すべてのリストが、日付の新しい順に、記録済みエラーの数と共に表示されます。(T) 列は、何日前かを表します。(T) = 今日で、(T-7) = 7 日前です。対象の日のすべてのエラーにユーザ・コメントが定義されている場合、そのコメントが角かっこに囲まれて表示されます。リストの後に、For Date: プロンプトが再表示されます。日付または「T-n」を入力できます。
-
「[text」を入力すると、部分文字列 text を含むすべてのエラーが一覧表示されます。「<text」を入力すると、エラー名コンポーネントに部分文字列 text を含むすべてのエラーが一覧表示されます。「^text」を入力すると、エラー位置コンポーネントに部分文字列 text を含むすべてのエラーが一覧表示されます。リストの後に、For Date: プロンプトが再表示されます。日付を入力します。
-
Error: プロンプトには、確認したいエラーの整数番号を入力します。対象の日の最初のエラーの場合は「1」、2 つ目のエラーの場合は「2」というように入力します。または、疑問符 (?) を入力すると、取得可能な応答のリストが表示されます。このユーティリティは、エラーに関する情報として、エラー名、エラー位置、時間、システム変数値、およびエラー発生時に実行されていたコード行を表示します。
Error: プロンプトに「*」を入力すると、コメントを表示できます。「*」を入力すると、対象の日のエラーすべてに適用されている現在のユーザ定義のコメントが表示されます。次に、そのすべてのエラーに適用されている既存のコメントに置き換わる新しいコメントを入力するよう求められます。
-
Variable: プロンプトには、変数に関する情報を取得するためのさまざまなオプションを指定できます。ローカル変数の名前 (添え字なしまたは添え字付き) を指定した場合、%ERN は、スタック・レベルとその変数の値 (定義されている場合)、およびそのすべての下位ノードを返します。グローバル変数、プロセス・プライベート変数、または特殊システム変数を指定することはできません。
「?」を入力すると、Variable: プロンプトで指定できるその他の構文オプションが一覧表示されます。
-
*A : Variable: プロンプトに指定した場合、Device: プロンプトが表示されます。Return キーを押すと、現在のターミナル・デバイスに結果が表示されます。
-
*V : Variable: プロンプトに指定した場合、Variable(s): プロンプトが表示されます。このプロンプトには、添え字なしのローカル変数を 1 つ、または添え字なしのローカル変数のコンマ区切りのリストを指定します。添え字付きの変数は拒否されます。これに応じて、%ERN から Device: プロンプトが表示されます。Return キーを押すと、現在のターミナル・デバイスに結果が表示されます。%ERN は、指定された各変数の値 (定義されている場合) とそのすべての下位ノードを返します。
-
*L : Variable: プロンプトに指定した場合、変数を現在のパーティションにロードします。すべてのプライベート変数を (パブリックとして) ロードしてから、ロードされたプライベート変数と競合しないすべてのパブリック変数をロードします。