はじめに
PHPでアプリケーションを開発する際、ログ出力は非常に重要な機能です。デバッグ情報の記録、エラーの追跡、システムの監視など、様々な場面で活用されます。
今回は、PHPの標準的なログ出力関数と、よく使われるカスタム関数「log_print」の実装について詳しく解説します。
PHPの標準ログ出力関数
1. error_log() 関数
最も一般的に使用されるログ出力関数です。
// 基本的な使い方
error_log("エラーメッセージ");
// ファイルに出力
error_log("デバッグ情報", 3, "/var/log/myapp.log");
// メール送信
error_log("重要なエラー", 1, "admin@example.com");
パラメータ説明:
- 第1引数:ログメッセージ
- 第2引数:出力先の指定(0=システムログ、1=メール、3=ファイル、4=直接出力)
- 第3引数:出力先の詳細(ファイルパスやメールアドレス)
2. syslog() 関数
システムログに出力する関数です。
// システムログの開始
openlog("MyApp", LOG_PID | LOG_PERROR, LOG_LOCAL0);
// ログ出力
syslog(LOG_WARNING, "警告メッセージ");
syslog(LOG_ERR, "エラーメッセージ");
// システムログの終了
closelog();
3. print_r() / var_dump()
変数の内容をデバッグ用に出力する関数です。
$data = ['name' => '太郎', 'age' => 30];
// print_rでの出力
error_log(print_r($data, true), 3, "/tmp/debug.log");
// var_dumpでの出力
ob_start();
var_dump($data);
$output = ob_get_clean();
error_log($output, 3, "/tmp/debug.log");
カスタムlog_print関数の実装
多くの開発現場では、より使いやすいカスタムログ関数「log_print」を作成します。以下に実装例を示します。
基本的なlog_print関数
function log_print($message, $level = 'INFO', $logfile = null) {
// デフォルトのログファイル
if ($logfile === null) {
$logfile = '/var/log/app.log';
}
// タイムスタンプの生成
$timestamp = date('Y-m-d H:i:s');
// ログレベルの正規化
$level = strtoupper($level);
// ログメッセージの整形
$log_message = "[{$timestamp}] [{$level}] {$message}" . PHP_EOL;
// ファイルに追記
file_put_contents($logfile, $log_message, FILE_APPEND | LOCK_EX);
}
使用例
// 基本的な使用法
log_print("アプリケーションが開始されました");
log_print("データベース接続エラー", 'ERROR');
log_print("ユーザーがログインしました", 'INFO', '/var/log/user.log');
// 配列やオブジェクトのログ出力
$user_data = ['id' => 123, 'name' => '田中太郎'];
log_print("ユーザーデータ: " . json_encode($user_data, JSON_UNESCAPED_UNICODE));
高度なlog_print関数
より実用的な機能を追加した版:
class Logger {
private static $logfile = '/var/log/app.log';
private static $max_file_size = 10485760; // 10MB
public static function log_print($message, $level = 'INFO', $context = []) {
// ログローテーション
self::rotateLogIfNeeded();
// バックトレースの取得(呼び出し元の特定)
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$caller = isset($backtrace[1]) ?
basename($backtrace[1]['file']) . ':' . $backtrace[1]['line'] :
'unknown';
// メッセージの整形
$timestamp = date('Y-m-d H:i:s');
$level = strtoupper($level);
$pid = getmypid();
// コンテキスト情報の追加
$context_str = !empty($context) ?
' ' . json_encode($context, JSON_UNESCAPED_UNICODE) : '';
$log_message = "[{$timestamp}] [{$level}] [PID:{$pid}] [{$caller}] {$message}{$context_str}" . PHP_EOL;
// ファイルに出力
file_put_contents(self::$logfile, $log_message, FILE_APPEND | LOCK_EX);
// 重要なレベルの場合はエラーログにも出力
if (in_array($level, ['ERROR', 'CRITICAL', 'EMERGENCY'])) {
error_log($message);
}
}
private static function rotateLogIfNeeded() {
if (file_exists(self::$logfile) && filesize(self::$logfile) > self::$max_file_size) {
$backup_name = self::$logfile . '.' . date('YmdHis');
rename(self::$logfile, $backup_name);
}
}
// 各レベル専用のメソッド
public static function debug($message, $context = []) {
self::log_print($message, 'DEBUG', $context);
}
public static function info($message, $context = []) {
self::log_print($message, 'INFO', $context);
}
public static function warning($message, $context = []) {
self::log_print($message, 'WARNING', $context);
}
public static function error($message, $context = []) {
self::log_print($message, 'ERROR', $context);
}
}
高度な使用例
// 基本的な使用
Logger::info("アプリケーションが開始されました");
// コンテキスト情報付き
Logger::error("データベース接続失敗", [
'host' => 'localhost',
'database' => 'myapp',
'error_code' => 2002
]);
// レベル別メソッドの使用
Logger::debug("デバッグ情報");
Logger::warning("警告メッセージ");
Logger::error("エラーが発生しました");
ログ出力のベストプラクティス
1. ログレベルの使い分け
// DEBUG: 開発時のデバッグ情報
Logger::debug("変数の値: " . $variable);
// INFO: 一般的な情報
Logger::info("ユーザー登録完了: user_id=" . $user_id);
// WARNING: 警告(処理は継続)
Logger::warning("古いAPIを使用しています");
// ERROR: エラー(処理に影響)
Logger::error("ファイルの読み込みに失敗しました");
2. セキュリティ対策
function secure_log_print($message, $level = 'INFO') {
// 個人情報のマスク処理
$message = preg_replace('/password=\w+/', 'password=***', $message);
$message = preg_replace('/\d{4}-\d{4}-\d{4}-\d{4}/', '****-****-****-****', $message);
Logger::log_print($message, $level);
}
3. パフォーマンス対策
function conditional_log_print($message, $level = 'INFO') {
// 本番環境ではDEBUGログを出力しない
if ($level === 'DEBUG' && $_ENV['APP_ENV'] === 'production') {
return;
}
Logger::log_print($message, $level);
}
まとめ
PHPでのログ出力は、標準関数のerror_log()
やsyslog()
から始まり、プロジェクトの要件に応じてカスタム関数log_print
を実装することが一般的です。
重要なポイント:
- ログレベルを適切に使い分ける
- セキュリティを考慮した情報のマスク処理
- ログローテーションによるディスク容量の管理
- 本番環境でのパフォーマンスへの配慮
適切なログ実装により、アプリケーションの保守性と信頼性を大幅に向上させることができます。