from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score app = FastAPI( title="JMeter Performance Analyzer API", description="API que recebe um CSV do JMeter, treina um modelo linear e retorna métricas e dados para visualização.", version="1.0.0" ) # ====================================== # 🔓 CORS – permite chamadas do front-end React # ====================================== app.add_middleware( CORSMiddleware, allow_origins=["*"], # 🔒 em produção, especifique seu domínio allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # ====================================== # 🧠 Função auxiliar # ====================================== def treinar_modelo(df: pd.DataFrame): """Treina o modelo linear e retorna métricas e previsões.""" df['timeStamp'] = pd.to_datetime(df['timeStamp'], unit='ms', errors='coerce') df.dropna(subset=['timeStamp', 'elapsed'], inplace=True) # Cria eixo temporal df['t'] = (df['timeStamp'] - df['timeStamp'].min()).dt.total_seconds() # Variáveis X = df[['t']] y = df['elapsed'] # Modelo linear model = LinearRegression().fit(X, y) df['predito'] = model.predict(X) df['erro'] = df['elapsed'] - df['predito'] # Métricas r2 = r2_score(y, df['predito']) mse = mean_squared_error(y, df['predito']) rmse = mse ** 0.5 # Previsão futura (ex: próximos 5 minutos = 300s) future_t = np.linspace(df['t'].max(), df['t'].max() + 300, 100) future_pred = model.predict(pd.DataFrame({'t': future_t})) return { "coeficiente": float(model.coef_[0]), "intercepto": float(model.intercept_), "r2": float(r2), "rmse": float(rmse), "dados": { "t": df['t'].tolist(), "elapsed": df['elapsed'].tolist(), "predito": df['predito'].tolist(), "erro": df['erro'].tolist(), "future_t": future_t.tolist(), "future_pred": future_pred.tolist(), } } # ====================================== # 🚀 Endpoint principal # ====================================== @app.post("/analisar/") async def analisar_csv(file: UploadFile = File(...)): """ Recebe um arquivo CSV do JMeter e retorna métricas e previsões. """ try: # Lê o arquivo CSV enviado contents = await file.read() df = pd.read_csv( pd.io.common.BytesIO(contents), encoding="utf-8" ) # Validação mínima required_cols = {"timeStamp", "elapsed"} if not required_cols.issubset(df.columns): raise HTTPException( status_code=400, detail=f"O CSV precisa conter as colunas: {', '.join(required_cols)}" ) # Processar e treinar o modelo resultado = treinar_modelo(df) return JSONResponse(content=resultado) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) # ====================================== # 🏠 Endpoint básico de teste # ====================================== @app.get("/") async def root(): return { "status": "ok", "message": "API JMeter Performance Analyzer está ativa. Envie um CSV para /analisar/" }