Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Byte-compiled / optimized / DLL files
__pycache__/
.idea/
.vscode/
*.py[cod]
*$py.class

Expand Down Expand Up @@ -138,3 +136,19 @@ dmypy.json

# Cython debug symbols
cython_debug/

# PyCharm
.idea/

# VSCode
.vscode/

# AI Editor
.agent/
.claude/
.codebuddy/
.codex/
.cursor/
.opencode/
.qoder/
.trae/
50 changes: 49 additions & 1 deletion ruoyi-fastapi-backend/.env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ APP_PORT = 9099
APP_VERSION= '1.8.1'
# 应用是否开启热重载
APP_RELOAD = true
# 应用工作进程数
APP_WORKERS = 1
# 应用是否开启IP归属区域查询
APP_IP_LOCATION_QUERY = true
# 应用是否允许账号同时登录
Expand Down Expand Up @@ -67,4 +69,50 @@ REDIS_USERNAME = ''
# Redis密码
REDIS_PASSWORD = ''
# Redis数据库
REDIS_DATABASE = 2
REDIS_DATABASE = 2

# -------- 日志配置 --------
# Redis Stream Key
LOG_STREAM_KEY = 'log:stream'
# Redis Stream 消费组名称
LOG_STREAM_GROUP = 'log_aggregator'
# Redis Stream 消费者名称前缀
LOG_STREAM_CONSUMER_PREFIX = 'worker'
# 每次读取的最大消息数量
LOG_STREAM_BATCH_SIZE = 100
# 阻塞读取等待时间(毫秒)
LOG_STREAM_BLOCK_MS = 2000
# Stream 最大长度(近似裁剪)
LOG_STREAM_MAXLEN = 100000
# Pending 回收最小空闲时间(毫秒)
LOG_STREAM_CLAIM_IDLE_MS = 60000
# Pending 回收检查间隔(毫秒)
LOG_STREAM_CLAIM_INTERVAL_MS = 5000
# 每次回收的最大消息数量
LOG_STREAM_CLAIM_BATCH_SIZE = 100
# 去重 Key 过期时间(秒)
LOG_STREAM_DEDUP_TTL = 3600
# 去重 Key 前缀
LOG_STREAM_DEDUP_PREFIX = 'log:dedup'
# stdout 输出是否为 JSON
LOGURU_JSON = false
# Loguru 最低输出级别
LOGURU_LEVEL = 'INFO'
# 是否输出到 stdout
LOGURU_STDOUT = true
# 是否启用文件日志
LOG_FILE_ENABLED = true
# 文件日志根目录
LOG_FILE_BASE_DIR = 'logs'
# 文件滚动策略
LOGURU_ROTATION = '50MB'
# 文件保留策略
LOGURU_RETENTION = '30 days'
# 文件压缩格式
LOGURU_COMPRESSION = 'zip'
# 实例标识(用于区分实例)
LOG_INSTANCE_ID = 'dev'
# 服务名称(用于统一标识服务)
LOG_SERVICE_NAME = 'ruoyi-fastapi-backend'
# Worker 标识(auto 自动生成)
LOG_WORKER_ID = 'auto'
50 changes: 49 additions & 1 deletion ruoyi-fastapi-backend/.env.dockermy
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ APP_PORT = 9099
APP_VERSION= '1.8.1'
# 应用是否开启热重载
APP_RELOAD = false
# 应用工作进程数
APP_WORKERS = 1
# 应用是否开启IP归属区域查询
APP_IP_LOCATION_QUERY = true
# 应用是否允许账号同时登录
Expand Down Expand Up @@ -67,4 +69,50 @@ REDIS_USERNAME = ''
# Redis密码
REDIS_PASSWORD = ''
# Redis数据库
REDIS_DATABASE = 2
REDIS_DATABASE = 2

# -------- 日志配置 --------
# Redis Stream Key
LOG_STREAM_KEY = 'log:stream'
# Redis Stream 消费组名称
LOG_STREAM_GROUP = 'log_aggregator'
# Redis Stream 消费者名称前缀
LOG_STREAM_CONSUMER_PREFIX = 'worker'
# 每次读取的最大消息数量
LOG_STREAM_BATCH_SIZE = 100
# 阻塞读取等待时间(毫秒)
LOG_STREAM_BLOCK_MS = 2000
# Stream 最大长度(近似裁剪)
LOG_STREAM_MAXLEN = 100000
# Pending 回收最小空闲时间(毫秒)
LOG_STREAM_CLAIM_IDLE_MS = 60000
# Pending 回收检查间隔(毫秒)
LOG_STREAM_CLAIM_INTERVAL_MS = 5000
# 每次回收的最大消息数量
LOG_STREAM_CLAIM_BATCH_SIZE = 100
# 去重 Key 过期时间(秒)
LOG_STREAM_DEDUP_TTL = 3600
# 去重 Key 前缀
LOG_STREAM_DEDUP_PREFIX = 'log:dedup'
# stdout 输出是否为 JSON
LOGURU_JSON = false
# Loguru 最低输出级别
LOGURU_LEVEL = 'INFO'
# 是否输出到 stdout
LOGURU_STDOUT = true
# 是否启用文件日志
LOG_FILE_ENABLED = true
# 文件日志根目录
LOG_FILE_BASE_DIR = 'logs'
# 文件滚动策略
LOGURU_ROTATION = '50MB'
# 文件保留策略
LOGURU_RETENTION = '30 days'
# 文件压缩格式
LOGURU_COMPRESSION = 'zip'
# 实例标识(用于区分实例)
LOG_INSTANCE_ID = 'dockermy'
# 服务名称(用于统一标识服务)
LOG_SERVICE_NAME = 'ruoyi-fastapi-backend'
# Worker 标识(auto 自动生成)
LOG_WORKER_ID = 'auto'
50 changes: 49 additions & 1 deletion ruoyi-fastapi-backend/.env.dockerpg
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ APP_PORT = 9099
APP_VERSION= '1.8.1'
# 应用是否开启热重载
APP_RELOAD = false
# 应用工作进程数
APP_WORKERS = 1
# 应用是否开启IP归属区域查询
APP_IP_LOCATION_QUERY = true
# 应用是否允许账号同时登录
Expand Down Expand Up @@ -67,4 +69,50 @@ REDIS_USERNAME = ''
# Redis密码
REDIS_PASSWORD = ''
# Redis数据库
REDIS_DATABASE = 2
REDIS_DATABASE = 2

# -------- 日志配置 --------
# Redis Stream Key
LOG_STREAM_KEY = 'log:stream'
# Redis Stream 消费组名称
LOG_STREAM_GROUP = 'log_aggregator'
# Redis Stream 消费者名称前缀
LOG_STREAM_CONSUMER_PREFIX = 'worker'
# 每次读取的最大消息数量
LOG_STREAM_BATCH_SIZE = 100
# 阻塞读取等待时间(毫秒)
LOG_STREAM_BLOCK_MS = 2000
# Stream 最大长度(近似裁剪)
LOG_STREAM_MAXLEN = 100000
# Pending 回收最小空闲时间(毫秒)
LOG_STREAM_CLAIM_IDLE_MS = 60000
# Pending 回收检查间隔(毫秒)
LOG_STREAM_CLAIM_INTERVAL_MS = 5000
# 每次回收的最大消息数量
LOG_STREAM_CLAIM_BATCH_SIZE = 100
# 去重 Key 过期时间(秒)
LOG_STREAM_DEDUP_TTL = 3600
# 去重 Key 前缀
LOG_STREAM_DEDUP_PREFIX = 'log:dedup'
# stdout 输出是否为 JSON
LOGURU_JSON = false
# Loguru 最低输出级别
LOGURU_LEVEL = 'INFO'
# 是否输出到 stdout
LOGURU_STDOUT = true
# 是否启用文件日志
LOG_FILE_ENABLED = true
# 文件日志根目录
LOG_FILE_BASE_DIR = 'logs'
# 文件滚动策略
LOGURU_ROTATION = '50MB'
# 文件保留策略
LOGURU_RETENTION = '30 days'
# 文件压缩格式
LOGURU_COMPRESSION = 'zip'
# 实例标识(用于区分实例)
LOG_INSTANCE_ID = 'dockerpg'
# 服务名称(用于统一标识服务)
LOG_SERVICE_NAME = 'ruoyi-fastapi-backend'
# Worker 标识(auto 自动生成)
LOG_WORKER_ID = 'auto'
50 changes: 49 additions & 1 deletion ruoyi-fastapi-backend/.env.prod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ APP_PORT = 9099
APP_VERSION= '1.8.1'
# 应用是否开启热重载
APP_RELOAD = false
# 应用工作进程数
APP_WORKERS = 1
# 应用是否开启IP归属区域查询
APP_IP_LOCATION_QUERY = true
# 应用是否允许账号同时登录
Expand Down Expand Up @@ -67,4 +69,50 @@ REDIS_USERNAME = ''
# Redis密码
REDIS_PASSWORD = ''
# Redis数据库
REDIS_DATABASE = 2
REDIS_DATABASE = 2

# -------- 日志配置 --------
# Redis Stream Key
LOG_STREAM_KEY = 'log:stream'
# Redis Stream 消费组名称
LOG_STREAM_GROUP = 'log_aggregator'
# Redis Stream 消费者名称前缀
LOG_STREAM_CONSUMER_PREFIX = 'worker'
# 每次读取的最大消息数量
LOG_STREAM_BATCH_SIZE = 100
# 阻塞读取等待时间(毫秒)
LOG_STREAM_BLOCK_MS = 2000
# Stream 最大长度(近似裁剪)
LOG_STREAM_MAXLEN = 100000
# Pending 回收最小空闲时间(毫秒)
LOG_STREAM_CLAIM_IDLE_MS = 60000
# Pending 回收检查间隔(毫秒)
LOG_STREAM_CLAIM_INTERVAL_MS = 5000
# 每次回收的最大消息数量
LOG_STREAM_CLAIM_BATCH_SIZE = 100
# 去重 Key 过期时间(秒)
LOG_STREAM_DEDUP_TTL = 3600
# 去重 Key 前缀
LOG_STREAM_DEDUP_PREFIX = 'log:dedup'
# stdout 输出是否为 JSON
LOGURU_JSON = false
# Loguru 最低输出级别
LOGURU_LEVEL = 'INFO'
# 是否输出到 stdout
LOGURU_STDOUT = true
# 是否启用文件日志
LOG_FILE_ENABLED = true
# 文件日志根目录
LOG_FILE_BASE_DIR = 'logs'
# 文件滚动策略
LOGURU_ROTATION = '50MB'
# 文件保留策略
LOGURU_RETENTION = '30 days'
# 文件压缩格式
LOGURU_COMPRESSION = 'zip'
# 实例标识(用于区分实例)
LOG_INSTANCE_ID = 'prod'
# 服务名称(用于统一标识服务)
LOG_SERVICE_NAME = 'ruoyi-fastapi-backend'
# Worker 标识(auto 自动生成)
LOG_WORKER_ID = 'auto'
1 change: 1 addition & 0 deletions ruoyi-fastapi-backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
port=AppConfig.app_port,
root_path=AppConfig.app_root_path,
reload=AppConfig.app_reload,
workers=AppConfig.app_workers,
)
9 changes: 3 additions & 6 deletions ruoyi-fastapi-backend/common/annotation/log_annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from async_lru import alru_cache
from fastapi import Request
from fastapi.responses import JSONResponse, ORJSONResponse, UJSONResponse
from sqlalchemy.ext.asyncio import AsyncSession
from starlette.status import HTTP_200_OK
from typing_extensions import ParamSpec
from user_agents import parse
Expand All @@ -20,7 +19,7 @@
from config.env import AppConfig
from exceptions.exception import LoginException, ServiceException, ServiceWarning
from module_admin.entity.vo.log_vo import LogininforModel, OperLogModel
from module_admin.service.log_service import LoginLogService, OperationLogService
from module_admin.service.log_service import LogQueueService
from utils.dependency_util import DependencyUtil
from utils.log_util import logger
from utils.response_util import ResponseUtil
Expand Down Expand Up @@ -63,8 +62,6 @@ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
request_name_list = get_function_parameters_name_by_type(func, Request)
request = get_function_parameters_value_by_name(func, request_name_list[0], *args, **kwargs)
DependencyUtil.check_exclude_routes(request, err_msg='当前路由不在认证规则内,不可使用Log装饰器')
session_name_list = get_function_parameters_name_by_type(func, AsyncSession)
query_db = get_function_parameters_value_by_name(func, session_name_list[0], *args, **kwargs)
request_method = request.method
user_agent = request.headers.get('User-Agent')
# 获取操作类型
Expand Down Expand Up @@ -122,7 +119,7 @@ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
}
)

await LoginLogService.add_login_log_services(query_db, LogininforModel(**login_log))
await LogQueueService.enqueue_login_log(request, LogininforModel(**login_log), func_path)
else:
current_user = RequestContext.get_current_user()
oper_name = current_user.user.user_name
Expand All @@ -145,7 +142,7 @@ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
operTime=oper_time,
costTime=int(cost_time),
)
await OperationLogService.add_operation_log_services(query_db, operation_log)
await LogQueueService.enqueue_operation_log(request, operation_log, func_path)

return result

Expand Down
10 changes: 10 additions & 0 deletions ruoyi-fastapi-backend/common/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ class JobConstant:
JOB_WHITE_LIST = ['module_task']


class LockConstant:
"""
分布式锁常量
"""

APP_STARTUP_LOCK_KEY = 'app:startup:lock'
LOCK_EXPIRE_SECONDS = 60
LOCK_RENEWAL_INTERVAL = 20


class MenuConstant:
"""
菜单常量
Expand Down
Loading