Код: Выделить всё
@SuppressWarnings("unused")
@Configuration
@EnableScheduling
public class SchedulingConfig {
@Bean(name = "schedulerHikari")
public ThreadPoolTaskScheduler schedulerHikari() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.setThreadNamePrefix("scheduler-hikari-hc-");
return scheduler;
}
@Bean(name = "schedulerJVM")
public ThreadPoolTaskScheduler schedulerJVM() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.setThreadNamePrefix("scheduler-jvm-hc-");
return scheduler;
}
}
Код: Выделить всё
@Component
@AllArgsConstructor
@Slf4j
@SuppressWarnings("unused")
public class HikariCPCheck implements ApplicationListener, SchedulingConfigurer {
private final HikariDataSource dataSource;
@Qualifier("schedulerHikari")
private final ThreadPoolTaskScheduler schedulerHikari;
@Value("${healthcheck.datasource.hikari.max-awaiting}")
private final int maxAwaitingConnections;
@Value("${healthcheck.datasource.hikari.scheduler-hikari-delay}")
private final int initialDelay;
@Value("${healthcheck.datasource.hikari.scheduler-hikari-rate}")
private final int fixedRate;
@Override
public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
try (Connection connection = dataSource.getConnection()) {
log.info("Successfully obtained connection from HikariCP");
} catch (SQLException e) {
if (e.getMessage().contains("Timeout")) {
log.error("HikariCP pool initialization failed: Connection timeout", e);
} else {
log.error("Failed to obtain connection from HikariCP", e);
}
}
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(schedulerHikari);
PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMinutes(fixedRate));
trigger.setInitialDelay(Duration.ofMinutes(initialDelay));
taskRegistrar.addTriggerTask(
this::logConnectionPoolStatus,
trigger
);
}
private void logConnectionPoolStatus() {
HikariPoolMXBean hikariPoolMXBean = dataSource.getHikariPoolMXBean();
HikariConfigMXBean hikariConfigMXBean = dataSource.getHikariConfigMXBean();
log.info("HikariCP Pool Name: {}", dataSource.getPoolName());
log.info("HikariCP Total Connections: {}", hikariPoolMXBean.getTotalConnections());
if (hikariPoolMXBean.getActiveConnections() >= hikariConfigMXBean.getMaximumPoolSize()) {
log.warn("HikariCP Active Connections reached max pool size {active connections: {}, max pool size: {}}.", hikariPoolMXBean.getActiveConnections(), hikariConfigMXBean.getMaximumPoolSize());
} else {
log.info("HikariCP Active Connections: {active connections: {}, max pool size: {}}.", hikariPoolMXBean.getActiveConnections(), hikariConfigMXBean.getMaximumPoolSize());
}
log.info("HikariCP Idle Connections: {}.", hikariPoolMXBean.getIdleConnections());
if (hikariPoolMXBean.getThreadsAwaitingConnection() > maxAwaitingConnections) {
log.error("HikariCP Threads Awaiting Connection greater then limit {awaiting threads: {}, max: {}}.", hikariPoolMXBean.getThreadsAwaitingConnection(), maxAwaitingConnections);
} else {
log.info("HikariCP Threads Awaiting Connection: {awaiting threads: {}, max: {}}.", hikariPoolMXBean.getThreadsAwaitingConnection(), maxAwaitingConnections);
}
}
}
Код: Выделить всё
@Component
@AllArgsConstructor
@Slf4j
@SuppressWarnings("unused")
public class JVMHealthCheck implements SchedulingConfigurer{
private final OperatingSystemMXBean osMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
private final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
@Qualifier("schedulerJVM")
private final ThreadPoolTaskScheduler schedulerJVM;
@Value("${healthcheck.jvm.processor.threshold}")
private final int processorThreshold;
@Value("${healthcheck.jvm.heap-memory.threshold}")
private final int heapMemoryThreshold;
@Value("${healthcheck.jvm.non-heap-memory.threshold}")
private final int nonHeapMemoryThreshold;
@Value("${healthcheck.jvm.scheduler-jvm-delay}")
private final int initialDelay;
@Value("${healthcheck.jvm.scheduler-jvm-rate}")
private final int fixedRate;
@PostConstruct
public void logConnectionConfigStatus() {
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
log.info("JVM Available Processors: {}", osMXBean.getAvailableProcessors());
log.info("JVM Init Heap Memory Usage: {}", memoryMXBean.getHeapMemoryUsage().getInit() / (1024 * 1024));
log.info("JVM Max Heap Memory Usage: {}", memoryMXBean.getHeapMemoryUsage().getMax() / (1024 * 1024));
log.info("JVM Init Non Heap Memory Usage: {}", memoryMXBean.getNonHeapMemoryUsage().getInit() / (1024 * 1024));
log.info("JVM Committed Non Heap Memory Usage: {}", memoryMXBean.getNonHeapMemoryUsage().getCommitted() / (1024 * 1024));
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(schedulerJVM);
PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMinutes(fixedRate));
trigger.setInitialDelay(Duration.ofMinutes(initialDelay));
taskRegistrar.addTriggerTask(
this::logJVMUsageStatus,
trigger
);
}
private void logJVMUsageStatus() {
log.error("wtf");
if (osMXBean.getProcessCpuLoad()*100 > processorThreshold) {
log.warn("JVM Process CPU usage reached threshold {usage: {}, threshold: {}}.", osMXBean.getProcessCpuLoad()*100, processorThreshold);
}
if (osMXBean.getProcessCpuLoad()*100 >= 99) {
log.error("JVM Process CPU usage reached max {usage: {}, max: 100}.", osMXBean.getProcessCpuLoad()*100);
}
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
double usedHeapMemory = (double) heapMemoryUsage.getUsed() / heapMemoryUsage.getMax();
double roundedHeapMemoryPercentage = Math.round(usedHeapMemory * 100 * 100.0) / 100.0;
if (roundedHeapMemoryPercentage > heapMemoryThreshold) {
log.warn("JVM Heap Memory usage reached threshold {usage: {}, threshold: {}}.", memoryMXBean.getHeapMemoryUsage().getUsed() / memoryMXBean.getHeapMemoryUsage().getMax(), heapMemoryThreshold);
}
if (roundedHeapMemoryPercentage >= 99) {
log.warn("JVM Heap Memory usage reached max {usage: {}, max: {}}.", roundedHeapMemoryPercentage, heapMemoryUsage.getMax());
}
MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
double usedNonHeapMemory = (double) nonHeapMemoryUsage.getUsed() / nonHeapMemoryUsage.getMax();
double roundedNonHeapMemoryPercentage = Math.round(usedNonHeapMemory * 100 * 100.0) / 100.0;
if (roundedNonHeapMemoryPercentage > nonHeapMemoryThreshold) {
log.warn("JVM Non Heap Memory usage reached threshold {usage: {}, threshold: {}}.", roundedNonHeapMemoryPercentage, nonHeapMemoryThreshold);
}
if (roundedNonHeapMemoryPercentage >= 99) {
log.warn("JVM Non Heap Memory usage reached max {usage: {}, max: {}}.", roundedNonHeapMemoryPercentage, nonHeapMemoryUsage.getMax());
}
}
}
Код: Выделить всё
lombok.copyableAnnotations+=org.springframework.beans.factory.annotation.Qualifier
Код: Выделить всё
spring.main.allow-bean-definition-overriding=false
Код: Выделить всё
2024-10-17 20:43:28,682 INFO [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Pool Name: name
2024-10-17 20:43:28,682 INFO [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Total Connections: 10
2024-10-17 20:43:28,682 INFO [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Active Connections: {active connections: 1, max pool size: 10}.
2024-10-17 20:43:28,683 INFO [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Idle Connections: 9.
2024-10-17 20:43:28,683 INFO [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Threads Awaiting Connection: {awaiting threads: 0, max: 3}.
2024-10-17 20:43:28,684 ERROR [scheduler-jvm-hc-1] b.c.h.JVMHealthCheck: wtf
Подробнее здесь: https://stackoverflow.com/questions/790 ... working-on