error_log()

PHP標準の組み込みロギング関数。外部依存関係なしで即座に利用可能で、ファイル、システムログ、メール等への出力をサポート。シンプルな文字列ベースのログ出力に適しているが、構造化ログや高度な機能は制限的。

ロギングライブラリPHP組み込み関数デバッグシンプル標準機能

ライブラリ

error_log()

概要

error_log()は、PHP標準の組み込みロギング関数で、外部依存関係なしで即座に利用可能な最もシンプルなログ出力手段として広く使用されています。システムログ、ファイル、メール等への柔軟なログ出力をサポートし、小規模スクリプトやクイックデバッグ、学習目的に最適。プロダクション環境では機能制限があるものの、PHP開発者にとって基本的なデバッグ・トラブルシューティングの第一歩となる重要なツールです。

詳細

error_log()は2025年でもPHP開発における基本的なロギング手段として継続使用されています。4つの出力先タイプ(システムログ、メール、ファイル、直接出力)により多様な用途に対応し、追加設定なしで即座に利用可能な利便性を提供。シンプルな文字列ベースのメッセージ出力により、デバッグやエラー追跡において迅速な問題特定を支援します。本格的なWebアプリケーションでは高度なログ管理機能(ログレベル、ローテーション、構造化ログ等)が制限的なため、Monolog等の専用ライブラリへの移行が推奨される傾向にあります。

主な特徴

  • ゼロ設定: PHP標準関数のため追加インストールや設定が不要
  • 多様な出力先: システムログ、ファイル、メール、SAPI出力への対応
  • 即座に利用可能: 任意のPHPスクリプトで即座に呼び出し可能
  • 軽量性: オーバーヘッドが最小限でパフォーマンス影響なし
  • クロスプラットフォーム: Unix/Linux、Windows環境での一貫動作
  • デバッグ支援: tailコマンドとの連携によるリアルタイム監視

メリット・デメリット

メリット

  • PHP標準関数のため設定不要で即座に利用開始
  • 外部依存関係がなく軽量でシンプルな実装
  • 学習コストが低く初心者でも容易に使用可能
  • デバッグやトラブルシューティングでの迅速な問題特定
  • システムログとの統合により管理ツールでの一元監視
  • クロスプラットフォーム対応で環境依存性が低い

デメリット

  • ログレベル(INFO、WARNING、ERROR等)の概念が不在
  • 構造化ログ(JSON、XML等)への対応が手動実装必要
  • ログローテーションやアーカイブ機能なし
  • 複数ファイルへの同時出力やフィルタリング機能の制限
  • 大量ログ出力時のパフォーマンス最適化が困難
  • 企業レベルの高度なログ管理・解析機能の不足

参考ページ

書き方の例

インストールと基本セットアップ

<?php
// error_log()はPHP標準関数のため追加インストール不要
// php.iniでログ設定を確認・調整(推奨)

// 基本的なログ設定確認
echo "error_reporting: " . error_reporting() . "\n";
echo "log_errors: " . ini_get('log_errors') . "\n";
echo "error_log: " . ini_get('error_log') . "\n";

// 本番環境推奨設定
ini_set('display_errors', 0);  // エラー画面表示を無効化
ini_set('log_errors', 1);      // ログ記録を有効化
ini_set('error_log', '/var/log/php/php_errors.log');  // ログファイル指定

// error_log()基本構文
// bool error_log(string $message, int $message_type = 0, ?string $destination = null, ?string $additional_headers = null)

// 最もシンプルなログ出力(システムログへ)
error_log("アプリケーション開始");
?>

基本的なログ出力(システムログ/ファイル/メール)

<?php
// 1. システムログへの出力(デフォルト、message_type = 0)
error_log("データベース接続エラーが発生しました");
error_log("ユーザー認証に失敗: " . $username);

// 2. 指定ファイルへの出力(message_type = 3)
$logFile = '/var/log/myapp/application.log';
error_log("カスタムログメッセージ", 3, $logFile);
error_log("処理時間: " . $processingTime . "秒", 3, $logFile);

// 3. メール送信によるログ(message_type = 1)
$adminEmail = '[email protected]';
$criticalError = "CRITICAL: サーバーディスク容量不足 - 残り容量: 5%";
error_log($criticalError, 1, $adminEmail);

// 4. SAPI(Server API)への直接出力(message_type = 4)
// 通常はApacheのエラーログ等に出力される
error_log("SAPI直接出力テスト", 4);

// 日時付きログの実装例
function logWithTimestamp($message, $logFile = null) {
    $timestamp = date('Y-m-d H:i:s');
    $formattedMessage = "[$timestamp] $message";
    
    if ($logFile) {
        error_log($formattedMessage, 3, $logFile);
    } else {
        error_log($formattedMessage);
    }
}

// 使用例
logWithTimestamp("ユーザーログイン: " . $userId);
logWithTimestamp("API呼び出し失敗: " . $apiEndpoint, '/var/log/api_errors.log');

// コンテキスト情報付きログ
function logWithContext($message, $context = [], $logFile = null) {
    $contextStr = empty($context) ? '' : ' | Context: ' . json_encode($context);
    $fullMessage = $message . $contextStr;
    
    if ($logFile) {
        error_log($fullMessage, 3, $logFile);
    } else {
        error_log($fullMessage);
    }
}

// 使用例
logWithContext(
    "決済処理エラー", 
    [
        'user_id' => $userId,
        'amount' => $amount,
        'payment_method' => $paymentMethod
    ],
    '/var/log/payment_errors.log'
);
?>

エラーハンドリングとデバッグ実践

<?php
// カスタムエラーハンドラーでerror_log()を活用
function customErrorHandler($severity, $message, $filename, $lineno) {
    $errorTypes = [
        E_ERROR => 'ERROR',
        E_WARNING => 'WARNING', 
        E_NOTICE => 'NOTICE',
        E_USER_ERROR => 'USER_ERROR',
        E_USER_WARNING => 'USER_WARNING',
        E_USER_NOTICE => 'USER_NOTICE'
    ];
    
    $errorType = $errorTypes[$severity] ?? 'UNKNOWN';
    $logMessage = sprintf(
        "%s: %s in %s on line %d",
        $errorType,
        $message,
        $filename,
        $lineno
    );
    
    error_log($logMessage, 3, '/var/log/php/custom_errors.log');
    
    // 本番環境では処理を継続、開発環境では停止
    if (defined('ENVIRONMENT') && ENVIRONMENT === 'production') {
        return true;  // エラー処理を継続
    }
    return false;  // デフォルトエラーハンドラーに移譲
}

// カスタムエラーハンドラーを設定
set_error_handler('customErrorHandler');

// 例外ハンドラーとの組み合わせ
function logException($exception) {
    $message = sprintf(
        "Uncaught %s: %s in %s:%d\nStack trace:\n%s",
        get_class($exception),
        $exception->getMessage(),
        $exception->getFile(),
        $exception->getLine(),
        $exception->getTraceAsString()
    );
    
    error_log($message, 3, '/var/log/php/exceptions.log');
}

set_exception_handler('logException');

// デバッグ用のロギング関数
function debugLog($variable, $label = 'DEBUG', $logFile = '/tmp/debug.log') {
    $output = "[$label] " . date('Y-m-d H:i:s') . " | ";
    
    if (is_array($variable) || is_object($variable)) {
        $output .= print_r($variable, true);
    } else {
        $output .= var_export($variable, true);
    }
    
    error_log($output, 3, $logFile);
}

// 使用例
$userData = ['id' => 123, 'name' => '田中太郎', 'email' => '[email protected]'];
debugLog($userData, 'USER_DATA');

// パフォーマンス測定ログ
function measureAndLog($callback, $operationName, $logFile = '/var/log/performance.log') {
    $startTime = microtime(true);
    $startMemory = memory_get_usage();
    
    try {
        $result = $callback();
        $success = true;
        $error = null;
    } catch (Exception $e) {
        $result = null;
        $success = false;
        $error = $e->getMessage();
    }
    
    $endTime = microtime(true);
    $endMemory = memory_get_usage();
    
    $logData = [
        'operation' => $operationName,
        'execution_time' => round(($endTime - $startTime) * 1000, 2) . 'ms',
        'memory_used' => round(($endMemory - $startMemory) / 1024, 2) . 'KB',
        'success' => $success,
        'error' => $error,
        'timestamp' => date('c')
    ];
    
    error_log(json_encode($logData), 3, $logFile);
    
    return $result;
}

// 使用例
$result = measureAndLog(function() {
    // 重い処理のシミュレーション
    sleep(1);
    return "処理完了";
}, "heavy_calculation");
?>

実用的なログ管理とモニタリング

<?php
// レベル別ログクラス(error_log()ベース)
class SimpleLogger {
    private $logFile;
    private $logLevel;
    
    const LEVELS = [
        'DEBUG' => 0,
        'INFO' => 1,
        'WARNING' => 2,
        'ERROR' => 3,
        'CRITICAL' => 4
    ];
    
    public function __construct($logFile = null, $logLevel = 'INFO') {
        $this->logFile = $logFile ?: '/var/log/php/simple_logger.log';
        $this->logLevel = self::LEVELS[$logLevel] ?? 1;
    }
    
    private function log($level, $message, $context = []) {
        if (self::LEVELS[$level] < $this->logLevel) {
            return;  // ログレベルが不十分
        }
        
        $timestamp = date('Y-m-d H:i:s');
        $pid = getmypid();
        $contextStr = empty($context) ? '' : ' ' . json_encode($context);
        
        $logEntry = sprintf(
            "[%s] [PID:%d] [%s] %s%s",
            $timestamp,
            $pid,
            $level,
            $message,
            $contextStr
        );
        
        error_log($logEntry, 3, $this->logFile);
    }
    
    public function debug($message, $context = []) {
        $this->log('DEBUG', $message, $context);
    }
    
    public function info($message, $context = []) {
        $this->log('INFO', $message, $context);
    }
    
    public function warning($message, $context = []) {
        $this->log('WARNING', $message, $context);
    }
    
    public function error($message, $context = []) {
        $this->log('ERROR', $message, $context);
    }
    
    public function critical($message, $context = []) {
        $this->log('CRITICAL', $message, $context);
        
        // クリティカルエラーはメールでも通知
        if (defined('ADMIN_EMAIL')) {
            error_log("CRITICAL ERROR: $message", 1, ADMIN_EMAIL);
        }
    }
}

// 使用例
$logger = new SimpleLogger('/var/log/myapp/app.log', 'INFO');

$logger->info("アプリケーション開始");
$logger->warning("設定ファイルが見つかりません", ['file' => 'config.ini']);
$logger->error("データベース接続失敗", ['host' => 'localhost', 'port' => 3306]);

// ログローテーション管理
class LogRotator {
    public static function rotateIfNeeded($logFile, $maxSize = 10485760) { // 10MB
        if (!file_exists($logFile)) {
            return;
        }
        
        if (filesize($logFile) > $maxSize) {
            $backupFile = $logFile . '.' . date('Ymd_His');
            rename($logFile, $backupFile);
            
            // 圧縮(gzipが使用可能な場合)
            if (function_exists('gzencode')) {
                $compressed = gzencode(file_get_contents($backupFile));
                file_put_contents($backupFile . '.gz', $compressed);
                unlink($backupFile);
            }
        }
    }
}

// 定期的なログローテーション実行
LogRotator::rotateIfNeeded('/var/log/myapp/app.log');

// セキュリティ対応ログ
function secureLog($message, $logFile = '/var/log/security.log') {
    // 機密情報のマスキング
    $maskedMessage = preg_replace('/password[=:\s]+\S+/i', 'password=***', $message);
    $maskedMessage = preg_replace('/token[=:\s]+\S+/i', 'token=***', $maskedMessage);
    $maskedMessage = preg_replace('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/', '***@***.***', $maskedMessage);
    
    $clientIP = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
    
    $secureLogEntry = sprintf(
        "[%s] [IP:%s] [UA:%s] %s",
        date('Y-m-d H:i:s'),
        $clientIP,
        substr($userAgent, 0, 100),  // User-Agentは100文字まで
        $maskedMessage
    );
    
    error_log($secureLogEntry, 3, $logFile);
}

// 使用例
secureLog("ログイン試行: [email protected] password=secret123");
secureLog("API呼び出し: token=abc123xyz endpoint=/api/users");

// リアルタイムモニタリング支援
// unix環境でtailコマンドと連携してリアルタイム監視
// tail -f /var/log/myapp/app.log | grep ERROR
// tail -f /var/log/myapp/app.log | grep "$(date '+%Y-%m-%d')"
?>

本番環境最適化とトラブルシューティング

<?php
// 本番環境用の設定最適化
class ProductionErrorLogger {
    private static $initialized = false;
    
    public static function initialize() {
        if (self::$initialized) return;
        
        // 本番環境推奨設定
        ini_set('display_errors', 0);
        ini_set('display_startup_errors', 0);
        ini_set('log_errors', 1);
        ini_set('log_errors_max_len', 1024);
        ini_set('ignore_repeated_errors', 1);
        ini_set('ignore_repeated_source', 1);
        
        // ログファイル設定
        $logDir = '/var/log/php';
        if (!is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }
        ini_set('error_log', $logDir . '/production_errors.log');
        
        self::$initialized = true;
    }
    
    // 重要度別ログ出力
    public static function logCritical($message, $context = []) {
        $logEntry = self::formatLogEntry('CRITICAL', $message, $context);
        error_log($logEntry, 3, '/var/log/php/critical_errors.log');
        
        // クリティカルエラーは即座にメール通知
        if (defined('EMERGENCY_EMAIL')) {
            error_log($logEntry, 1, EMERGENCY_EMAIL);
        }
    }
    
    public static function logBusinessLogic($message, $context = []) {
        $logEntry = self::formatLogEntry('BUSINESS', $message, $context);
        error_log($logEntry, 3, '/var/log/php/business_logic.log');
    }
    
    public static function logPerformance($operation, $duration, $memory = null) {
        $perfData = [
            'operation' => $operation,
            'duration_ms' => round($duration * 1000, 2),
            'memory_mb' => $memory ? round($memory / 1024 / 1024, 2) : null,
            'timestamp' => date('c')
        ];
        
        error_log(json_encode($perfData), 3, '/var/log/php/performance.log');
    }
    
    private static function formatLogEntry($level, $message, $context = []) {
        return sprintf(
            "[%s] [%s] [PID:%d] %s %s",
            date('Y-m-d H:i:s'),
            $level,
            getmypid(),
            $message,
            empty($context) ? '' : '| Context: ' . json_encode($context)
        );
    }
}

// 初期化
ProductionErrorLogger::initialize();

// エラー発生時の総合ログ収集
function collectSystemInfo() {
    return [
        'php_version' => PHP_VERSION,
        'memory_usage' => memory_get_usage(true),
        'memory_peak' => memory_get_peak_usage(true),
        'time' => microtime(true),
        'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
        'http_method' => $_SERVER['REQUEST_METHOD'] ?? '',
        'user_ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
    ];
}

// データベース操作ログ
function logDatabaseOperation($query, $params = [], $duration = null, $error = null) {
    $logData = [
        'query' => substr($query, 0, 200), // クエリを200文字に制限
        'params_count' => count($params),
        'duration_ms' => $duration ? round($duration * 1000, 2) : null,
        'error' => $error,
        'timestamp' => date('c')
    ];
    
    $logLevel = $error ? 'ERROR' : 'INFO';
    $message = sprintf("[DB_%s] %s", $logLevel, json_encode($logData));
    
    error_log($message, 3, '/var/log/php/database.log');
}

// ログファイル管理ツール
class LogFileManager {
    // ログファイルサイズ監視
    public static function checkLogSize($logFile, $maxSizeMB = 50) {
        if (!file_exists($logFile)) return;
        
        $sizeMB = filesize($logFile) / 1024 / 1024;
        if ($sizeMB > $maxSizeMB) {
            error_log(
                "WARNING: ログファイルサイズが制限を超過 {$logFile}: {$sizeMB}MB",
                3,
                '/var/log/php/system_alerts.log'
            );
        }
    }
    
    // 古いログファイルの自動削除
    public static function cleanOldLogs($logDir, $daysToKeep = 30) {
        $files = glob($logDir . '/*.log.*');
        $cutoffTime = time() - ($daysToKeep * 24 * 60 * 60);
        
        foreach ($files as $file) {
            if (filemtime($file) < $cutoffTime) {
                unlink($file);
                error_log("古いログファイルを削除: $file", 3, '/var/log/php/maintenance.log');
            }
        }
    }
}

// 使用例
try {
    // 重要な処理の実行
    $startTime = microtime(true);
    $startMemory = memory_get_usage();
    
    // ビジネスロジック実行
    performCriticalOperation();
    
    $duration = microtime(true) - $startTime;
    $memoryUsed = memory_get_usage() - $startMemory;
    
    ProductionErrorLogger::logPerformance('critical_operation', $duration, $memoryUsed);
    ProductionErrorLogger::logBusinessLogic('クリティカル処理完了', collectSystemInfo());
    
} catch (Exception $e) {
    ProductionErrorLogger::logCritical(
        'クリティカル処理でエラー発生: ' . $e->getMessage(),
        [
            'file' => $e->getFile(),
            'line' => $e->getLine(),
            'trace' => $e->getTraceAsString()
        ]
    );
}

// 定期メンテナンス(cron等で実行)
LogFileManager::checkLogSize('/var/log/php/production_errors.log');
LogFileManager::cleanOldLogs('/var/log/php', 30);
?>