Files
core-api/src/domains/tools/controller.py
T
Jeroen SchweitzerandClaude Opus 4.5 075b0ec297
Build and Push / build (release) Successful in 1m44s
feat: add system stats API for dashboard monitoring
- GET /tools/system/stats - Real-time host system statistics
- CPU usage, memory, all mounted disks, network I/O
- GPU/VRAM stats via nvidia-smi (if available)
- Uses psutil for cross-platform host metrics
- Auto-discovers and filters real filesystems

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 17:30:45 +01:00

154 lines
5.3 KiB
Python

"""
Tools Controller
Provides utility tool endpoints including:
- DNS lookups
- System stats
"""
from fastapi import APIRouter, HTTPException, status
from src.shared.base import BaseController
from src.shared.logging import get_logger
from src.domains.tools.dns.schemas import DNSLookupRequest, DNSLookupResponse
from src.domains.tools.dns.service import DNSService
from src.domains.tools.dns.exceptions import DNSQueryError
from src.domains.tools.system.schemas import SystemStatsResponse
from src.domains.tools.system.service import SystemStatsService
logger = get_logger(__name__)
class ToolsController(BaseController):
"""
Controller for utility tools
Provides endpoints for:
- DNS lookups
- System stats
"""
def __init__(self):
super().__init__(prefix="/tools", tags=["Tools"])
self.dns_service = DNSService()
self.system_stats_service = SystemStatsService()
def create_router(self) -> APIRouter:
"""Create and configure the router"""
router = APIRouter(prefix=self.prefix, tags=self.tags)
@router.post(
"/dns/lookup",
response_model=DNSLookupResponse,
status_code=status.HTTP_200_OK,
summary="Perform DNS lookup",
description="""
Perform DNS lookups for various record types.
Uses dnspython for reliable DNS queries with support for multiple record types
and custom nameservers. Perfect for troubleshooting DNS issues and checking
domain configurations.
**Supported Record Types:**
- A: IPv4 address records
- AAAA: IPv6 address records
- MX: Mail exchange records
- TXT: Text records (SPF, DKIM, etc.)
- CNAME: Canonical name records
- NS: Nameserver records
- SOA: Start of authority records
- PTR: Pointer records (reverse DNS)
- CAA: Certification authority authorization
- SRV: Service records
**Features:**
- Custom nameserver support (e.g., 8.8.8.8, 1.1.1.1)
- Query time measurement
- Detailed error messages
**Rate Limiting:** None (internal network use only)
"""
)
async def dns_lookup(request: DNSLookupRequest) -> DNSLookupResponse:
"""
Perform DNS lookup for a domain
Args:
request: DNS lookup request with domain, record type, and optional nameserver
Returns:
DNS lookup results with records and metadata
Raises:
HTTPException: 400 for invalid queries, 500 for processing errors
"""
try:
logger.info(f"Received DNS lookup request for: {request.domain} ({request.record_type})")
result = await self.dns_service.lookup(request)
return result
except DNSQueryError as e:
logger.warning(f"DNS query error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"DNS query failed: {str(e)}"
)
except Exception as e:
logger.error(f"Unexpected error during DNS lookup: {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An unexpected error occurred during DNS lookup"
)
@router.get(
"/system/stats",
response_model=SystemStatsResponse,
status_code=status.HTTP_200_OK,
summary="Get host system statistics",
description="""
Get real-time host system resource statistics.
Returns CPU, memory, disk, network, and GPU/VRAM usage for the host machine
(not Docker container metrics).
**Metrics Returned:**
- **CPU:** Usage percentage, core count, load averages
- **Memory:** Usage percentage, total/used/available bytes
- **Disk:** Usage percentage, total/used/free bytes (root partition)
- **Network:** Total bytes sent/received
- **GPU:** VRAM usage (if NVIDIA GPU available via nvidia-smi)
**Use Cases:**
- Dashboard system monitoring widgets
- Health checks and alerting
- Capacity planning
"""
)
async def get_system_stats() -> SystemStatsResponse:
"""
Get current host system statistics
Returns:
System statistics including CPU, memory, disk, network, and GPU
Raises:
HTTPException: 500 for processing errors
"""
try:
logger.info("Fetching system stats")
result = await self.system_stats_service.get_stats()
return result
except Exception as e:
logger.error(f"Failed to get system stats: {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to collect system stats: {str(e)}"
)
return router
# Create controller instance
tools_controller = ToolsController()