mirror of
https://devops.lemonos.cn/lawson/FendxPHP.git
synced 2026-06-15 23:12:49 +08:00
feat(database): 添加用户角色权限系统及相关监控功能
- 创建用户表(users)包含基本信息和认证字段 - 创建角色表(roles)用于权限控制 - 创建权限表(permissions)定义系统权限 - 创建用户角色关联表(user_roles)建立用户与角色关系 - 创建角色权限关联表(role_permissions)建立角色与权限关系 - 创建迁移记录表(migrations)追踪数据库变更 - 添加AdminController提供管理员面板功能 - 实现系统监控、配置管理、缓存清理等功能 - 添加AOP切面编程支持的各种通知类型 - 实现告警管理AlertManager支持多渠道告警 - 添加文档注解接口规范
This commit is contained in:
24
fendx-framework/fendx-log/composer.json
Normal file
24
fendx-framework/fendx-log/composer.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "fendx/log",
|
||||
"description": "FendxPHP Log Module - TraceId、异步日志",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Lawson",
|
||||
"email": "lawson@fendx.cn"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"fendx/common": "^1.0",
|
||||
"fendx/core": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Fendx\\Log\\": "src/"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true
|
||||
}
|
||||
192
fendx-framework/fendx-log/src/Logger.php
Normal file
192
fendx-framework/fendx-log/src/Logger.php
Normal file
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Fendx\Log;
|
||||
|
||||
use Fendx\Core\Context\Context;
|
||||
use Fendx\Common\Exception\BusinessException;
|
||||
|
||||
final class Logger
|
||||
{
|
||||
private const LEVELS = [
|
||||
'DEBUG' => 0,
|
||||
'INFO' => 1,
|
||||
'WARN' => 2,
|
||||
'ERROR' => 3
|
||||
];
|
||||
|
||||
private string $name;
|
||||
private int $level;
|
||||
private string $logFile;
|
||||
private bool $async;
|
||||
|
||||
public function __construct(string $name = 'fendx', array $config = [])
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->level = $config['level'] ?? self::LEVELS['INFO'];
|
||||
$this->logFile = $config['file'] ?? $this->getDefaultLogFile();
|
||||
$this->async = $config['async'] ?? true;
|
||||
}
|
||||
|
||||
public function debug(string $message, array $context = []): void
|
||||
{
|
||||
$this->log('DEBUG', $message, $context);
|
||||
}
|
||||
|
||||
public function info(string $message, array $context = []): void
|
||||
{
|
||||
$this->log('INFO', $message, $context);
|
||||
}
|
||||
|
||||
public function warn(string $message, array $context = []): void
|
||||
{
|
||||
$this->log('WARN', $message, $context);
|
||||
}
|
||||
|
||||
public function error(string $message, array $context = []): void
|
||||
{
|
||||
$this->log('ERROR', $message, $context);
|
||||
}
|
||||
|
||||
private function log(string $level, string $message, array $context = []): void
|
||||
{
|
||||
if (self::LEVELS[$level] < $this->level) {
|
||||
return;
|
||||
}
|
||||
|
||||
$logEntry = $this->formatLogEntry($level, $message, $context);
|
||||
|
||||
if ($this->async) {
|
||||
$this->writeAsync($logEntry);
|
||||
} else {
|
||||
$this->write($logEntry);
|
||||
}
|
||||
}
|
||||
|
||||
private function formatLogEntry(string $level, string $message, array $context): string
|
||||
{
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
$traceId = Context::getTraceId();
|
||||
$userId = Context::getUserId();
|
||||
|
||||
$contextStr = empty($context) ? '' : ' ' . json_encode($context, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
return sprintf(
|
||||
'[%s] [%s] [%s] [user:%s] %s%s',
|
||||
$timestamp,
|
||||
$level,
|
||||
$traceId,
|
||||
$userId ?? 'guest',
|
||||
$message,
|
||||
$contextStr
|
||||
);
|
||||
}
|
||||
|
||||
private function write(string $logEntry): void
|
||||
{
|
||||
$dir = dirname($this->logFile);
|
||||
if (!is_dir($dir)) {
|
||||
if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
|
||||
throw new BusinessException(500, 'LOG_DIR_CREATE_FAILED', ['dir' => $dir]);
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents($this->logFile, $logEntry . PHP_EOL, FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
|
||||
private function writeAsync(string $logEntry): void
|
||||
{
|
||||
register_shutdown_function(function () use ($logEntry) {
|
||||
$this->write($logEntry);
|
||||
});
|
||||
}
|
||||
|
||||
private function getDefaultLogFile(): string
|
||||
{
|
||||
$date = date('Y-m-d');
|
||||
return dirname(__DIR__, 4) . "/runtime/logs/fendx-{$date}.log";
|
||||
}
|
||||
|
||||
public function setLevel(string $level): void
|
||||
{
|
||||
if (!isset(self::LEVELS[$level])) {
|
||||
throw new BusinessException(500, 'INVALID_LOG_LEVEL', ['level' => $level]);
|
||||
}
|
||||
$this->level = self::LEVELS[$level];
|
||||
}
|
||||
|
||||
public function getLevel(): int
|
||||
{
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
public function setLogFile(string $file): void
|
||||
{
|
||||
$this->logFile = $file;
|
||||
}
|
||||
|
||||
public function getLogFile(): string
|
||||
{
|
||||
return $this->logFile;
|
||||
}
|
||||
|
||||
public static function create(string $name = 'fendx', array $config = []): self
|
||||
{
|
||||
return new self($name, $config);
|
||||
}
|
||||
|
||||
public static function debug(string $message, array $context = []): void
|
||||
{
|
||||
static $logger = null;
|
||||
if ($logger === null) {
|
||||
$logger = new self();
|
||||
}
|
||||
$logger->debug($message, $context);
|
||||
}
|
||||
|
||||
public static function info(string $message, array $context = []): void
|
||||
{
|
||||
static $logger = null;
|
||||
if ($logger === null) {
|
||||
$logger = new self();
|
||||
}
|
||||
$logger->info($message, $context);
|
||||
}
|
||||
|
||||
public static function warn(string $message, array $context = []): void
|
||||
{
|
||||
static $logger = null;
|
||||
if ($logger === null) {
|
||||
$logger = new self();
|
||||
}
|
||||
$logger->warn($message, $context);
|
||||
}
|
||||
|
||||
public static function error(string $message, array $context = []): void
|
||||
{
|
||||
static $logger = null;
|
||||
if ($logger === null) {
|
||||
$logger = new self();
|
||||
}
|
||||
$logger->error($message, $context);
|
||||
}
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
if (file_exists($this->logFile)) {
|
||||
unlink($this->logFile);
|
||||
}
|
||||
}
|
||||
|
||||
public function rotate(): void
|
||||
{
|
||||
if (!file_exists($this->logFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$timestamp = date('Y-m-d_H-i-s');
|
||||
$backupFile = str_replace('.log', "-{$timestamp}.log", $this->logFile);
|
||||
|
||||
rename($this->logFile, $backupFile);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user