341 lines
9.7 KiB
Python
341 lines
9.7 KiB
Python
"""监控测试:权限系统监控功能验证
|
|
|
|
测试权限系统的监控功能,包括:
|
|
- 指标收集
|
|
- 告警生成
|
|
- 健康检查
|
|
"""
|
|
|
|
import time
|
|
import uuid
|
|
|
|
import pytest
|
|
|
|
from app.core.permission_monitor import (
|
|
PermissionMonitor,
|
|
PermissionCheckMetrics,
|
|
CacheMetrics,
|
|
get_permission_monitor,
|
|
set_permission_monitor,
|
|
evaluate_permission_system_health,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_permission_check_metrics():
|
|
"""测试权限检查指标"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录权限检查
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.005)
|
|
monitor.record_permission_check(allowed=False, elapsed_time=0.003)
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.004)
|
|
|
|
metrics = monitor.metrics.check_metrics
|
|
assert metrics.total_checks == 3
|
|
assert metrics.allowed_checks == 2
|
|
assert metrics.denied_checks == 1
|
|
assert metrics.allow_rate == pytest.approx(66.67, 0.1)
|
|
assert metrics.deny_rate == pytest.approx(33.33, 0.1)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_permission_check_timing():
|
|
"""测试权限检查耗时统计"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录不同耗时的权限检查
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.001)
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.005)
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.003)
|
|
|
|
metrics = monitor.metrics.check_metrics
|
|
assert metrics.min_time == pytest.approx(0.001, 0.0001)
|
|
assert metrics.max_time == pytest.approx(0.005, 0.0001)
|
|
assert metrics.avg_time == pytest.approx(0.003, 0.0001)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cache_metrics():
|
|
"""测试缓存指标"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录缓存访问
|
|
monitor.record_cache_hit()
|
|
monitor.record_cache_hit()
|
|
monitor.record_cache_miss()
|
|
monitor.record_cache_hit()
|
|
|
|
metrics = monitor.metrics.cache_metrics
|
|
assert metrics.total_accesses == 4
|
|
assert metrics.cache_hits == 3
|
|
assert metrics.cache_misses == 1
|
|
assert metrics.hit_rate == pytest.approx(75.0, 0.1)
|
|
assert metrics.miss_rate == pytest.approx(25.0, 0.1)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cache_invalidation_tracking():
|
|
"""测试缓存失效追踪"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录缓存失效
|
|
monitor.record_cache_invalidation()
|
|
monitor.record_cache_invalidation()
|
|
monitor.record_cache_invalidation()
|
|
|
|
metrics = monitor.metrics.cache_metrics
|
|
assert metrics.cache_invalidations == 3
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_tracking():
|
|
"""测试错误追踪"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录权限检查错误
|
|
error = ValueError("test error")
|
|
monitor.record_permission_check(allowed=False, elapsed_time=0.005, error=error)
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.003)
|
|
|
|
metrics = monitor.metrics.check_metrics
|
|
assert metrics.errors == 1
|
|
assert metrics.error_rate == pytest.approx(50.0, 0.1)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_alert_generation():
|
|
"""测试告警生成"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录慢速权限检查(应该生成告警)
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.1)
|
|
|
|
alerts = monitor.get_alerts()
|
|
assert len(alerts) > 0
|
|
assert alerts[0]["type"] == "slow_permission_check"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_error_alert_generation():
|
|
"""测试错误告警生成"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录权限检查错误(应该生成告警)
|
|
error = ValueError("test error")
|
|
monitor.record_permission_check(allowed=False, elapsed_time=0.005, error=error)
|
|
|
|
alerts = monitor.get_alerts()
|
|
assert len(alerts) > 0
|
|
assert alerts[0]["type"] == "permission_check_error"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_alert_filtering():
|
|
"""测试告警过滤"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 生成不同级别的告警
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.1) # warning
|
|
error = ValueError("test error")
|
|
monitor.record_permission_check(allowed=False, elapsed_time=0.005, error=error) # error
|
|
|
|
# 过滤 warning 级别的告警
|
|
warning_alerts = monitor.get_alerts(level="warning")
|
|
assert len(warning_alerts) > 0
|
|
assert all(a["level"] == "warning" for a in warning_alerts)
|
|
|
|
# 过滤 error 级别的告警
|
|
error_alerts = monitor.get_alerts(level="error")
|
|
assert len(error_alerts) > 0
|
|
assert all(a["level"] == "error" for a in error_alerts)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_alert_limit():
|
|
"""测试告警数量限制"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 生成大量告警
|
|
for _ in range(50):
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.1)
|
|
|
|
# 获取告警,限制为10条
|
|
alerts = monitor.get_alerts(limit=10)
|
|
assert len(alerts) == 10
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_metrics_reset():
|
|
"""测试指标重置"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录一些指标
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.005)
|
|
monitor.record_cache_hit()
|
|
|
|
assert monitor.metrics.check_metrics.total_checks == 1
|
|
assert monitor.metrics.cache_metrics.total_accesses == 1
|
|
|
|
# 重置指标
|
|
monitor.reset_metrics()
|
|
|
|
assert monitor.metrics.check_metrics.total_checks == 0
|
|
assert monitor.metrics.cache_metrics.total_accesses == 0
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_alerts_clear():
|
|
"""测试告警清除"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 生成告警
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.1)
|
|
|
|
assert len(monitor.get_alerts()) > 0
|
|
|
|
# 清除告警
|
|
monitor.clear_alerts()
|
|
|
|
assert len(monitor.get_alerts()) == 0
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_metrics_to_dict():
|
|
"""测试指标转换为字典"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录指标
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.005)
|
|
monitor.record_permission_check(allowed=False, elapsed_time=0.003)
|
|
monitor.record_cache_hit()
|
|
monitor.record_cache_miss()
|
|
|
|
metrics_dict = monitor.get_metrics()
|
|
|
|
assert "check_metrics" in metrics_dict
|
|
assert "cache_metrics" in metrics_dict
|
|
assert "uptime_seconds" in metrics_dict
|
|
|
|
check_metrics = metrics_dict["check_metrics"]
|
|
assert check_metrics["total_checks"] == 2
|
|
assert check_metrics["allowed_checks"] == 1
|
|
assert check_metrics["denied_checks"] == 1
|
|
|
|
cache_metrics = metrics_dict["cache_metrics"]
|
|
assert cache_metrics["total_accesses"] == 2
|
|
assert cache_metrics["cache_hits"] == 1
|
|
assert cache_metrics["cache_misses"] == 1
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_global_monitor_instance():
|
|
"""测试全局监控器实例"""
|
|
monitor1 = get_permission_monitor()
|
|
monitor2 = get_permission_monitor()
|
|
|
|
# 应该是同一个实例
|
|
assert monitor1 is monitor2
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_set_global_monitor():
|
|
"""测试设置全局监控器实例"""
|
|
new_monitor = PermissionMonitor()
|
|
set_permission_monitor(new_monitor)
|
|
|
|
monitor = get_permission_monitor()
|
|
assert monitor is new_monitor
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_alert_timestamp():
|
|
"""测试告警时间戳"""
|
|
monitor = PermissionMonitor()
|
|
|
|
before_time = time.time()
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.1)
|
|
after_time = time.time()
|
|
|
|
alerts = monitor.get_alerts()
|
|
assert len(alerts) > 0
|
|
assert before_time <= alerts[0]["timestamp"] <= after_time
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_alert_data():
|
|
"""测试告警数据"""
|
|
monitor = PermissionMonitor()
|
|
|
|
# 记录慢速权限检查
|
|
monitor.record_permission_check(allowed=True, elapsed_time=0.1)
|
|
|
|
alerts = monitor.get_alerts()
|
|
assert len(alerts) > 0
|
|
assert "data" in alerts[0]
|
|
assert "elapsed_time" in alerts[0]["data"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_permission_check_metrics_dataclass():
|
|
"""测试权限检查指标数据类"""
|
|
metrics = PermissionCheckMetrics()
|
|
|
|
# 初始状态
|
|
assert metrics.total_checks == 0
|
|
assert metrics.avg_time == 0.0
|
|
assert metrics.allow_rate == 0.0
|
|
|
|
# 添加数据
|
|
metrics.total_checks = 100
|
|
metrics.allowed_checks = 80
|
|
metrics.denied_checks = 20
|
|
metrics.total_time = 0.5
|
|
|
|
assert metrics.avg_time == pytest.approx(0.005, 0.0001)
|
|
assert metrics.allow_rate == pytest.approx(80.0, 0.1)
|
|
assert metrics.deny_rate == pytest.approx(20.0, 0.1)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cache_metrics_dataclass():
|
|
"""测试缓存指标数据类"""
|
|
metrics = CacheMetrics()
|
|
|
|
# 初始状态
|
|
assert metrics.total_accesses == 0
|
|
assert metrics.hit_rate == 0.0
|
|
|
|
# 添加数据
|
|
metrics.total_accesses = 100
|
|
metrics.cache_hits = 80
|
|
metrics.cache_misses = 20
|
|
|
|
assert metrics.hit_rate == pytest.approx(80.0, 0.1)
|
|
assert metrics.miss_rate == pytest.approx(20.0, 0.1)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_health_check_ignores_cache_hit_rate_without_samples():
|
|
"""没有缓存访问样本时,不应判定缓存命中率过低"""
|
|
monitor = PermissionMonitor()
|
|
metrics = monitor.get_metrics()
|
|
cache_stats = monitor.get_cache_stats()
|
|
|
|
health = evaluate_permission_system_health(metrics, cache_stats)
|
|
|
|
assert metrics["cache_metrics"]["total_accesses"] == 0
|
|
assert "缓存命中率过低" not in health["issues"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_health_check_ignores_cache_hit_rate_with_too_few_samples():
|
|
"""缓存访问样本过少时,不应判定缓存命中率过低"""
|
|
monitor = PermissionMonitor()
|
|
for _ in range(3):
|
|
monitor.record_cache_miss()
|
|
|
|
health = evaluate_permission_system_health(monitor.get_metrics(), monitor.get_cache_stats())
|
|
|
|
assert "缓存命中率过低" not in health["issues"]
|