Build lightweight AI agent admin
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Redis监控模块
|
||||
"""
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Redis监控API
|
||||
"""
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.config import settings
|
||||
from core.redis_monitor.redis_collector import AsyncRedisInfoCollector
|
||||
from core.redis_monitor.schema import (
|
||||
RedisMonitorOverviewSchema,
|
||||
RedisRealtimeStatsSchema,
|
||||
RedisConnectionTestSchema,
|
||||
RedisConfigSchema,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/redis_monitor", tags=["Redis监控"])
|
||||
|
||||
|
||||
def get_redis_config():
|
||||
"""获取项目Redis配置"""
|
||||
redis_host = settings.REDIS_HOST
|
||||
redis_port = settings.REDIS_PORT
|
||||
redis_password = settings.REDIS_PASSWORD
|
||||
redis_db = settings.REDIS_DB
|
||||
|
||||
# 如果密码为空字符串,设置为None
|
||||
if redis_password == '':
|
||||
redis_password = None
|
||||
|
||||
return redis_host, redis_port, redis_password, redis_db
|
||||
|
||||
|
||||
@router.get("/overview", response_model=RedisMonitorOverviewSchema, summary="获取Redis监控概览")
|
||||
async def get_redis_monitor_overview():
|
||||
"""获取Redis监控概览信息"""
|
||||
redis_host, redis_port, redis_password, redis_db = get_redis_config()
|
||||
|
||||
collector = AsyncRedisInfoCollector(
|
||||
host=redis_host,
|
||||
port=redis_port,
|
||||
password=redis_password,
|
||||
db=redis_db
|
||||
)
|
||||
|
||||
data = await collector.get_all_info('project_redis', '项目Redis')
|
||||
return RedisMonitorOverviewSchema(**data)
|
||||
|
||||
|
||||
@router.get("/realtime", response_model=RedisRealtimeStatsSchema, summary="获取Redis实时统计")
|
||||
async def get_redis_realtime_stats():
|
||||
"""获取Redis实时统计信息"""
|
||||
redis_host, redis_port, redis_password, redis_db = get_redis_config()
|
||||
|
||||
collector = AsyncRedisInfoCollector(
|
||||
host=redis_host,
|
||||
port=redis_port,
|
||||
password=redis_password,
|
||||
db=redis_db
|
||||
)
|
||||
|
||||
data = await collector.get_realtime_stats('project_redis')
|
||||
return RedisRealtimeStatsSchema(**data)
|
||||
|
||||
|
||||
@router.post("/test", response_model=RedisConnectionTestSchema, summary="测试Redis连接")
|
||||
async def test_redis_connection():
|
||||
"""测试Redis连接"""
|
||||
redis_host, redis_port, redis_password, redis_db = get_redis_config()
|
||||
|
||||
collector = AsyncRedisInfoCollector(
|
||||
host=redis_host,
|
||||
port=redis_port,
|
||||
password=redis_password,
|
||||
db=redis_db
|
||||
)
|
||||
|
||||
result = await collector.test_connection()
|
||||
return RedisConnectionTestSchema(**result)
|
||||
|
||||
|
||||
@router.get("/config", response_model=RedisConfigSchema, summary="获取Redis配置")
|
||||
def get_redis_config_info():
|
||||
"""获取Redis配置信息"""
|
||||
redis_host, redis_port, redis_password, redis_db = get_redis_config()
|
||||
|
||||
return RedisConfigSchema(
|
||||
host=redis_host,
|
||||
port=redis_port,
|
||||
database=redis_db,
|
||||
has_password=bool(redis_password),
|
||||
redis_url=settings.REDIS_URL or ''
|
||||
)
|
||||
@@ -0,0 +1,455 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Redis信息收集器(异步版本)
|
||||
"""
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Any, Optional
|
||||
|
||||
import redis.asyncio as aioredis
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def serialize_redis_data(data: Any) -> Any:
|
||||
"""递归地将Redis数据中的bytes转换为字符串"""
|
||||
if isinstance(data, bytes):
|
||||
try:
|
||||
return data.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
return str(data)
|
||||
elif isinstance(data, dict):
|
||||
return {serialize_redis_data(k): serialize_redis_data(v) for k, v in data.items()}
|
||||
elif isinstance(data, list):
|
||||
return [serialize_redis_data(item) for item in data]
|
||||
elif isinstance(data, tuple):
|
||||
return tuple(serialize_redis_data(item) for item in data)
|
||||
else:
|
||||
return data
|
||||
|
||||
|
||||
class AsyncRedisInfoCollector:
|
||||
"""异步Redis信息收集器"""
|
||||
|
||||
def __init__(self, host: str = 'localhost', port: int = 6379,
|
||||
password: Optional[str] = None, db: int = 0):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.password = password
|
||||
self.db = db
|
||||
self.client = None
|
||||
|
||||
async def connect(self) -> bool:
|
||||
"""连接Redis"""
|
||||
try:
|
||||
self.client = aioredis.Redis(
|
||||
host=self.host,
|
||||
port=self.port,
|
||||
password=self.password,
|
||||
db=self.db,
|
||||
decode_responses=True,
|
||||
socket_timeout=5,
|
||||
socket_connect_timeout=5
|
||||
)
|
||||
await self.client.ping()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to connect to Redis {self.host}:{self.port}: {e}")
|
||||
return False
|
||||
|
||||
async def disconnect(self):
|
||||
"""断开连接"""
|
||||
if self.client:
|
||||
try:
|
||||
await self.client.aclose()
|
||||
except Exception as e:
|
||||
logger.error(f"Error disconnecting from Redis: {e}")
|
||||
finally:
|
||||
self.client = None
|
||||
|
||||
async def test_connection(self) -> Dict[str, Any]:
|
||||
"""测试Redis连接"""
|
||||
start_time = time.time()
|
||||
try:
|
||||
if await self.connect():
|
||||
response_time = (time.time() - start_time) * 1000
|
||||
info = await self.client.info('server')
|
||||
redis_version = info.get('redis_version', 'unknown')
|
||||
return serialize_redis_data({
|
||||
'success': True,
|
||||
'message': '连接成功',
|
||||
'response_time': round(response_time, 2),
|
||||
'redis_version': redis_version
|
||||
})
|
||||
else:
|
||||
return {
|
||||
'success': False,
|
||||
'message': '连接失败',
|
||||
'response_time': None,
|
||||
'redis_version': None
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'success': False,
|
||||
'message': f'连接错误: {str(e)}',
|
||||
'response_time': None,
|
||||
'redis_version': None
|
||||
}
|
||||
finally:
|
||||
await self.disconnect()
|
||||
|
||||
async def get_server_info(self) -> Dict[str, Any]:
|
||||
"""获取Redis服务器信息"""
|
||||
if not self.client:
|
||||
if not await self.connect():
|
||||
return {}
|
||||
|
||||
try:
|
||||
info = await self.client.info('server')
|
||||
clients_info = await self.client.info('clients')
|
||||
return {
|
||||
'redis_version': info.get('redis_version', ''),
|
||||
'redis_mode': info.get('redis_mode', 'standalone'),
|
||||
'role': info.get('role', 'master'),
|
||||
'os': info.get('os', ''),
|
||||
'arch_bits': info.get('arch_bits', 64),
|
||||
'uptime_in_seconds': info.get('uptime_in_seconds', 0),
|
||||
'uptime_in_days': info.get('uptime_in_days', 0),
|
||||
'tcp_port': info.get('tcp_port', self.port),
|
||||
'connected_clients': clients_info.get('connected_clients', 0),
|
||||
'blocked_clients': clients_info.get('blocked_clients', 0)
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis server info: {e}")
|
||||
return {}
|
||||
|
||||
async def get_memory_info(self) -> Dict[str, Any]:
|
||||
"""获取Redis内存信息"""
|
||||
if not self.client:
|
||||
if not await self.connect():
|
||||
return {}
|
||||
|
||||
try:
|
||||
info = await self.client.info('memory')
|
||||
return {
|
||||
'used_memory': info.get('used_memory', 0),
|
||||
'used_memory_human': info.get('used_memory_human', '0B'),
|
||||
'used_memory_rss': info.get('used_memory_rss', 0),
|
||||
'used_memory_peak': info.get('used_memory_peak', 0),
|
||||
'used_memory_peak_human': info.get('used_memory_peak_human', '0B'),
|
||||
'total_system_memory': info.get('total_system_memory', 0),
|
||||
'total_system_memory_human': info.get('total_system_memory_human', '0B'),
|
||||
'used_memory_dataset': info.get('used_memory_dataset', 0),
|
||||
'used_memory_dataset_perc': info.get('used_memory_dataset_perc', '0%'),
|
||||
'allocator_allocated': info.get('allocator_allocated', 0),
|
||||
'allocator_active': info.get('allocator_active', 0),
|
||||
'maxmemory': info.get('maxmemory', 0),
|
||||
'maxmemory_human': info.get('maxmemory_human', '0B'),
|
||||
'maxmemory_policy': info.get('maxmemory_policy', 'noeviction'),
|
||||
'mem_fragmentation_ratio': info.get('mem_fragmentation_ratio', 1.0)
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis memory info: {e}")
|
||||
return {}
|
||||
|
||||
async def get_stats_info(self) -> Dict[str, Any]:
|
||||
"""获取Redis统计信息"""
|
||||
if not self.client:
|
||||
if not await self.connect():
|
||||
return {}
|
||||
|
||||
try:
|
||||
info = await self.client.info('stats')
|
||||
return {
|
||||
'total_connections_received': info.get('total_connections_received', 0),
|
||||
'total_commands_processed': info.get('total_commands_processed', 0),
|
||||
'instantaneous_ops_per_sec': info.get('instantaneous_ops_per_sec', 0),
|
||||
'total_net_input_bytes': info.get('total_net_input_bytes', 0),
|
||||
'total_net_output_bytes': info.get('total_net_output_bytes', 0),
|
||||
'instantaneous_input_kbps': info.get('instantaneous_input_kbps', 0.0),
|
||||
'instantaneous_output_kbps': info.get('instantaneous_output_kbps', 0.0),
|
||||
'rejected_connections': info.get('rejected_connections', 0),
|
||||
'sync_full': info.get('sync_full', 0),
|
||||
'sync_partial_ok': info.get('sync_partial_ok', 0),
|
||||
'sync_partial_err': info.get('sync_partial_err', 0),
|
||||
'expired_keys': info.get('expired_keys', 0),
|
||||
'evicted_keys': info.get('evicted_keys', 0),
|
||||
'keyspace_hits': info.get('keyspace_hits', 0),
|
||||
'keyspace_misses': info.get('keyspace_misses', 0),
|
||||
'pubsub_channels': info.get('pubsub_channels', 0),
|
||||
'pubsub_patterns': info.get('pubsub_patterns', 0),
|
||||
'latest_fork_usec': info.get('latest_fork_usec', 0),
|
||||
'migrate_cached_sockets': info.get('migrate_cached_sockets', 0)
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis stats info: {e}")
|
||||
return {}
|
||||
|
||||
async def get_keyspace_info(self) -> List[Dict[str, Any]]:
|
||||
"""获取Redis键空间信息"""
|
||||
if not self.client:
|
||||
if not await self.connect():
|
||||
return []
|
||||
|
||||
try:
|
||||
info = await self.client.info('keyspace')
|
||||
keyspaces = []
|
||||
|
||||
for key, value in info.items():
|
||||
if key.startswith('db'):
|
||||
db_id = int(key[2:])
|
||||
if isinstance(value, dict):
|
||||
stats = value
|
||||
elif isinstance(value, str):
|
||||
stats = {}
|
||||
for stat in value.split(','):
|
||||
if '=' in stat:
|
||||
stat_key, stat_value = stat.split('=', 1)
|
||||
try:
|
||||
stats[stat_key] = int(stat_value)
|
||||
except ValueError:
|
||||
stats[stat_key] = stat_value
|
||||
else:
|
||||
continue
|
||||
|
||||
keyspaces.append({
|
||||
'db_id': db_id,
|
||||
'keys': stats.get('keys', 0),
|
||||
'expires': stats.get('expires', 0),
|
||||
'avg_ttl': stats.get('avg_ttl', 0)
|
||||
})
|
||||
|
||||
return keyspaces
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis keyspace info: {e}")
|
||||
return []
|
||||
|
||||
async def get_clients_info(self, limit: int = 100) -> List[Dict[str, Any]]:
|
||||
"""获取Redis客户端信息"""
|
||||
if not self.client:
|
||||
if not await self.connect():
|
||||
return []
|
||||
|
||||
try:
|
||||
clients_raw = await self.client.client_list()
|
||||
clients = []
|
||||
|
||||
for client in clients_raw[:limit]:
|
||||
clients.append({
|
||||
'id': str(client.get('id', '')),
|
||||
'addr': client.get('addr', ''),
|
||||
'fd': client.get('fd', 0),
|
||||
'name': client.get('name', ''),
|
||||
'age': client.get('age', 0),
|
||||
'idle': client.get('idle', 0),
|
||||
'flags': client.get('flags', ''),
|
||||
'db': client.get('db', 0),
|
||||
'sub': client.get('sub', 0),
|
||||
'psub': client.get('psub', 0),
|
||||
'multi': client.get('multi', 0),
|
||||
'qbuf': client.get('qbuf', 0),
|
||||
'qbuf_free': client.get('qbuf-free', 0),
|
||||
'obl': client.get('obl', 0),
|
||||
'oll': client.get('oll', 0),
|
||||
'omem': client.get('omem', 0),
|
||||
'events': client.get('events', ''),
|
||||
'cmd': client.get('cmd', '')
|
||||
})
|
||||
|
||||
return clients
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis clients info: {e}")
|
||||
return []
|
||||
|
||||
async def get_slowlog(self, limit: int = 10) -> List[Dict[str, Any]]:
|
||||
"""获取Redis慢日志"""
|
||||
if not self.client:
|
||||
if not await self.connect():
|
||||
return []
|
||||
|
||||
try:
|
||||
slowlog_raw = await self.client.slowlog_get(limit)
|
||||
slowlog = []
|
||||
|
||||
for entry in slowlog_raw:
|
||||
slowlog.append({
|
||||
'id': entry['id'],
|
||||
'timestamp': entry['start_time'],
|
||||
'duration': entry['duration'],
|
||||
'command': ' '.join(str(arg) for arg in entry['command']),
|
||||
'client_ip': entry.get('client_address', 'unknown'),
|
||||
'client_name': entry.get('client_name', '')
|
||||
})
|
||||
|
||||
return slowlog
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis slowlog: {e}")
|
||||
return []
|
||||
|
||||
def _get_default_info(self) -> Dict[str, Any]:
|
||||
"""获取默认的info数据"""
|
||||
return {
|
||||
'redis_version': '',
|
||||
'redis_mode': 'standalone',
|
||||
'role': 'master',
|
||||
'os': '',
|
||||
'arch_bits': 64,
|
||||
'uptime_in_seconds': 0,
|
||||
'uptime_in_days': 0,
|
||||
'tcp_port': self.port,
|
||||
'connected_clients': 0,
|
||||
'blocked_clients': 0
|
||||
}
|
||||
|
||||
def _get_default_memory(self) -> Dict[str, Any]:
|
||||
"""获取默认的memory数据"""
|
||||
return {
|
||||
'used_memory': 0,
|
||||
'used_memory_human': '0B',
|
||||
'used_memory_rss': 0,
|
||||
'used_memory_peak': 0,
|
||||
'used_memory_peak_human': '0B',
|
||||
'total_system_memory': 0,
|
||||
'total_system_memory_human': '0B',
|
||||
'used_memory_dataset': 0,
|
||||
'used_memory_dataset_perc': '0%',
|
||||
'allocator_allocated': 0,
|
||||
'allocator_active': 0,
|
||||
'maxmemory': 0,
|
||||
'maxmemory_human': '0B',
|
||||
'maxmemory_policy': 'noeviction',
|
||||
'mem_fragmentation_ratio': 1.0
|
||||
}
|
||||
|
||||
def _get_default_stats(self) -> Dict[str, Any]:
|
||||
"""获取默认的stats数据"""
|
||||
return {
|
||||
'total_connections_received': 0,
|
||||
'total_commands_processed': 0,
|
||||
'instantaneous_ops_per_sec': 0,
|
||||
'total_net_input_bytes': 0,
|
||||
'total_net_output_bytes': 0,
|
||||
'instantaneous_input_kbps': 0.0,
|
||||
'instantaneous_output_kbps': 0.0,
|
||||
'rejected_connections': 0,
|
||||
'sync_full': 0,
|
||||
'sync_partial_ok': 0,
|
||||
'sync_partial_err': 0,
|
||||
'expired_keys': 0,
|
||||
'evicted_keys': 0,
|
||||
'keyspace_hits': 0,
|
||||
'keyspace_misses': 0,
|
||||
'pubsub_channels': 0,
|
||||
'pubsub_patterns': 0,
|
||||
'latest_fork_usec': 0,
|
||||
'migrate_cached_sockets': 0
|
||||
}
|
||||
|
||||
async def get_all_info(self, connection_id: str, connection_name: str) -> Dict[str, Any]:
|
||||
"""获取所有Redis监控信息"""
|
||||
timestamp = datetime.now().isoformat()
|
||||
|
||||
try:
|
||||
if not await self.connect():
|
||||
return {
|
||||
'connection_id': connection_id,
|
||||
'connection_name': connection_name,
|
||||
'status': 'disconnected',
|
||||
'info': self._get_default_info(),
|
||||
'memory': self._get_default_memory(),
|
||||
'stats': self._get_default_stats(),
|
||||
'keyspace': [],
|
||||
'clients': [],
|
||||
'slow_log': [],
|
||||
'timestamp': timestamp
|
||||
}
|
||||
|
||||
data = {
|
||||
'connection_id': connection_id,
|
||||
'connection_name': connection_name,
|
||||
'status': 'connected',
|
||||
'info': await self.get_server_info(),
|
||||
'memory': await self.get_memory_info(),
|
||||
'stats': await self.get_stats_info(),
|
||||
'keyspace': await self.get_keyspace_info(),
|
||||
'clients': await self.get_clients_info(),
|
||||
'slow_log': await self.get_slowlog(),
|
||||
'timestamp': timestamp
|
||||
}
|
||||
return serialize_redis_data(data)
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis all info: {e}")
|
||||
return {
|
||||
'connection_id': connection_id,
|
||||
'connection_name': connection_name,
|
||||
'status': 'error',
|
||||
'info': self._get_default_info(),
|
||||
'memory': self._get_default_memory(),
|
||||
'stats': self._get_default_stats(),
|
||||
'keyspace': [],
|
||||
'clients': [],
|
||||
'slow_log': [],
|
||||
'timestamp': timestamp
|
||||
}
|
||||
finally:
|
||||
await self.disconnect()
|
||||
|
||||
async def get_realtime_stats(self, connection_id: str) -> Dict[str, Any]:
|
||||
"""获取实时统计信息"""
|
||||
timestamp = datetime.now().isoformat()
|
||||
|
||||
try:
|
||||
if not await self.connect():
|
||||
return {
|
||||
'connection_id': connection_id,
|
||||
'used_memory': 0,
|
||||
'memory_usage_percent': 0.0,
|
||||
'connected_clients': 0,
|
||||
'ops_per_sec': 0,
|
||||
'hit_rate': 0.0,
|
||||
'keyspace_hits': 0,
|
||||
'keyspace_misses': 0,
|
||||
'timestamp': timestamp
|
||||
}
|
||||
|
||||
memory_info = await self.get_memory_info()
|
||||
stats_info = await self.get_stats_info()
|
||||
server_info = await self.get_server_info()
|
||||
|
||||
used_memory = memory_info.get('used_memory', 0)
|
||||
total_memory = memory_info.get('total_system_memory', 0)
|
||||
memory_usage_percent = (used_memory / total_memory * 100) if total_memory > 0 else 0.0
|
||||
|
||||
hits = stats_info.get('keyspace_hits', 0)
|
||||
misses = stats_info.get('keyspace_misses', 0)
|
||||
hit_rate = (hits / (hits + misses) * 100) if (hits + misses) > 0 else 0.0
|
||||
|
||||
data = {
|
||||
'connection_id': connection_id,
|
||||
'used_memory': used_memory,
|
||||
'memory_usage_percent': round(memory_usage_percent, 2),
|
||||
'connected_clients': server_info.get('connected_clients', 0),
|
||||
'ops_per_sec': stats_info.get('instantaneous_ops_per_sec', 0),
|
||||
'hit_rate': round(hit_rate, 2),
|
||||
'keyspace_hits': hits,
|
||||
'keyspace_misses': misses,
|
||||
'timestamp': timestamp
|
||||
}
|
||||
return serialize_redis_data(data)
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting Redis realtime stats: {e}")
|
||||
return {
|
||||
'connection_id': connection_id,
|
||||
'used_memory': 0,
|
||||
'memory_usage_percent': 0.0,
|
||||
'connected_clients': 0,
|
||||
'ops_per_sec': 0,
|
||||
'hit_rate': 0.0,
|
||||
'keyspace_hits': 0,
|
||||
'keyspace_misses': 0,
|
||||
'timestamp': timestamp
|
||||
}
|
||||
finally:
|
||||
await self.disconnect()
|
||||
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Redis监控Schema
|
||||
"""
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class RedisInfoSchema(BaseModel):
|
||||
"""Redis基础信息Schema"""
|
||||
redis_version: str = Field(..., description="Redis版本")
|
||||
redis_mode: str = Field(..., description="Redis模式")
|
||||
role: str = Field(..., description="角色")
|
||||
os: str = Field(..., description="操作系统")
|
||||
arch_bits: int = Field(..., description="架构位数")
|
||||
uptime_in_seconds: int = Field(..., description="运行时间(秒)")
|
||||
uptime_in_days: int = Field(..., description="运行时间(天)")
|
||||
tcp_port: int = Field(..., description="TCP端口")
|
||||
connected_clients: int = Field(..., description="连接的客户端数量")
|
||||
blocked_clients: int = Field(..., description="阻塞的客户端数量")
|
||||
|
||||
|
||||
class RedisMemorySchema(BaseModel):
|
||||
"""Redis内存信息Schema"""
|
||||
used_memory: int = Field(..., description="已使用内存(字节)")
|
||||
used_memory_human: str = Field(..., description="已使用内存(人类可读)")
|
||||
used_memory_rss: int = Field(..., description="RSS内存使用(字节)")
|
||||
used_memory_peak: int = Field(..., description="内存使用峰值(字节)")
|
||||
used_memory_peak_human: str = Field(..., description="内存使用峰值(人类可读)")
|
||||
total_system_memory: int = Field(..., description="系统总内存(字节)")
|
||||
total_system_memory_human: str = Field(..., description="系统总内存(人类可读)")
|
||||
used_memory_dataset: int = Field(..., description="数据集内存使用(字节)")
|
||||
used_memory_dataset_perc: str = Field(..., description="数据集内存使用百分比")
|
||||
allocator_allocated: int = Field(..., description="分配器已分配内存")
|
||||
allocator_active: int = Field(..., description="分配器活跃内存")
|
||||
maxmemory: int = Field(..., description="最大内存限制")
|
||||
maxmemory_human: str = Field(..., description="最大内存限制(人类可读)")
|
||||
maxmemory_policy: str = Field(..., description="内存策略")
|
||||
mem_fragmentation_ratio: float = Field(..., description="内存碎片率")
|
||||
|
||||
|
||||
class RedisStatsSchema(BaseModel):
|
||||
"""Redis统计信息Schema"""
|
||||
total_connections_received: int = Field(..., description="总连接数")
|
||||
total_commands_processed: int = Field(..., description="总命令处理数")
|
||||
instantaneous_ops_per_sec: int = Field(..., description="每秒操作数")
|
||||
total_net_input_bytes: int = Field(..., description="总输入字节数")
|
||||
total_net_output_bytes: int = Field(..., description="总输出字节数")
|
||||
instantaneous_input_kbps: float = Field(..., description="每秒输入KB")
|
||||
instantaneous_output_kbps: float = Field(..., description="每秒输出KB")
|
||||
rejected_connections: int = Field(..., description="拒绝的连接数")
|
||||
sync_full: int = Field(..., description="完整同步次数")
|
||||
sync_partial_ok: int = Field(..., description="部分同步成功次数")
|
||||
sync_partial_err: int = Field(..., description="部分同步失败次数")
|
||||
expired_keys: int = Field(..., description="过期键数量")
|
||||
evicted_keys: int = Field(..., description="被驱逐键数量")
|
||||
keyspace_hits: int = Field(..., description="键空间命中数")
|
||||
keyspace_misses: int = Field(..., description="键空间未命中数")
|
||||
pubsub_channels: int = Field(..., description="发布订阅频道数")
|
||||
pubsub_patterns: int = Field(..., description="发布订阅模式数")
|
||||
latest_fork_usec: int = Field(..., description="最近fork时间(微秒)")
|
||||
migrate_cached_sockets: int = Field(..., description="迁移缓存套接字数")
|
||||
|
||||
|
||||
class RedisKeyspaceSchema(BaseModel):
|
||||
"""Redis键空间信息Schema"""
|
||||
db_id: int = Field(..., description="数据库ID")
|
||||
keys: int = Field(..., description="键数量")
|
||||
expires: int = Field(..., description="过期键数量")
|
||||
avg_ttl: int = Field(..., description="平均TTL")
|
||||
|
||||
|
||||
class RedisSlowLogSchema(BaseModel):
|
||||
"""Redis慢日志Schema"""
|
||||
id: int = Field(..., description="日志ID")
|
||||
timestamp: int = Field(..., description="时间戳")
|
||||
duration: int = Field(..., description="执行时间(微秒)")
|
||||
command: str = Field(..., description="命令")
|
||||
client_ip: str = Field(..., description="客户端IP")
|
||||
client_name: str = Field(..., description="客户端名称")
|
||||
|
||||
|
||||
class RedisClientSchema(BaseModel):
|
||||
"""Redis客户端信息Schema"""
|
||||
id: str = Field(..., description="客户端ID")
|
||||
addr: str = Field(..., description="客户端地址")
|
||||
fd: int = Field(..., description="文件描述符")
|
||||
name: str = Field(..., description="客户端名称")
|
||||
age: int = Field(..., description="连接时长(秒)")
|
||||
idle: int = Field(..., description="空闲时间(秒)")
|
||||
flags: str = Field(..., description="客户端标志")
|
||||
db: int = Field(..., description="数据库")
|
||||
sub: int = Field(..., description="订阅频道数")
|
||||
psub: int = Field(..., description="订阅模式数")
|
||||
multi: int = Field(..., description="事务命令数")
|
||||
qbuf: int = Field(..., description="查询缓冲区长度")
|
||||
qbuf_free: int = Field(..., description="查询缓冲区剩余空间")
|
||||
obl: int = Field(..., description="输出缓冲区长度")
|
||||
oll: int = Field(..., description="输出列表长度")
|
||||
omem: int = Field(..., description="输出内存使用")
|
||||
events: str = Field(..., description="文件描述符事件")
|
||||
cmd: str = Field(..., description="最后执行的命令")
|
||||
|
||||
|
||||
class RedisMonitorOverviewSchema(BaseModel):
|
||||
"""Redis监控概览Schema"""
|
||||
connection_id: str = Field(..., description="连接ID")
|
||||
connection_name: str = Field(..., description="连接名称")
|
||||
status: str = Field(..., description="连接状态")
|
||||
info: RedisInfoSchema = Field(..., description="基础信息")
|
||||
memory: RedisMemorySchema = Field(..., description="内存信息")
|
||||
stats: RedisStatsSchema = Field(..., description="统计信息")
|
||||
keyspace: List[RedisKeyspaceSchema] = Field(default=[], description="键空间信息")
|
||||
clients: List[RedisClientSchema] = Field(default=[], description="客户端信息")
|
||||
slow_log: List[RedisSlowLogSchema] = Field(default=[], description="慢日志")
|
||||
timestamp: str = Field(..., description="时间戳")
|
||||
|
||||
|
||||
class RedisRealtimeStatsSchema(BaseModel):
|
||||
"""Redis实时统计Schema"""
|
||||
connection_id: str = Field(..., description="连接ID")
|
||||
used_memory: int = Field(..., description="已使用内存")
|
||||
memory_usage_percent: float = Field(..., description="内存使用率")
|
||||
connected_clients: int = Field(..., description="连接客户端数")
|
||||
ops_per_sec: int = Field(..., description="每秒操作数")
|
||||
hit_rate: float = Field(..., description="命中率")
|
||||
keyspace_hits: int = Field(..., description="键空间命中数")
|
||||
keyspace_misses: int = Field(..., description="键空间未命中数")
|
||||
timestamp: str = Field(..., description="时间戳")
|
||||
|
||||
|
||||
class RedisConnectionTestSchema(BaseModel):
|
||||
"""Redis连接测试Schema"""
|
||||
success: bool = Field(..., description="连接是否成功")
|
||||
message: str = Field(..., description="测试结果消息")
|
||||
response_time: Optional[float] = Field(None, description="响应时间(毫秒)")
|
||||
redis_version: Optional[str] = Field(None, description="Redis版本")
|
||||
|
||||
|
||||
class RedisConfigSchema(BaseModel):
|
||||
"""Redis配置信息Schema"""
|
||||
host: str = Field(..., description="主机地址")
|
||||
port: int = Field(..., description="端口")
|
||||
database: int = Field(..., description="数据库编号")
|
||||
has_password: bool = Field(..., description="是否有密码")
|
||||
redis_url: str = Field(default='', description="Redis URL")
|
||||
Reference in New Issue
Block a user