study-api-v2/app/Exceptions/LogException.php

149 lines
4.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Support\Facades\Log;
/**
* 日志异常处理类
* 专门处理日志系统相关的异常,避免影响主业务流程
*/
class LogException extends Exception
{
/**
* 安全记录异常到系统日志
*
* @param string $message 错误消息
* @param \Exception|null $exception 原始异常
* @param array $context 上下文信息
*/
public static function safeLog(string $message, ?\Exception $exception = null, array $context = []): void
{
try {
// 构建完整的错误信息
$fullMessage = $message;
if ($exception) {
$fullMessage .= ' | 异常: ' . $exception->getMessage();
$fullMessage .= ' | 文件: ' . $exception->getFile() . ':' . $exception->getLine();
}
// 尝试多种日志记录方式
self::tryLogToChannels($fullMessage, $context);
} catch (\Exception $e) {
// 最后的兜底方案:系统错误日志
error_log("Laravel日志系统完全失效 - 原始消息: {$message} | 日志异常: {$e->getMessage()}");
}
}
/**
* 尝试多个日志通道记录
*/
private static function tryLogToChannels(string $message, array $context): void
{
$channels = ['single', 'daily', 'errorlog'];
foreach ($channels as $channel) {
try {
Log::channel($channel)->warning($message, $context);
return; // 成功记录后退出
} catch (\Exception $e) {
continue; // 继续尝试下一个通道
}
}
// 所有Laravel日志通道都失败使用系统错误日志
error_log("Laravel日志记录失败: {$message}");
}
/**
* 检查日志目录权限并尝试修复
*
* @param string $logPath 日志路径
* @return bool 是否修复成功
*/
public static function checkAndFixLogPermissions(string $logPath): bool
{
try {
$logDir = dirname($logPath);
// 检查目录是否存在
if (!is_dir($logDir)) {
if (!mkdir($logDir, 0755, true)) {
return false;
}
}
// 检查目录权限
if (!is_writable($logDir)) {
// 尝试修改权限
if (!chmod($logDir, 0755)) {
return false;
}
}
// 如果日志文件存在,检查文件权限
if (file_exists($logPath) && !is_writable($logPath)) {
if (!chmod($logPath, 0644)) {
return false;
}
}
return true;
} catch (\Exception $e) {
self::safeLog("日志权限检查失败: " . $e->getMessage(), $e);
return false;
}
}
/**
* 获取所有配置的日志路径
*
* @return array
*/
public static function getAllLogPaths(): array
{
$paths = [];
try {
$channels = config('logging.channels', []);
foreach ($channels as $name => $config) {
if (isset($config['path'])) {
$paths[$name] = $config['path'];
}
}
} catch (\Exception $e) {
self::safeLog("获取日志路径配置失败: " . $e->getMessage(), $e);
}
return $paths;
}
/**
* 批量检查所有日志路径权限
*
* @return array 返回检查结果
*/
public static function checkAllLogPermissions(): array
{
$results = [];
$paths = self::getAllLogPaths();
foreach ($paths as $channel => $path) {
$results[$channel] = [
'path' => $path,
'writable' => self::checkAndFixLogPermissions($path),
'dir_exists' => is_dir(dirname($path)),
'dir_writable' => is_writable(dirname($path)),
'file_exists' => file_exists($path),
'file_writable' => file_exists($path) ? is_writable($path) : null
];
}
return $results;
}
}