本文目录导读:

我来提供一个完整的PHP自定义日志类封装方案:
基础日志类实现
<?php
/**
* 自定义日志类
*/
class Logger {
// 日志级别
const DEBUG = 'DEBUG';
const INFO = 'INFO';
const WARNING = 'WARNING';
const ERROR = 'ERROR';
const CRITICAL = 'CRITICAL';
private static $instance = null;
private $logDir = '';
private $logLevel = self::DEBUG;
private $dateFormat = 'Y-m-d H:i:s';
private $filePrefix = 'app';
private $maxFileSize = 10485760; // 10MB
private $backupCount = 5;
/**
* 私有构造函数
*/
private function __construct($config = []) {
if (!empty($config)) {
$this->initialize($config);
}
}
/**
* 获取单例实例
*/
public static function getInstance($config = []) {
if (self::$instance === null) {
self::$instance = new self($config);
}
return self::$instance;
}
/**
* 初始化配置
*/
public function initialize($config) {
if (isset($config['log_dir'])) {
$this->logDir = rtrim($config['log_dir'], '/') . '/';
} else {
$this->logDir = dirname(__FILE__) . '/../logs/';
}
if (isset($config['log_level'])) {
$this->logLevel = strtoupper($config['log_level']);
}
if (isset($config['date_format'])) {
$this->dateFormat = $config['date_format'];
}
if (isset($config['file_prefix'])) {
$this->filePrefix = $config['file_prefix'];
}
if (isset($config['max_file_size'])) {
$this->maxFileSize = (int)$config['max_file_size'];
}
if (isset($config['backup_count'])) {
$this->backupCount = (int)$config['backup_count'];
}
// 创建日志目录
$this->createLogDirectory();
}
/**
* 创建日志目录
*/
private function createLogDirectory() {
if (!is_dir($this->logDir)) {
@mkdir($this->logDir, 0777, true);
}
// 按日期创建子目录
$dateDir = $this->logDir . date('Ymd') . '/';
if (!is_dir($dateDir)) {
@mkdir($dateDir, 0777, true);
}
}
/**
* 记录调试日志
*/
public function debug($message, $context = []) {
$this->log(self::DEBUG, $message, $context);
}
/**
* 记录信息日志
*/
public function info($message, $context = []) {
$this->log(self::INFO, $message, $context);
}
/**
* 记录警告日志
*/
public function warning($message, $context = []) {
$this->log(self::WARNING, $message, $context);
}
/**
* 记录错误日志
*/
public function error($message, $context = []) {
$this->log(self::ERROR, $message, $context);
}
/**
* 记录关键错误日志
*/
public function critical($message, $context = []) {
$this->log(self::CRITICAL, $message, $context);
}
/**
* 核心日志记录方法
*/
public function log($level, $message, $context = []) {
// 检查日志级别
if (!$this->isLevelAllowed($level)) {
return;
}
// 格式化消息
$formattedMessage = $this->formatMessage($level, $message, $context);
// 写入日志
$this->writeToFile($level, $formattedMessage);
}
/**
* 检查日志级别是否允许
*/
private function isLevelAllowed($level) {
$levels = [
self::DEBUG => 0,
self::INFO => 1,
self::WARNING => 2,
self::ERROR => 3,
self::CRITICAL => 4
];
return $levels[$level] >= $levels[$this->logLevel];
}
/**
* 格式化日志消息
*/
private function formatMessage($level, $message, $context = []) {
$timestamp = date($this->dateFormat);
if (!empty($context)) {
$message = $this->interpolate($message, $context);
}
// 获取调用信息
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
$caller = isset($trace[2]) ? $trace[2] : [];
$file = isset($caller['file']) ? basename($caller['file']) : 'unknown';
$line = isset($caller['line']) ? $caller['line'] : 'unknown';
return sprintf(
"[%s] [%s] [%s:%d] %s",
$timestamp,
$level,
$file,
$line,
$message
);
}
/**
* 替换消息中的占位符
*/
private function interpolate($message, $context = []) {
$replace = [];
foreach ($context as $key => $val) {
if (is_string($val) || method_exists($val, '__toString')) {
$replace['{' . $key . '}'] = $val;
}
}
return strtr($message, $replace);
}
/**
* 写入日志文件
*/
private function writeToFile($level, $message) {
$filename = $this->getLogFilename($level);
$this->rotateLogFile($filename);
$result = @file_put_contents(
$filename,
$message . PHP_EOL,
FILE_APPEND | LOCK_EX
);
if ($result === false) {
error_log("Failed to write to log file: {$filename}");
}
}
/**
* 获取日志文件名
*/
private function getLogFilename($level) {
$dateDir = $this->logDir . date('Ymd') . '/';
$levelLower = strtolower($level);
return $dateDir . "{$this->filePrefix}_{$levelLower}.log";
}
/**
* 日志文件轮转
*/
private function rotateLogFile($filename) {
if (!file_exists($filename)) {
return;
}
if (filesize($filename) < $this->maxFileSize) {
return;
}
// 删除最旧的备份
$oldestBackup = $filename . '.' . $this->backupCount;
if (file_exists($oldestBackup)) {
@unlink($oldestBackup);
}
// 轮转备份文件
for ($i = $this->backupCount - 1; $i >= 1; $i--) {
$backup = $filename . '.' . $i;
if (file_exists($backup)) {
rename($backup, $filename . '.' . ($i + 1));
}
}
// 重命名当前文件
rename($filename, $filename . '.1');
}
/**
* 防止克隆
*/
private function __clone() {}
/**
* 防止反序列化
*/
private function __wakeup() {}
}
增强版日志类(支持更多功能)
<?php
/**
* 增强版日志类
*/
class AdvancedLogger {
private static $instance = null;
private $config = [];
private $buffer = [];
// 日志级别定义
const LEVELS = [
'DEBUG' => 100,
'INFO' => 200,
'NOTICE' => 250,
'WARNING' => 300,
'ERROR' => 400,
'CRITICAL' => 500,
'ALERT' => 550,
'EMERGENCY' => 600
];
private function __construct($config = []) {
$this->config = array_merge([
'log_dir' => dirname(__FILE__) . '/../logs/',
'log_level' => 'DEBUG',
'date_format' => 'Y-m-d H:i:s',
'file_prefix' => 'app',
'max_file_size' => 10485760,
'backup_count' => 5,
'enable_buffer' => false,
'buffer_size' => 100,
'enable_email' => false,
'email_recipients' => [],
'email_level' => 'ERROR',
'enable_console' => false,
'format' => 'json', // json or text
], $config);
$this->init();
}
public static function getInstance($config = []) {
if (self::$instance === null) {
self::$instance = new self($config);
}
return self::$instance;
}
private function init() {
$this->createDirectory();
$this->registerShutdownHandler();
}
/**
* 注册关闭处理器
*/
private function registerShutdownHandler() {
register_shutdown_function(function() {
$this->flushBuffer();
});
}
/**
* 记录日志
*/
public function log($level, $message, $context = []) {
if (!$this->isLevelAllowed($level)) {
return;
}
$record = $this->createRecord($level, $message, $context);
if ($this->config['enable_buffer']) {
$this->buffer[] = $record;
if (count($this->buffer) >= $this->config['buffer_size']) {
$this->flushBuffer();
}
} else {
$this->writeRecord($record);
}
}
/**
* 创建日志记录
*/
private function createRecord($level, $message, $context = []) {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
$caller = isset($trace[2]) ? $trace[2] : [];
$record = [
'timestamp' => date($this->config['date_format']),
'level' => $level,
'message' => $this->interpolate($message, $context),
'file' => isset($caller['file']) ? $caller['file'] : 'unknown',
'line' => isset($caller['line']) ? $caller['line'] : 'unknown',
'context' => $context,
'extra' => $this->getExtraData()
];
return $record;
}
/**
* 获取额外数据
*/
private function getExtraData() {
return [
'ip' => $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1',
'uri' => $_SERVER['REQUEST_URI'] ?? 'cli',
'method' => $_SERVER['REQUEST_METHOD'] ?? 'UNKNOWN',
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
'memory_usage' => memory_get_usage(true),
'memory_peak' => memory_get_peak_usage(true),
'execution_time' => defined('START_TIME') ? microtime(true) - START_TIME : 0
];
}
/**
* 写入日志记录
*/
private function writeRecord($record) {
$formatted = $this->formatRecord($record);
$filename = $this->getLogFilename($record['level']);
$this->rotateLogFile($filename);
$this->writeToFile($filename, $formatted);
// 发送邮件告警
if ($this->config['enable_email'] &&
$this->isLevelReached($record['level'], $this->config['email_level'])) {
$this->sendEmailAlert($record);
}
// 控制台输出
if ($this->config['enable_console'] && PHP_SAPI === 'cli') {
$this->writeToConsole($formatted);
}
}
/**
* 格式化日志记录
*/
private function formatRecord($record) {
if ($this->config['format'] === 'json') {
return json_encode($record, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
} else {
return sprintf(
"[%s] [%s] [%s:%d] %s",
$record['timestamp'],
$record['level'],
basename($record['file']),
$record['line'],
$record['message']
);
}
}
/**
* 写入文件
*/
private function writeToFile($filename, $content) {
$result = @file_put_contents(
$filename,
$content . PHP_EOL,
FILE_APPEND | LOCK_EX
);
if ($result === false) {
// 写入失败时使用系统日志
error_log("Logger: Failed to write log to {$filename}: {$content}");
}
}
/**
* 写入控制台
*/
private function writeToConsole($content) {
$colors = [
'DEBUG' => "\033[36m", // Cyan
'INFO' => "\033[32m", // Green
'NOTICE' => "\033[34m", // Blue
'WARNING' => "\033[33m", // Yellow
'ERROR' => "\033[31m", // Red
'CRITICAL' => "\033[41m",// Red background
'ALERT' => "\033[45m", // Purple background
'EMERGENCY' => "\033[41m"// Red background
];
$level = json_decode($content, true)['level'] ?? 'INFO';
$color = $colors[$level] ?? "\033[0m";
$reset = "\033[0m";
echo $color . $content . $reset . PHP_EOL;
}
/**
* 刷新缓冲区
*/
public function flushBuffer() {
if (empty($this->buffer)) {
return;
}
$records = $this->buffer;
$this->buffer = [];
// 按级别分组写入
$grouped = [];
foreach ($records as $record) {
$grouped[$record['level']][] = $record;
}
foreach ($grouped as $level => $records) {
$filename = $this->getLogFilename($level);
$this->rotateLogFile($filename);
$content = '';
foreach ($records as $record) {
$content .= $this->formatRecord($record) . PHP_EOL;
}
$this->writeToFile($filename, $content);
}
}
/**
* 发送邮件告警
*/
private function sendEmailAlert($record) {
if (empty($this->config['email_recipients'])) {
return;
}
$subject = sprintf(
'[%s] Log Alert: %s',
$record['level'],
substr($record['message'], 0, 100)
);
$body = print_r($record, true);
foreach ($this->config['email_recipients'] as $recipient) {
@mail($recipient, $subject, $body);
}
}
/**
* 检查日志级别是否允许
*/
private function isLevelAllowed($level) {
return self::LEVELS[$level] >= self::LEVELS[$this->config['log_level']];
}
/**
* 检查是否达到指定级别
*/
private function isLevelReached($current, $target) {
return self::LEVELS[$current] >= self::LEVELS[$target];
}
// ... 其他辅助方法与基础版本相同
private function __clone() {}
private function __wakeup() {}
}
使用示例
<?php
// 配置文件
$config = [
'log_dir' => '/path/to/logs',
'log_level' => 'DEBUG',
'file_prefix' => 'myapp',
'max_file_size' => 5242880, // 5MB
'backup_count' => 3,
'enable_buffer' => true,
'buffer_size' => 50,
'format' => 'json',
'enable_email' => true,
'email_recipients' => ['admin@example.com'],
'email_level' => 'ERROR',
'enable_console' => true
];
// 获取日志实例
$logger = Logger::getInstance($config);
// 基本使用
$logger->info('User logged in', ['user_id' => 123, 'username' => 'john']);
$logger->error('Database connection failed', ['error_code' => 1045]);
$logger->debug('Memory usage: {memory}', ['memory' => memory_get_usage()]);
// 使用高级版本
$advLogger = AdvancedLogger::getInstance($config);
// 批量记录
$advLogger->log('INFO', 'API Request', [
'endpoint' => '/users',
'method' => 'GET',
'params' => $_GET
]);
// 异常记录
try {
// 一些代码
throw new Exception('Something went wrong');
} catch (Exception $e) {
$logger->critical($e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
]);
}
// 性能监控
$logger->info('Page load completed', [
'execution_time' => (microtime(true) - START_TIME),
'memory_usage' => memory_get_usage()
]);
特点说明
- 单例模式:确保全局只有一个日志实例
- 多级别支持:DEBUG到CRITICAL多个级别
- 自动轮转:当文件超过指定大小时自动分割
- 日期目录:按日期创建子目录,便于管理
- 缓冲机制:支持批量写入,提高性能
- 上下文信息:自动记录调用位置、IP、URI等
- 多种输出:支持文件、控制台、邮件
- 格式化灵活:支持JSON和文本格式
这个日志类封装了企业级应用所需的大部分功能,你可以根据实际需求进行扩展和调整。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播