php5.2 日志类,每小时一个文件,超过10MB创建新文件
效果


LogHelper.php
<?php // ===================== LogHelper.php PHP 5.2兼容版本 ===================== /** * 日志助手类 - PHP 5.2兼容版本 * 使用方法: LogHelper::write("日志消息"); */ // 定义日志级别常量(PHP 5.2不支持类常量数组) define('LOG_LEVEL_INFO', 'INFO'); define('LOG_LEVEL_WARN', 'WARN'); define('LOG_LEVEL_ERROR', 'ERROR'); define('LOG_LEVEL_DEBUG', 'DEBUG'); class LogHelper { // 私有属性(PHP 5.2不支持直接属性赋值,需要在构造函数中初始化) private static $lastMaintenance = 0; private static $maxFileSize = 10485760; // 10MB = 10 * 1024 * 1024 /** * 写入日志 * @param string $message 日志消息 * @param string $level 日志级别 * @param string $category 日志分类 * @return bool 是否写入成功 */ public static function write($message, $level = 'INFO', $category = '') { // 设置时区 date_default_timezone_set('asia/chongqing'); // 获取当前时间 $now = time(); $currentDate = date('Y-m-d', $now); $currentDateTime = date('Y-m-d H:i:s', $now); // 基础日志目录 $baseLogDir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'logs'; // 构建每日目录路径 $dailyLogDir = $baseLogDir . DIRECTORY_SEPARATOR . $currentDate; // 创建目录(如果不存在) if (!self::ensureDirectory($dailyLogDir)) { error_log("无法创建日志目录: $dailyLogDir"); return false; } // 构建日志文件名(按小时分组) $currentHour = date('Y-m-d H', $now); $baseLogFile = $dailyLogDir . DIRECTORY_SEPARATOR . '' . $currentHour . '.log'; // 查找可用的日志文件(处理10MB轮换) $logFile = self::findAvailableLogFile($baseLogFile, $dailyLogDir, $currentHour); // 构建日志内容 //$logContent = '[' . $currentDateTime . '] [' . str_pad($level, 5) . ']'; $logContent = '[' . $currentDateTime . '] [' . $level . ']'; if (!empty($category)) { $logContent .= ' [' . $category . ']'; } $logContent .= ' ' . $message . "\n"; // 写入文件(PHP 5.2的file_put_contents支持有限,使用fopen/fwrite) $fp = fopen($logFile, 'a'); if (!$fp) { error_log("无法打开日志文件: $logFile"); return false; } // 尝试锁定文件 $locked = false; if (function_exists('flock')) { $locked = flock($fp, LOCK_EX); } if ($locked || !function_exists('flock')) { fwrite($fp, $logContent); if ($locked) { flock($fp, LOCK_UN); } } fclose($fp); // 自动维护 self::autoMaintenance($baseLogDir); return true; } /** * 快捷方法:信息日志 */ public static function info($message, $category = '') { return self::write($message, LOG_LEVEL_INFO, $category); } /** * 快捷方法:警告日志 */ public static function warn($message, $category = '') { return self::write($message, LOG_LEVEL_WARN, $category); } /** * 快捷方法:错误日志 */ public static function error($message, $category = '') { return self::write($message, LOG_LEVEL_ERROR, $category); } /** * 快捷方法:调试日志 */ public static function debug($message, $category = '') { return self::write($message, LOG_LEVEL_DEBUG, $category); } /** * 确保目录存在 */ private static function ensureDirectory($dir) { if (!is_dir($dir)) { // PHP 5.2的mkdir需要第三个参数 return mkdir($dir, 0755, true); } return true; } /** * 查找可用的日志文件(处理10MB大小限制) */ private static function findAvailableLogFile($baseFile, $dailyLogDir, $currentHour) { // 尝试基础文件名(无序号) if (!file_exists($baseFile)) { return $baseFile; } // 检查基础文件大小 if (filesize($baseFile) < self::$maxFileSize) { return $baseFile; } // 基础文件超过10MB,查找带序号的文件 $filePattern = $dailyLogDir . DIRECTORY_SEPARATOR . 'app_' . $currentHour . '_'; // 查找已有序号文件 $existingFiles = array(); if (function_exists('glob')) { $existingFiles = glob($filePattern . '*.log'); } else { // PHP 5.2可能没有glob,使用opendir if ($handle = opendir($dailyLogDir)) { while (false !== ($file = readdir($handle))) { if (preg_match('/^app_' . $currentHour . '_(\d+)\.log$/', $file)) { $existingFiles[] = $dailyLogDir . DIRECTORY_SEPARATOR . $file; } } closedir($handle); } } $maxIndex = 0; foreach ($existingFiles as $file) { if (preg_match('/_(\d+)\.log$/', basename($file), $matches)) { $index = intval($matches[1]); if ($index > $maxIndex) { $maxIndex = $index; } } } // 检查最后一个文件的大小 $lastFile = $filePattern . sprintf('%03d', $maxIndex) . '.log'; if ($maxIndex > 0 && file_exists($lastFile) && filesize($lastFile) < self::$maxFileSize) { return $lastFile; } // 需要创建新文件 $newIndex = $maxIndex + 1; return $filePattern . sprintf('%03d', $newIndex) . '.log'; } /** * 自动维护(清理旧日志) */ private static function autoMaintenance($baseLogDir) { // 每小时最多执行一次维护 if (time() - self::$lastMaintenance < 3600) { return; } self::$lastMaintenance = time(); // 保留30天的目录 $retentionDays = 30; $retentionTime = time() - ($retentionDays * 24 * 60 * 60); $dateDirs = array(); if (function_exists('glob')) { $dateDirs = glob($baseLogDir . DIRECTORY_SEPARATOR . '20*', GLOB_ONLYDIR); } else { // 手动扫描目录 if ($handle = opendir($baseLogDir)) { while (false !== ($entry = readdir($handle))) { $path = $baseLogDir . DIRECTORY_SEPARATOR . $entry; if ($entry != '.' && $entry != '..' && is_dir($path) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $entry)) { $dateDirs[] = $path; } } closedir($handle); } } foreach ($dateDirs as $dir) { if (filemtime($dir) < $retentionTime) { self::deleteDirectoryRecursive($dir); } } } /** * 递归删除目录 */ private static function deleteDirectoryRecursive($dir) { if (!is_dir($dir)) { return false; } $files = array_diff(scandir($dir), array('.', '..')); foreach ($files as $file) { $path = $dir . DIRECTORY_SEPARATOR . $file; if (is_dir($path)) { self::deleteDirectoryRecursive($path); } else { // PHP 5.2确保文件存在再删除 if (file_exists($path)) { unlink($path); } } } // 再次检查目录是否为空 $remainingFiles = array_diff(scandir($dir), array('.', '..')); if (empty($remainingFiles)) { return rmdir($dir); } return false; } /** * 获取日志统计信息 */ public static function getStats() { $baseLogDir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'logs'; if (!is_dir($baseLogDir)) { return array('error' => '日志目录不存在'); } $stats = array( 'total_dirs' => 0, 'total_files' => 0, 'total_size_mb' => 0, 'recent_days' => array() ); // 获取所有日期目录 $dateDirs = array(); if ($handle = opendir($baseLogDir)) { while (false !== ($entry = readdir($handle))) { $path = $baseLogDir . DIRECTORY_SEPARATOR . $entry; if ($entry != '.' && $entry != '..' && is_dir($path) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $entry)) { $dateDirs[] = $path; } } closedir($handle); } // 按日期排序(手动) sort($dateDirs); // 只显示最近7天 $recentDirs = array_slice($dateDirs, -7); foreach ($recentDirs as $dir) { $date = basename($dir); $files = array(); // 获取目录中的所有.log文件 if ($handle = opendir($dir)) { while (false !== ($entry = readdir($handle))) { if (preg_match('/\.log$/', $entry)) { $files[] = $dir . DIRECTORY_SEPARATOR . $entry; } } closedir($handle); } $dayStats = array( 'date' => $date, 'file_count' => count($files), 'size_mb' => 0 ); $daySize = 0; foreach ($files as $file) { if (file_exists($file)) { $daySize += filesize($file); } } $dayStats['size_mb'] = round($daySize / 1024 / 1024, 2); $stats['recent_days'][] = $dayStats; $stats['total_dirs']++; $stats['total_files'] += count($files); $stats['total_size_mb'] += $dayStats['size_mb']; } $stats['total_size_mb'] = round($stats['total_size_mb'], 2); return $stats; } /** * 运行手动维护 */ public static function runMaintenance() { $baseLogDir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'logs'; if (!is_dir($baseLogDir)) { return "日志目录不存在: $baseLogDir"; } $retentionDays = 30; $retentionTime = time() - ($retentionDays * 24 * 60 * 60); $deletedCount = 0; // 获取所有日期目录 $dateDirs = array(); if ($handle = opendir($baseLogDir)) { while (false !== ($entry = readdir($handle))) { $path = $baseLogDir . DIRECTORY_SEPARATOR . $entry; if ($entry != '.' && $entry != '..' && is_dir($path) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $entry)) { $dateDirs[] = $path; } } closedir($handle); } foreach ($dateDirs as $dir) { if (filemtime($dir) < $retentionTime) { if (self::deleteDirectoryRecursive($dir)) { $deletedCount++; } } } return "维护完成,删除了 " . $deletedCount . " 个旧日志目录"; } } // ===================== 兼容旧代码的函数 ===================== /** * 兼容旧代码的日志函数 * 可以逐步替换为 LogHelper::write() */ function WriteLog($msg) { //return LogHelper::info($msg, 'Legacy'); return LogHelper::info($msg); } ?>
使用方法
require_once('Log/LogHelper.php'); //例 WriteLog("收到REQUEST=". " '$UniqueId','$StartTime', '$EndTime', '$BillableSeconds'," ."'$CallerId', '$Called', '$CallType', '$CallFee'");
// ===================== PHP 5.2兼容的测试代码 ===================== // 只有在命令行直接运行此文件时才执行测试 if (basename(__FILE__) == 'LogHelper.php') { // 简单的命令行检测 if (isset($argv) && is_array($argv) && count($argv) > 1 && $argv[1] == 'test') { echo "LogHelper PHP 5.2兼容版本测试\n"; echo "===============================\n"; // 测试不同级别的日志 LogHelper::info("系统启动成功 - PHP 5.2测试"); LogHelper::warn("数据库连接较慢 - PHP 5.2测试"); LogHelper::error("文件上传失败 - PHP 5.2测试"); LogHelper::debug("调试信息: user_id=123 - PHP 5.2测试"); // 使用分类 LogHelper::info("用户登录", "Auth"); LogHelper::info("计费计算: 0.22元", "Billing"); // 测试旧函数兼容性 WriteLog("旧代码兼容性测试"); echo "基本日志测试完成\n"; // 查看统计 $stats = LogHelper::getStats(); echo "\n日志统计:\n"; echo "总目录数: " . $stats['total_dirs'] . "\n"; echo "总文件数: " . $stats['total_files'] . "\n"; echo "总大小: " . $stats['total_size_mb'] . " MB\n"; if (!empty($stats['recent_days'])) { echo "最近7天日志:\n"; foreach ($stats['recent_days'] as $day) { echo " " . $day['date'] . ": " . $day['file_count'] . " 个文件, " . $day['size_mb'] . " MB\n"; } } // 运行维护 echo "\n运行维护:\n"; echo LogHelper::runMaintenance() . "\n"; echo "\n测试完成!\n"; } elseif (isset($argv) && is_array($argv) && count($argv) > 1 && $argv[1] == 'clean') { // 清理命令 echo LogHelper::runMaintenance() . "\n"; } elseif (isset($argv) && is_array($argv) && count($argv) > 1 && $argv[1] == 'stats') { // 统计命令 $stats = LogHelper::getStats(); echo "日志统计信息:\n"; echo "=============\n"; echo "总目录数: " . $stats['total_dirs'] . "\n"; echo "总文件数: " . $stats['total_files'] . "\n"; echo "总大小: " . $stats['total_size_mb'] . " MB\n\n"; if (!empty($stats['recent_days'])) { echo "最近7天详细统计:\n"; foreach ($stats['recent_days'] as $day) { echo " [" . $day['date'] . "] 文件: " . $day['file_count'] . ", 大小: " . $day['size_mb'] . " MB\n"; } } } }

浙公网安备 33010602011771号