Fix: Translate all validation messages and UI text from Portuguese to English

This commit is contained in:
2025-09-25 20:08:13 -03:00
parent 2d0c086df2
commit 89a7ee41de
10 changed files with 248 additions and 154 deletions

View File

@@ -54,15 +54,15 @@ class HistoricalAnalysisService:
validations.extend(memory_analysis)
except Exception as e:
logger.error(f"Erro na análise histórica do pod {pod.name}: {e}")
logger.error(f"Error in historical analysis for pod {pod.name}: {e}")
validations.append(ResourceValidation(
pod_name=pod.name,
namespace=pod.namespace,
container_name="all",
validation_type="historical_analysis_error",
severity="warning",
message=f"Erro na análise histórica: {str(e)}",
recommendation="Verificar conectividade com Prometheus"
message=f"Error in historical analysis: {str(e)}",
recommendation="Check Prometheus connectivity"
))
return validations
@@ -123,7 +123,7 @@ class HistoricalAnalysisService:
validations.extend(analysis)
except Exception as e:
logger.warning(f"Erro ao analisar CPU do container {container_name}: {e}")
logger.warning(f"Error analyzing CPU for container {container_name}: {e}")
return validations
@@ -183,7 +183,7 @@ class HistoricalAnalysisService:
validations.extend(analysis)
except Exception as e:
logger.warning(f"Erro ao analisar memória do container {container_name}: {e}")
logger.warning(f"Error analyzing memory for container {container_name}: {e}")
return validations
@@ -218,9 +218,9 @@ class HistoricalAnalysisService:
p95_usage = sorted(usage_values)[int(len(usage_values) * 0.95)]
p99_usage = sorted(usage_values)[int(len(usage_values) * 0.99)]
# Análise de adequação dos requests
# Request adequacy analysis
if current_requests > 0:
# Request muito alto (uso médio < 50% do request)
# Request too high (average usage < 50% of request)
if avg_usage < current_requests * 0.5:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -228,11 +228,11 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="warning",
message=f"CPU request muito alto: uso médio {avg_usage:.3f} cores vs request {current_requests:.3f} cores",
recommendation=f"Considerar reduzir CPU request para ~{avg_usage * 1.2:.3f} cores (baseado em {time_range} de uso)"
message=f"CPU request too high: average usage {avg_usage:.3f} cores vs request {current_requests:.3f} cores",
recommendation=f"Consider reducing CPU request to ~{avg_usage * 1.2:.3f} cores (based on {time_range} of usage)"
))
# Request muito baixo (uso P95 > 80% do request)
# Request too low (P95 usage > 80% of request)
elif p95_usage > current_requests * 0.8:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -240,13 +240,13 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="warning",
message=f"CPU request pode ser insuficiente: P95 {p95_usage:.3f} cores vs request {current_requests:.3f} cores",
recommendation=f"Considerar aumentar CPU request para ~{p95_usage * 1.2:.3f} cores (baseado em {time_range} de uso)"
message=f"CPU request may be insufficient: P95 {p95_usage:.3f} cores vs request {current_requests:.3f} cores",
recommendation=f"Consider increasing CPU request to ~{p95_usage * 1.2:.3f} cores (based on {time_range} of usage)"
))
# Análise de adequação dos limits
# Limit adequacy analysis
if current_limits > 0:
# Limit muito alto (uso P99 < 50% do limit)
# Limit too high (P99 usage < 50% of limit)
if p99_usage < current_limits * 0.5:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -254,11 +254,11 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="info",
message=f"CPU limit muito alto: P99 {p99_usage:.3f} cores vs limit {current_limits:.3f} cores",
recommendation=f"Considerar reduzir CPU limit para ~{p99_usage * 1.5:.3f} cores (baseado em {time_range} de uso)"
message=f"CPU limit too high: P99 {p99_usage:.3f} cores vs limit {current_limits:.3f} cores",
recommendation=f"Consider reducing CPU limit to ~{p99_usage * 1.5:.3f} cores (based on {time_range} of usage)"
))
# Limit muito baixo (uso máximo > 90% do limit)
# Limit too low (maximum usage > 90% of limit)
elif max_usage > current_limits * 0.9:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -266,8 +266,8 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="warning",
message=f"CPU limit pode ser insuficiente: uso máximo {max_usage:.3f} cores vs limit {current_limits:.3f} cores",
recommendation=f"Considerar aumentar CPU limit para ~{max_usage * 1.2:.3f} cores (baseado em {time_range} de uso)"
message=f"CPU limit may be insufficient: maximum usage {max_usage:.3f} cores vs limit {current_limits:.3f} cores",
recommendation=f"Consider increasing CPU limit to ~{max_usage * 1.2:.3f} cores (based on {time_range} of usage)"
))
return validations
@@ -307,9 +307,9 @@ class HistoricalAnalysisService:
def bytes_to_mib(bytes_value):
return bytes_value / (1024 * 1024)
# Análise de adequação dos requests
# Request adequacy analysis
if current_requests > 0:
# Request muito alto (uso médio < 50% do request)
# Request too high (average usage < 50% of request)
if avg_usage < current_requests * 0.5:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -317,11 +317,11 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="warning",
message=f"Memória request muito alto: uso médio {bytes_to_mib(avg_usage):.1f}Mi vs request {bytes_to_mib(current_requests):.1f}Mi",
recommendation=f"Considerar reduzir memória request para ~{bytes_to_mib(avg_usage * 1.2):.1f}Mi (baseado em {time_range} de uso)"
message=f"Memory request too high: average usage {bytes_to_mib(avg_usage):.1f}Mi vs request {bytes_to_mib(current_requests):.1f}Mi",
recommendation=f"Consider reducing memory request to ~{bytes_to_mib(avg_usage * 1.2):.1f}Mi (based on {time_range} of usage)"
))
# Request muito baixo (uso P95 > 80% do request)
# Request too low (P95 usage > 80% of request)
elif p95_usage > current_requests * 0.8:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -329,13 +329,13 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="warning",
message=f"Memória request pode ser insuficiente: P95 {bytes_to_mib(p95_usage):.1f}Mi vs request {bytes_to_mib(current_requests):.1f}Mi",
recommendation=f"Considerar aumentar memória request para ~{bytes_to_mib(p95_usage * 1.2):.1f}Mi (baseado em {time_range} de uso)"
message=f"Memory request may be insufficient: P95 {bytes_to_mib(p95_usage):.1f}Mi vs request {bytes_to_mib(current_requests):.1f}Mi",
recommendation=f"Consider increasing memory request to ~{bytes_to_mib(p95_usage * 1.2):.1f}Mi (based on {time_range} of usage)"
))
# Análise de adequação dos limits
# Limit adequacy analysis
if current_limits > 0:
# Limit muito alto (uso P99 < 50% do limit)
# Limit too high (P99 usage < 50% of limit)
if p99_usage < current_limits * 0.5:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -343,11 +343,11 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="info",
message=f"Memória limit muito alto: P99 {bytes_to_mib(p99_usage):.1f}Mi vs limit {bytes_to_mib(current_limits):.1f}Mi",
recommendation=f"Considerar reduzir memória limit para ~{bytes_to_mib(p99_usage * 1.5):.1f}Mi (baseado em {time_range} de uso)"
message=f"Memory limit too high: P99 {bytes_to_mib(p99_usage):.1f}Mi vs limit {bytes_to_mib(current_limits):.1f}Mi",
recommendation=f"Consider reducing memory limit to ~{bytes_to_mib(p99_usage * 1.5):.1f}Mi (based on {time_range} of usage)"
))
# Limit muito baixo (uso máximo > 90% do limit)
# Limit too low (maximum usage > 90% of limit)
elif max_usage > current_limits * 0.9:
validations.append(ResourceValidation(
pod_name=pod_name,
@@ -355,8 +355,8 @@ class HistoricalAnalysisService:
container_name=container_name,
validation_type="historical_analysis",
severity="warning",
message=f"Memória limit pode ser insuficiente: uso máximo {bytes_to_mib(max_usage):.1f}Mi vs limit {bytes_to_mib(current_limits):.1f}Mi",
recommendation=f"Considerar aumentar memória limit para ~{bytes_to_mib(max_usage * 1.2):.1f}Mi (baseado em {time_range} de uso)"
message=f"Memory limit may be insufficient: maximum usage {bytes_to_mib(max_usage):.1f}Mi vs limit {bytes_to_mib(current_limits):.1f}Mi",
recommendation=f"Consider increasing memory limit to ~{bytes_to_mib(max_usage * 1.2):.1f}Mi (based on {time_range} of usage)"
))
return validations
@@ -385,7 +385,7 @@ class HistoricalAnalysisService:
logger.warning(f"Prometheus query failed: {response.status}")
return []
except Exception as e:
logger.error(f"Erro ao consultar Prometheus: {e}")
logger.error(f"Error querying Prometheus: {e}")
return []
async def get_cluster_historical_summary(self, time_range: str = '24h') -> Dict[str, Any]:
@@ -441,5 +441,5 @@ class HistoricalAnalysisService:
}
except Exception as e:
logger.error(f"Erro ao obter resumo histórico: {e}")
logger.error(f"Error getting historical summary: {e}")
return {}

View File

@@ -1,5 +1,5 @@
"""
Serviço de geração de relatórios
Report generation service
"""
import logging
import json
@@ -18,7 +18,7 @@ from app.core.config import settings
logger = logging.getLogger(__name__)
class ReportService:
"""Serviço para geração de relatórios"""
"""Service for report generation"""
def __init__(self):
self.export_path = settings.report_export_path
@@ -32,12 +32,12 @@ class ReportService:
overcommit_info: Dict[str, Any],
nodes_info: List[Dict[str, Any]]
) -> ClusterReport:
"""Gerar relatório do cluster"""
"""Generate cluster report"""
# Contar namespaces únicos
# Count unique namespaces
namespaces = set(pod.namespace for pod in pods)
# Gerar resumo
# Generate summary
summary = self._generate_summary(validations, vpa_recommendations, overcommit_info)
report = ClusterReport(
@@ -60,14 +60,14 @@ class ReportService:
validations: List[ResourceValidation],
resource_usage: Dict[str, Any]
) -> NamespaceReport:
"""Gerar relatório de um namespace"""
"""Generate namespace report"""
# Filtrar validações do namespace
# Filter validations for the namespace
namespace_validations = [
v for v in validations if v.namespace == namespace
]
# Gerar recomendações
# Generate recommendations
recommendations = self._generate_namespace_recommendations(namespace_validations)
report = NamespaceReport(
@@ -87,9 +87,9 @@ class ReportService:
vpa_recommendations: List[VPARecommendation],
overcommit_info: Dict[str, Any]
) -> Dict[str, Any]:
"""Gerar resumo do relatório"""
"""Generate report summary"""
# Contar validações por severidade
# Count validations by severity
severity_counts = {}
for validation in validations:
severity = validation.severity
@@ -97,7 +97,7 @@ class ReportService:
severity_counts[severity] = 0
severity_counts[severity] += 1
# Contar validações por tipo
# Count validations by type
type_counts = {}
for validation in validations:
validation_type = validation.validation_type
@@ -120,10 +120,10 @@ class ReportService:
self,
validations: List[ResourceValidation]
) -> List[str]:
"""Gerar recomendações para um namespace"""
"""Generate recommendations for a namespace"""
recommendations = []
# Agrupar por tipo de problema
# Group by problem type
problems = {}
for validation in validations:
problem_type = validation.validation_type
@@ -131,18 +131,18 @@ class ReportService:
problems[problem_type] = []
problems[problem_type].append(validation)
# Gerar recomendações específicas
# Generate recommendations específicas
if "missing_requests" in problems:
count = len(problems["missing_requests"])
recommendations.append(
f"Criar LimitRange para definir requests padrão "
f"({count} containers sem requests)"
f"Create LimitRange to define default requests "
f"({count} containers without requests)"
)
if "missing_limits" in problems:
count = len(problems["missing_limits"])
recommendations.append(
f"Definir limits para {count} containers para evitar consumo excessivo"
f"Define limits for {count} containers to avoid excessive consumption"
)
if "invalid_ratio" in problems:
@@ -163,7 +163,7 @@ class ReportService:
report: ClusterReport,
export_request: ExportRequest
) -> str:
"""Exportar relatório em diferentes formatos"""
"""Export report in different formats"""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
@@ -174,10 +174,10 @@ class ReportService:
elif export_request.format == "pdf":
return await self._export_pdf(report, timestamp)
else:
raise ValueError(f"Formato não suportado: {export_request.format}")
raise ValueError(f"Unsupported format: {export_request.format}")
async def _export_json(self, report: ClusterReport, timestamp: str) -> str:
"""Exportar relatório em JSON"""
"""Export report in JSON"""
filename = f"cluster_report_{timestamp}.json"
filepath = os.path.join(self.export_path, filename)
@@ -187,11 +187,11 @@ class ReportService:
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(report_dict, f, indent=2, ensure_ascii=False)
logger.info(f"Relatório JSON exportado: {filepath}")
logger.info(f"JSON report exported: {filepath}")
return filepath
async def _export_csv(self, report: ClusterReport, timestamp: str) -> str:
"""Exportar relatório em CSV"""
"""Export report in CSV"""
filename = f"cluster_report_{timestamp}.csv"
filepath = os.path.join(self.export_path, filename)
@@ -204,7 +204,7 @@ class ReportService:
"Validation Type", "Severity", "Message", "Recommendation"
])
# Dados das validações
# Validation data
for validation in report.validations:
writer.writerow([
validation.pod_name,
@@ -216,11 +216,11 @@ class ReportService:
validation.recommendation or ""
])
logger.info(f"Relatório CSV exportado: {filepath}")
logger.info(f"CSV report exported: {filepath}")
return filepath
async def _export_pdf(self, report: ClusterReport, timestamp: str) -> str:
"""Exportar relatório em PDF"""
"""Export report in PDF"""
try:
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
@@ -241,20 +241,20 @@ class ReportService:
# Resumo
summary_text = f"""
<b>Resumo do Cluster:</b><br/>
Total de Pods: {report.total_pods}<br/>
Total de Namespaces: {report.total_namespaces}<br/>
Total des: {report.total_nodes}<br/>
Total de Validações: {report.summary['total_validations']}<br/>
Problemas Críticos: {report.summary['critical_issues']}<br/>
<b>Cluster Summary:</b><br/>
Total Pods: {report.total_pods}<br/>
Total Namespaces: {report.total_namespaces}<br/>
Total Nodes: {report.total_nodes}<br/>
Total Validations: {report.summary['total_validations']}<br/>
Critical Issues: {report.summary['critical_issues']}<br/>
"""
story.append(Paragraph(summary_text, styles['Normal']))
story.append(Spacer(1, 12))
# Tabela de validações
# Validations table
if report.validations:
data = [["Pod", "Namespace", "Container", "Tipo", "Severidade", "Mensagem"]]
for validation in report.validations[:50]: # Limitar a 50 para PDF
data = [["Pod", "Namespace", "Container", "Type", "Severity", "Message"]]
for validation in report.validations[:50]: # Limit to 50 for PDF
data.append([
validation.pod_name,
validation.namespace,
@@ -280,15 +280,15 @@ class ReportService:
story.append(table)
doc.build(story)
logger.info(f"Relatório PDF exportado: {filepath}")
logger.info(f"PDF report exported: {filepath}")
return filepath
except ImportError:
logger.error("reportlab não instalado. Instale com: pip install reportlab")
raise ValueError("PDF export requer reportlab")
logger.error("reportlab not installed. Install with: pip install reportlab")
raise ValueError("PDF export requires reportlab")
def get_exported_reports(self) -> List[Dict[str, str]]:
"""Listar relatórios exportados"""
"""List exported reports"""
reports = []
for filename in os.listdir(self.export_path):

View File

@@ -50,7 +50,7 @@ class ValidationService:
)
static_validations.extend(historical_validations)
except Exception as e:
logger.warning(f"Erro na análise histórica do pod {pod.name}: {e}")
logger.warning(f"Error in historical analysis for pod {pod.name}: {e}")
return static_validations
@@ -74,8 +74,8 @@ class ValidationService:
container_name=container["name"],
validation_type="missing_requests",
severity="error",
message="Container sem requests definidos",
recommendation="Definir requests de CPU e memória para garantir QoS"
message="Container without defined requests",
recommendation="Define CPU and memory requests to guarantee QoS"
))
# 2. Verificar se limits estão definidos
@@ -86,8 +86,8 @@ class ValidationService:
container_name=container["name"],
validation_type="missing_limits",
severity="warning",
message="Container sem limits definidos",
recommendation="Definir limits para evitar consumo excessivo de recursos"
message="Container without defined limits",
recommendation="Define limits to avoid excessive resource consumption"
))
# 3. Validar ratio limit:request
@@ -139,8 +139,8 @@ class ValidationService:
container_name=container_name,
validation_type="invalid_ratio",
severity="warning",
message=f"Ratio CPU limit:request muito alto ({ratio:.2f}:1)",
recommendation=f"Considerar reduzir limits ou aumentar requests (ratio recomendado: {self.cpu_ratio}:1)"
message=f"CPU limit:request ratio too high ({ratio:.2f}:1)",
recommendation=f"Consider reducing limits or increasing requests (recommended ratio: {self.cpu_ratio}:1)"
)
elif ratio < 1.0:
return ResourceValidation(
@@ -149,12 +149,12 @@ class ValidationService:
container_name=container_name,
validation_type="invalid_ratio",
severity="error",
message=f"CPU limit menor que request ({ratio:.2f}:1)",
recommendation="CPU limit deve ser maior ou igual ao request"
message=f"CPU limit less than request ({ratio:.2f}:1)",
recommendation="CPU limit should be greater than or equal to request"
)
except (ValueError, InvalidOperation) as e:
logger.warning(f"Erro ao validar ratio CPU: {e}")
logger.warning(f"Error validating CPU ratio: {e}")
return None
@@ -184,8 +184,8 @@ class ValidationService:
container_name=container_name,
validation_type="invalid_ratio",
severity="warning",
message=f"Ratio memória limit:request muito alto ({ratio:.2f}:1)",
recommendation=f"Considerar reduzir limits ou aumentar requests (ratio recomendado: {self.memory_ratio}:1)"
message=f"Memory limit:request ratio too high ({ratio:.2f}:1)",
recommendation=f"Consider reducing limits or increasing requests (recommended ratio: {self.memory_ratio}:1)"
)
elif ratio < 1.0:
return ResourceValidation(
@@ -194,12 +194,12 @@ class ValidationService:
container_name=container_name,
validation_type="invalid_ratio",
severity="error",
message=f"Memória limit menor que request ({ratio:.2f}:1)",
recommendation="Memória limit deve ser maior ou igual ao request"
message=f"Memory limit less than request ({ratio:.2f}:1)",
recommendation="Memory limit should be greater than or equal to request"
)
except (ValueError, InvalidOperation) as e:
logger.warning(f"Erro ao validar ratio memória: {e}")
logger.warning(f"Error validating memory ratio: {e}")
return None
@@ -226,8 +226,8 @@ class ValidationService:
container_name=container_name,
validation_type="minimum_value",
severity="warning",
message=f"CPU request muito baixo ({requests['cpu']})",
recommendation=f"Considerar aumentar para pelo menos {self.min_cpu_request}"
message=f"CPU request too low ({requests['cpu']})",
recommendation=f"Consider increasing to at least {self.min_cpu_request}"
))
except (ValueError, InvalidOperation):
pass
@@ -245,8 +245,8 @@ class ValidationService:
container_name=container_name,
validation_type="minimum_value",
severity="warning",
message=f"Memória request muito baixa ({requests['memory']})",
recommendation=f"Considerar aumentar para pelo menos {self.min_memory_request}"
message=f"Memory request too low ({requests['memory']})",
recommendation=f"Consider increasing to at least {self.min_memory_request}"
))
except (ValueError, InvalidOperation):
pass
@@ -307,8 +307,8 @@ class ValidationService:
container_name="all",
validation_type="overcommit",
severity="critical",
message=f"Overcommit de CPU no namespace: {cpu_utilization:.1f}%",
recommendation="Reduzir requests de CPU ou adicionar mais nós ao cluster"
message=f"CPU overcommit in namespace: {cpu_utilization:.1f}%",
recommendation="Reduce CPU requests or add more nodes to the cluster"
))
# Verificar overcommit de memória
@@ -321,8 +321,8 @@ class ValidationService:
container_name="all",
validation_type="overcommit",
severity="critical",
message=f"Overcommit de memória no namespace: {memory_utilization:.1f}%",
recommendation="Reduzir requests de memória ou adicionar mais nós ao cluster"
message=f"Memory overcommit in namespace: {memory_utilization:.1f}%",
recommendation="Reduce memory requests or add more nodes to the cluster"
))
return validations
@@ -342,26 +342,26 @@ class ValidationService:
# Gerar recomendações baseadas nos problemas encontrados
if validation_counts.get("missing_requests", 0) > 0:
recommendations.append(
f"Implementar LimitRange no namespace para definir requests padrão "
f"({validation_counts['missing_requests']} containers sem requests)"
f"Implement LimitRange in namespace to define default requests "
f"({validation_counts['missing_requests']} containers without requests)"
)
if validation_counts.get("missing_limits", 0) > 0:
recommendations.append(
f"Definir limits para {validation_counts['missing_limits']} containers "
"para evitar consumo excessivo de recursos"
f"Define limits for {validation_counts['missing_limits']} containers "
"to avoid excessive resource consumption"
)
if validation_counts.get("invalid_ratio", 0) > 0:
recommendations.append(
f"Ajustar ratio limit:request para {validation_counts['invalid_ratio']} containers "
f"(recomendado: {self.cpu_ratio}:1)"
f"Adjust limit:request ratio for {validation_counts['invalid_ratio']} containers "
f"(recommended: {self.cpu_ratio}:1)"
)
if validation_counts.get("overcommit", 0) > 0:
recommendations.append(
f"Resolver overcommit em {validation_counts['overcommit']} namespaces "
"para evitar problemas de performance"
f"Resolve overcommit in {validation_counts['overcommit']} namespaces "
"to avoid performance issues"
)
return recommendations