今日からおこなう簡易エラーロギング - 外部DBを用いたロギング
FileMaker Webアプリケーションに限らず、エラーのロギングはトラブルシューティング時に大変有用な情報となる。エラーが起きた際にエンドユーザから問い合わせが入った時点でトラブルシューティングに入る場合と、エラーの前兆をメールで受信するなり、ログに記録するなりであらかじめ準備ができている場合とでは解決にかかるまでの時間も違ってくる。複雑なFileMakerファイルの場合、エラーの原因特定にも一苦労だ。
エラーが発生した際に、エラー番号のほかにも実際に使用されていた引数やそのリクエストの日時の記録が残っていると、トラブルシューティングがぐっとやりやすくなる。たとえば特定の時間にFileMakerエラー16: 「処理に失敗したため、再試行が必要です(たとえば、ユーザクエリーなど)」が頻発していることがログに残っている場合、アクセス過多の時間帯に負荷のかかる処理が集中していることがわかる。
FileMakerデータベースでエラーロギングを行う手もあるが、ログという性質上、あまり適していない面も見受けられる。メリットとデメリットを挙げてみよう。
メリット
- FileMakerを使用する分、ほかのFileMakerアプリケーションと連携しやすい
- FileMakerから扱えるファイル形式(tab, csv, dbf, mer, html, fp7, xml, xls, xlsx)でエラーログを出力できる。その際の操作も簡単
デメリット
- エラー発生後、さらにFileMakerにアクセスするので処理が遅くなる
- 保存したい情報やログの量が増えるほど、処理が遅くなっていく
- FileMaker Server自体にトラブルが起こっている場合、ロギングが行えない
とくにデメリット3番目の「FileMaker Server自体にトラブルが起こっている場合、ロギングが行えない」はかなりの痛手だ。FileMakerファイルやサーバ自体にトラブルが起こっている場合、当然FileMakerにログを残すことはできない。原因の切り分けにも支障が出るので、ログを残す場合はなるべくFileMaker以外の方法で実装を行いたいところだ。
CSVなどのファイルとして保存、MySQLやPostgreSQLなどの外部データベースに保存……実装方法はいろいろあるが、ここではSQLiteに保存する方法を紹介しよう。
SQLiteを用いたロギング
まずはロギングする情報を整理しよう。ここではシリアル番号を含めて8つの情報をログとして残すようにする。
- id : シリアル番号
- uri : FileMaker Web公開エンジンに渡すクエリ
- saveLayout : 処理対象のレイアウト
- userId : 処理をおこなったユーザID
- userName : 処理をおこなったユーザ名
- date : 処理日時
- recid : レコードID
- errorCode : FileMakerエラーコード
まずはSQLiteのデータベースを作成してみよう。ターミナルを起動し、sqlite3を起動する。
% sqlite3 logs.db
続いてテーブルとフィールドを作成する。
sqlite> create table logs
(
id INTEGER NOT NULL PRIMARY KEY,
uri TEXT,
saveLayout TEXT,
userId TEXT,
userName TEXT,
date DATE,
recid NUMERIC,
errorCode NUMERIC
);
テーブルを作成したら、.schemaで作成したテーブルを確認する。
sqlite> .schema
これでSQLiteの準備がととのった。.quitでsqliteを終了する。
sqlite> .quit
それではPHP側でFileMakerエラーが発生した場合にエラーをSQLite3に保存するコードを記述してみよう。
SetDBData('fxphp_tips.fp7', $layoutName);
$data->SetDBUserPass('admin','');
$data->SetCharacterEncoding('utf8');
$data->SetDataParamsEncoding('utf8');
$data->AddDBParam('-recid', $_POST['-recid']);
$result = $data->FMFind();
if ( '0' === (string)$result['errorCode'] )
{
// 正常処理
}
else
{
echo 'FileMaker Error: ' . $result['errorCode'] . ' - ' . $errorsList[$result['errorCode']];
// SQLiteにエラーログを保存
$dbh = new PDO('sqlite:./logs.db', null, null);
$stmt = null;
$stmt = $dbh->prepare
(
'
INSERT INTO
logs ( uri, saveLayout, userId, userName, date, recid, errorCode)
VALUES
(
:uri,
:saveLayout,
:userId,
:userName,
:date,
:recid,
:errorCode
)
'
);
$stmt->bindParam(':uri', $s_uri);
$stmt->bindParam(':saveLayout', $s_saveLayout);
$stmt->bindParam(':userId', $s_userId);
$stmt->bindParam(':userName', $s_userName);
$stmt->bindParam(':date', $s_date);
$stmt->bindParam(':recid', $s_recid);
$stmt->bindParam(':errorCode', $s_errorCode);
$s_uri = $result['URL'];
$s_saveLayout = $layoutName;
$s_userId = $_SESSION['user_id'];
$s_userName = $_SESSION['user_name'];
$s_date = date('Y/m/d H:i:s');
$s_recid = $_POST['-recid'];
$s_errorCode = (int)$result['errorCode'];
$stmt->execute();
}
?>
ユーザIDとユーザ名はセッション変数から、recidはPOST経由で取得されるものとしている。FileMakerが実際にリクエストに使用したURLは、FX.phpから返る配列から取得した。それでは実際に動作を確認してみよう。
ログに保存する内容をアプリケーションに沿った内容にすることで、さらにトラブルシューティングが行いやすくなる。たとえば、案件テーブルの場合は案件Noや顧客名を保存しておくなどだ。特定の環境下で発現するエラーを追いかけるのに役立つことだろう。
ターミナルなどのCUIでの操作が取っつきづらいという方は、GUIでSQLiteを操作できるソフトウェアを使うのも手だ。自分の使いやすいものを探してみて欲しい。
- SQLite Administrator : Windows用のSQLite管理ツール
- SQLite Manager Firefox Extension : XULベースのアプリケーション。Firefoxのエクステンションとして動作する
- Lita : Adobe AIRベースのアプリケーション。Windows, Mac OS X, Linux上で動作する
以上、SQLiteを用いたエラーロギングの方法を紹介した。先に紹介したFX.phpのメールロギングとうまく併用して、トラブルの予兆を察し、有事の際でも素早く適切に対応ができるようになっておきたいところだ。