Sync: code local unifié
Synchronisation du code source local (fait foi). Signed-off-by: lions dev Team
This commit is contained in:
@@ -0,0 +1,382 @@
|
||||
package dev.lions.unionflow.server.service;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.system.response.SystemMetricsResponse;
|
||||
import dev.lions.unionflow.server.entity.Membre;
|
||||
import dev.lions.unionflow.server.repository.MembreRepository;
|
||||
import io.agroal.api.AgroalDataSource;
|
||||
import io.quarkus.runtime.StartupEvent;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Service pour récupérer les métriques système réelles
|
||||
*/
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class SystemMetricsService {
|
||||
|
||||
@Inject
|
||||
MembreRepository membreRepository;
|
||||
|
||||
@Inject
|
||||
DataSource dataSource;
|
||||
|
||||
@ConfigProperty(name = "quarkus.application.name")
|
||||
String applicationName;
|
||||
|
||||
@ConfigProperty(name = "quarkus.application.version")
|
||||
String applicationVersion;
|
||||
|
||||
@ConfigProperty(name = "quarkus.oidc.auth-server-url", defaultValue = "http://localhost:8180/realms/unionflow")
|
||||
String authServerUrl;
|
||||
|
||||
// Compteurs pour les métriques
|
||||
private final AtomicLong apiRequestsCount = new AtomicLong(0);
|
||||
private final AtomicLong apiRequestsLastHour = new AtomicLong(0);
|
||||
private final AtomicLong apiRequestsToday = new AtomicLong(0);
|
||||
private long startTimeMillis;
|
||||
private LocalDateTime startTime;
|
||||
|
||||
/**
|
||||
* Initialisation au démarrage
|
||||
*/
|
||||
void onStart(@Observes StartupEvent event) {
|
||||
startTimeMillis = System.currentTimeMillis();
|
||||
startTime = LocalDateTime.now();
|
||||
log.info("SystemMetricsService initialized at {}", startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupérer toutes les métriques système
|
||||
*/
|
||||
public SystemMetricsResponse getSystemMetrics() {
|
||||
log.debug("Collecting system metrics...");
|
||||
|
||||
return SystemMetricsResponse.builder()
|
||||
// Métriques CPU
|
||||
.cpuUsagePercent(getCpuUsage())
|
||||
.availableProcessors(Runtime.getRuntime().availableProcessors())
|
||||
.systemLoadAverage(getSystemLoadAverage())
|
||||
|
||||
// Métriques mémoire
|
||||
.totalMemoryBytes(getTotalMemory())
|
||||
.usedMemoryBytes(getUsedMemory())
|
||||
.freeMemoryBytes(getFreeMemory())
|
||||
.maxMemoryBytes(getMaxMemory())
|
||||
.memoryUsagePercent(getMemoryUsagePercent())
|
||||
.totalMemoryFormatted(SystemMetricsResponse.formatBytes(getTotalMemory()))
|
||||
.usedMemoryFormatted(SystemMetricsResponse.formatBytes(getUsedMemory()))
|
||||
.freeMemoryFormatted(SystemMetricsResponse.formatBytes(getFreeMemory()))
|
||||
|
||||
// Métriques disque
|
||||
.totalDiskBytes(getTotalDiskSpace())
|
||||
.usedDiskBytes(getUsedDiskSpace())
|
||||
.freeDiskBytes(getFreeDiskSpace())
|
||||
.diskUsagePercent(getDiskUsagePercent())
|
||||
.totalDiskFormatted(SystemMetricsResponse.formatBytes(getTotalDiskSpace()))
|
||||
.usedDiskFormatted(SystemMetricsResponse.formatBytes(getUsedDiskSpace()))
|
||||
.freeDiskFormatted(SystemMetricsResponse.formatBytes(getFreeDiskSpace()))
|
||||
|
||||
// Métriques utilisateurs
|
||||
.activeUsersCount(getActiveUsersCount())
|
||||
.totalUsersCount(getTotalUsersCount())
|
||||
.activeSessionsCount(getActiveSessionsCount())
|
||||
.failedLoginAttempts24h(getFailedLoginAttempts())
|
||||
|
||||
// Métriques API
|
||||
.apiRequestsLastHour(apiRequestsLastHour.get())
|
||||
.apiRequestsToday(apiRequestsToday.get())
|
||||
.averageResponseTimeMs(getAverageResponseTime())
|
||||
.totalRequestsCount(apiRequestsCount.get())
|
||||
|
||||
// Métriques base de données
|
||||
.dbConnectionPoolSize(getDbConnectionPoolSize())
|
||||
.dbActiveConnections(getDbActiveConnections())
|
||||
.dbIdleConnections(getDbIdleConnections())
|
||||
.dbHealthy(isDatabaseHealthy())
|
||||
|
||||
// Métriques erreurs et logs (simulées pour l'instant, à implémenter avec vrai système de logs)
|
||||
.criticalErrorsCount(0)
|
||||
.warningsCount(0)
|
||||
.infoLogsCount(0)
|
||||
.debugLogsCount(0)
|
||||
.totalLogsCount(0L)
|
||||
|
||||
// Métriques réseau (simulées, nécessiterait monitoring avancé)
|
||||
.networkBytesReceivedPerSec(0.0)
|
||||
.networkBytesSentPerSec(0.0)
|
||||
.networkInFormatted("0 B/s")
|
||||
.networkOutFormatted("0 B/s")
|
||||
|
||||
// Métriques système
|
||||
.systemStatus(getSystemStatus())
|
||||
.uptimeMillis(getUptimeMillis())
|
||||
.uptimeFormatted(SystemMetricsResponse.formatUptime(getUptimeMillis()))
|
||||
.startTime(startTime)
|
||||
.currentTime(LocalDateTime.now())
|
||||
.javaVersion(System.getProperty("java.version"))
|
||||
.quarkusVersion(getQuarkusVersion())
|
||||
.applicationVersion(applicationVersion)
|
||||
|
||||
// Métriques maintenance (à implémenter avec vrai système de backup)
|
||||
.lastBackup(null)
|
||||
.nextScheduledMaintenance(null)
|
||||
.lastMaintenance(null)
|
||||
|
||||
// URLs
|
||||
.apiBaseUrl(getApiBaseUrl())
|
||||
.authServerUrl(authServerUrl)
|
||||
.cdnUrl(null)
|
||||
|
||||
// Cache (à implémenter)
|
||||
.totalCacheSizeBytes(0L)
|
||||
.totalCacheSizeFormatted("0 B")
|
||||
.totalCacheEntries(0)
|
||||
|
||||
.build();
|
||||
}
|
||||
|
||||
// ==================== MÉTHODES DE CALCUL DES MÉTRIQUES ====================
|
||||
|
||||
/**
|
||||
* CPU Usage (estimation basée sur la charge système)
|
||||
*/
|
||||
private Double getCpuUsage() {
|
||||
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
double loadAvg = osBean.getSystemLoadAverage();
|
||||
int processors = osBean.getAvailableProcessors();
|
||||
|
||||
if (loadAvg < 0) {
|
||||
return 0.0; // Non disponible sur certains OS
|
||||
}
|
||||
|
||||
// Calcul approximatif : (load average / nb processeurs) * 100
|
||||
return Math.min(100.0, (loadAvg / processors) * 100.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* System Load Average
|
||||
*/
|
||||
private Double getSystemLoadAverage() {
|
||||
return ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mémoire totale
|
||||
*/
|
||||
private Long getTotalMemory() {
|
||||
return Runtime.getRuntime().totalMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mémoire utilisée
|
||||
*/
|
||||
private Long getUsedMemory() {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
return runtime.totalMemory() - runtime.freeMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mémoire libre
|
||||
*/
|
||||
private Long getFreeMemory() {
|
||||
return Runtime.getRuntime().freeMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mémoire maximale
|
||||
*/
|
||||
private Long getMaxMemory() {
|
||||
return Runtime.getRuntime().maxMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pourcentage mémoire utilisée
|
||||
*/
|
||||
private Double getMemoryUsagePercent() {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
long used = runtime.totalMemory() - runtime.freeMemory();
|
||||
long max = runtime.maxMemory();
|
||||
return (used * 100.0) / max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Espace disque total
|
||||
*/
|
||||
private Long getTotalDiskSpace() {
|
||||
File root = new File("/");
|
||||
return root.getTotalSpace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Espace disque utilisé
|
||||
*/
|
||||
private Long getUsedDiskSpace() {
|
||||
File root = new File("/");
|
||||
return root.getTotalSpace() - root.getFreeSpace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Espace disque libre
|
||||
*/
|
||||
private Long getFreeDiskSpace() {
|
||||
File root = new File("/");
|
||||
return root.getFreeSpace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pourcentage disque utilisé
|
||||
*/
|
||||
private Double getDiskUsagePercent() {
|
||||
File root = new File("/");
|
||||
long total = root.getTotalSpace();
|
||||
long free = root.getFreeSpace();
|
||||
if (total == 0) return 0.0;
|
||||
return ((total - free) * 100.0) / total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nombre d'utilisateurs actifs (avec sessions actives)
|
||||
*/
|
||||
private Integer getActiveUsersCount() {
|
||||
// TODO: Implémenter avec vrai système de sessions
|
||||
// Pour l'instant, compte les membres actifs
|
||||
try {
|
||||
return (int) membreRepository.count("actif = true");
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting active users count", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nombre total d'utilisateurs
|
||||
*/
|
||||
private Integer getTotalUsersCount() {
|
||||
try {
|
||||
return (int) membreRepository.count();
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting total users count", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nombre de sessions actives
|
||||
*/
|
||||
private Integer getActiveSessionsCount() {
|
||||
// TODO: Implémenter avec vrai système de sessions Keycloak
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tentatives de login échouées (24h)
|
||||
*/
|
||||
private Integer getFailedLoginAttempts() {
|
||||
// TODO: Implémenter avec vrai système d'audit
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temps de réponse moyen API
|
||||
*/
|
||||
private Double getAverageResponseTime() {
|
||||
// TODO: Implémenter avec vrai système de métriques
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Taille du pool de connexions DB
|
||||
*/
|
||||
private Integer getDbConnectionPoolSize() {
|
||||
if (dataSource instanceof AgroalDataSource agroalDataSource) {
|
||||
return agroalDataSource.getConfiguration().connectionPoolConfiguration().maxSize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connexions DB actives
|
||||
*/
|
||||
private Integer getDbActiveConnections() {
|
||||
if (dataSource instanceof AgroalDataSource agroalDataSource) {
|
||||
return (int) agroalDataSource.getMetrics().activeCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connexions DB en attente
|
||||
*/
|
||||
private Integer getDbIdleConnections() {
|
||||
if (dataSource instanceof AgroalDataSource agroalDataSource) {
|
||||
return (int) agroalDataSource.getMetrics().availableCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* État santé base de données
|
||||
*/
|
||||
private Boolean isDatabaseHealthy() {
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
return conn.isValid(5); // 5 secondes timeout
|
||||
} catch (SQLException e) {
|
||||
log.error("Database health check failed", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Statut système
|
||||
*/
|
||||
private String getSystemStatus() {
|
||||
// TODO: Implémenter logique plus sophistiquée
|
||||
return "OPERATIONAL";
|
||||
}
|
||||
|
||||
/**
|
||||
* Uptime en millisecondes
|
||||
*/
|
||||
private Long getUptimeMillis() {
|
||||
return System.currentTimeMillis() - startTimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Version Quarkus
|
||||
*/
|
||||
private String getQuarkusVersion() {
|
||||
return io.quarkus.runtime.annotations.QuarkusMain.class.getPackage().getImplementationVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* URL base API
|
||||
*/
|
||||
private String getApiBaseUrl() {
|
||||
// TODO: Récupérer depuis configuration
|
||||
return "http://localhost:8085";
|
||||
}
|
||||
|
||||
/**
|
||||
* Incrémenter le compteur de requêtes API
|
||||
*/
|
||||
public void incrementApiRequestCount() {
|
||||
apiRequestsCount.incrementAndGet();
|
||||
apiRequestsLastHour.incrementAndGet();
|
||||
apiRequestsToday.incrementAndGet();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user