- Backend: Go API server with Gin framework - Frontend: React setup (placeholder) - ML Service: Python FastAPI skeleton - Docker Compose: Full stack configuration - Database: PostgreSQL schema with migrations - Documentation: Implementation plan and README Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
123 lines
2.9 KiB
Python
123 lines
2.9 KiB
Python
from fastapi import FastAPI, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from pydantic import BaseModel
|
|
from typing import List, Dict, Any, Optional
|
|
import logging
|
|
|
|
# Configure logging
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
app = FastAPI(
|
|
title="VictoriaLogs ML Service",
|
|
description="Machine Learning service for anomaly detection in logs",
|
|
version="1.0.0"
|
|
)
|
|
|
|
# CORS middleware
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Request/Response models
|
|
class TrainRequest(BaseModel):
|
|
model_name: str
|
|
query: str
|
|
start_time: str
|
|
end_time: str
|
|
contamination: float = 0.1
|
|
|
|
class DetectRequest(BaseModel):
|
|
model_name: str
|
|
logs: List[Dict[str, Any]]
|
|
|
|
class TrainResponse(BaseModel):
|
|
status: str
|
|
model_name: str
|
|
model_path: str
|
|
message: str
|
|
|
|
class DetectResponse(BaseModel):
|
|
status: str
|
|
anomalies: List[Dict[str, Any]]
|
|
anomaly_count: int
|
|
|
|
@app.get("/")
|
|
async def root():
|
|
return {
|
|
"service": "VictoriaLogs ML Service",
|
|
"status": "running",
|
|
"version": "1.0.0"
|
|
}
|
|
|
|
@app.get("/health")
|
|
async def health_check():
|
|
return {"status": "healthy"}
|
|
|
|
@app.post("/api/ml/train", response_model=TrainResponse)
|
|
async def train_model(request: TrainRequest):
|
|
"""
|
|
Train an anomaly detection model on historical logs
|
|
"""
|
|
logger.info(f"Training model: {request.model_name}")
|
|
|
|
# TODO: Implement model training
|
|
# 1. Fetch logs from VictoriaLogs
|
|
# 2. Extract features
|
|
# 3. Train Isolation Forest model
|
|
# 4. Save model to disk
|
|
|
|
return TrainResponse(
|
|
status="success",
|
|
model_name=request.model_name,
|
|
model_path=f"/app/models/{request.model_name}.pkl",
|
|
message="Model training not yet implemented"
|
|
)
|
|
|
|
@app.post("/api/ml/detect", response_model=DetectResponse)
|
|
async def detect_anomalies(request: DetectRequest):
|
|
"""
|
|
Detect anomalies in a batch of logs using a trained model
|
|
"""
|
|
logger.info(f"Detecting anomalies with model: {request.model_name}")
|
|
|
|
# TODO: Implement anomaly detection
|
|
# 1. Load trained model
|
|
# 2. Extract features from logs
|
|
# 3. Predict anomalies
|
|
# 4. Return flagged logs with scores
|
|
|
|
return DetectResponse(
|
|
status="success",
|
|
anomalies=[],
|
|
anomaly_count=0
|
|
)
|
|
|
|
@app.get("/api/ml/models")
|
|
async def list_models():
|
|
"""
|
|
List all trained models
|
|
"""
|
|
# TODO: List model files from disk
|
|
return {
|
|
"models": [],
|
|
"count": 0
|
|
}
|
|
|
|
@app.delete("/api/ml/models/{model_name}")
|
|
async def delete_model(model_name: str):
|
|
"""
|
|
Delete a trained model
|
|
"""
|
|
logger.info(f"Deleting model: {model_name}")
|
|
|
|
# TODO: Delete model file
|
|
return {
|
|
"status": "success",
|
|
"message": f"Model {model_name} deleted"
|
|
}
|