Files
py-wikijs/tests/test_metrics.py
Claude cef6903cbc feat: implement production-ready features from improvement plan phase 2.5 & 2.6
Phase 2.5: Fix Foundation (CRITICAL)
- Fixed 4 failing tests by adding cache attribute to mock_client fixture
- Created comprehensive cache tests for Pages endpoint (test_pages_cache.py)
- Added missing dependencies: pydantic[email] and aiohttp to core requirements
- Updated requirements.txt with proper dependency versions
- Achieved 82.67% test coverage with 454 passing tests

Phase 2.6: Production Essentials
- Implemented structured logging (wikijs/logging.py)
  * JSON and text log formatters
  * Configurable log levels and output destinations
  * Integration with client operations

- Implemented metrics and telemetry (wikijs/metrics.py)
  * Request tracking with duration, status codes, errors
  * Latency percentiles (min, max, avg, p50, p95, p99)
  * Error rate calculation
  * Thread-safe metrics collection

- Implemented rate limiting (wikijs/ratelimit.py)
  * Token bucket algorithm for request throttling
  * Per-endpoint rate limiting support
  * Configurable timeout handling
  * Burst capacity management

- Created SECURITY.md policy
  * Vulnerability reporting procedures
  * Security best practices
  * Response timelines
  * Supported versions

Documentation
- Added comprehensive logging guide (docs/logging.md)
- Added metrics and telemetry guide (docs/metrics.md)
- Added rate limiting guide (docs/rate_limiting.md)
- Updated README.md with production features section
- Updated IMPROVEMENT_PLAN_2.md with completed checkboxes

Testing
- Created test suite for logging (tests/test_logging.py)
- Created test suite for metrics (tests/test_metrics.py)
- Created test suite for rate limiting (tests/test_ratelimit.py)
- All 454 tests passing
- Test coverage: 82.67%

Breaking Changes: None
Dependencies Added: pydantic[email], email-validator, dnspython

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 16:45:02 +00:00

90 lines
2.3 KiB
Python

"""Tests for metrics functionality."""
from wikijs.metrics import MetricsCollector, get_metrics
def test_metrics_collector_init():
"""Test metrics collector initialization."""
collector = MetricsCollector()
stats = collector.get_stats()
assert stats["total_requests"] == 0
assert stats["total_errors"] == 0
def test_record_request():
"""Test recording requests."""
collector = MetricsCollector()
# Record successful request
collector.record_request("/api/test", "GET", 200, 100.0)
stats = collector.get_stats()
assert stats["total_requests"] == 1
assert stats["total_errors"] == 0
def test_record_error():
"""Test recording errors."""
collector = MetricsCollector()
# Record error request
collector.record_request("/api/test", "GET", 404, 50.0, error="Not found")
stats = collector.get_stats()
assert stats["total_requests"] == 1
assert stats["total_errors"] == 1
def test_latency_stats():
"""Test latency statistics."""
collector = MetricsCollector()
# Record multiple requests
collector.record_request("/api/test", "GET", 200, 100.0)
collector.record_request("/api/test", "GET", 200, 200.0)
collector.record_request("/api/test", "GET", 200, 150.0)
stats = collector.get_stats()
assert "latency" in stats
assert stats["latency"]["min"] == 100.0
assert stats["latency"]["max"] == 200.0
assert stats["latency"]["avg"] == 150.0
def test_increment_counter():
"""Test incrementing counters."""
collector = MetricsCollector()
collector.increment("custom_counter", 5)
collector.increment("custom_counter", 3)
stats = collector.get_stats()
assert stats["counters"]["custom_counter"] == 8
def test_set_gauge():
"""Test setting gauges."""
collector = MetricsCollector()
collector.set_gauge("memory_usage", 75.5)
stats = collector.get_stats()
assert stats["gauges"]["memory_usage"] == 75.5
def test_reset_metrics():
"""Test resetting metrics."""
collector = MetricsCollector()
collector.record_request("/api/test", "GET", 200, 100.0)
collector.reset()
stats = collector.get_stats()
assert stats["total_requests"] == 0
def test_get_global_metrics():
"""Test getting global metrics instance."""
metrics = get_metrics()
assert isinstance(metrics, MetricsCollector)