Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


Delphi TextFileを使った簡単テキストログ出力

  • 「エラーが発生しているけど、処理のどこで発生しているかわからない……」
  • 「運用端末でエラーが発生するけど、開発端末では問題ないからデバッグができない……」

といったケースのお問い合わせを、弊社テクニカルサポートでも時々頂戴します。

そんな時にログをテキストに逐次出力することで、
処理がどこまで成功していて、どこでエラーになったのか追跡することが容易になります。

そんなテキストログの出力手順をご紹介します。


【手順1:ログ書き出し処理の作成】

共通処理として以下のような手続き(procedure)を作成しておきます。
データモジュールやdprファイルのようなどこからでも呼び出せるユニット内に
記述しておくと、各ユニットに個別に記述する必要がないため便利です。

{*******************************************************************************
 目的: ログ書き出し処理(簡易版)
 引数: AMsg - 出力するメッセージ内容
 戻値: 
*******************************************************************************}
procedure WriteLog(AMsg: String);
var
  FLog: TextFile;       // テキストファイル制御変数
  SLog: string;         // 出力文字列(AMsgに情報追加し、実際に出力する文字列)
  sLogFileName: String; // 出力するログファイルのフルパス
begin
  // ログファイル名の取得 ※1
  sLogFileName := ChangeFileExt(Application.ExeName, '.log');
  // ログ書き出し処理
  try
    // ファイル変数の関連付け
    AssignFile(FLog, sLogFileName);
    try
      if FileExists(sLogFileName) then
        Append(FLog)     // ファイルの末尾に追加
      else
        Rewrite(FLog);   // 新しいファイルを作成し開く

      // 出力メッセージ文字列を作成 ※2
      SLog := FormatDateTime('YYYY/MM/DD HH:NN:SS', Now) + ' … ' + AMsg;
      // ファイルへ書き出し
      Writeln(FLog, SLog);
    finally
      // ファイル関連付け終了
      CloseFile(FLog);
    end;
  except
    // ログ書き出しに失敗した場合、0.5秒待機して再処理
    // (※ログファイルが掴まれていた場合は書き出しに失敗します)
    Sleep(500);
    WriteLog(AMsg); // 同じ引数でもう一度呼び出す

    // このまま抜ければエラーは画面に表示されない
  end;
end;
 

※1:この例では、EXEと同階層にEXEと同名のログファイルが作成されます。
   実際のコーディング時は任意のパスを(フルパスで)指定して下さい。

※2:この例では、タイムスタンプと引数のメッセージが以下のように出力されます。
   2021/06/14 12:02:05 … (1)データセットを閉じました

 

【手順2:ログ書き出し処理の呼び出し】

実際の処理中では、以下の例のように記述することで、
手順1で作成した「WriteLog」を通るたびにテキスト出力処理が行われます。

(※コンパイルエラーになった場合は、uses節に「System」を追加)

procedure TForm1.Button2Click(Sender: TObject);
begin
  FDQuery1.Close;
  WriteLog('(1)データセットを閉じました'); // ★★テキストログ出力
  FDQuery1.SQL.Text := '~~~';
  FDQuery1.ParamByName(~~~).AsString := '~~~';
  WriteLog('(2)SQLとパラメータをセットしました'); // ★★テキストログ出力
  Call4001.Execute;
  WriteLog('(3)事前に呼んでおくCLを呼出完了しました'); // ★★テキストログ出力
  try
    FDQuery1.Open;
    WriteLog('(4)FDQuery1のオープンが完了しました'); // ★★テキストログ出力
  except
    on e: Exception do
    begin
      // エラー発生時にも活用できる
      WriteLog('エラー発生!  エラークラス名=' + e.ClassName + '  ' +
               'エラーメッセージ=' + e.Message); // ★★テキストログ出力

      // 本来出るはずだったエラーを画面に再表示する
      //(raiseしていないと、エラーを画面に出さずに抜けられる)
      raise; 
    end;
  end;
end;
 

 

 
<出力されるテキストのイメージ>

この例では、例えばエラー発生時に(1)(2)(3)までのログのみ残っていて
次の行が「エラー発生!」のログになっていた場合、
(4)に到達することなくエラーになったということが読み取れます。

そこから、ロジックのどの部分でエラーが発生したかが特定しやすくなります。