Spaces:
Sleeping
Sleeping
| 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 | |
| # ====================================== | |
| 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 | |
| # ====================================== | |
| async def root(): | |
| return { | |
| "status": "ok", | |
| "message": "API JMeter Performance Analyzer está ativa. Envie um CSV para /analisar/" | |
| } | |