All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.swisspush.redisques.util.DefaultMemoryUsageProvider Maven / Gradle / Ivy

There is a newer version: 4.1.10
Show newest version
package org.swisspush.redisques.util;

import io.vertx.core.Vertx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.Optional;

public class DefaultMemoryUsageProvider implements MemoryUsageProvider {

    private final Logger log = LoggerFactory.getLogger(DefaultMemoryUsageProvider.class);

    private final RedisProvider redisProvider;

    private Optional currentMemoryUsagePercentageOpt = Optional.empty();

    private static final int MAX_PERCENTAGE = 100;
    private static final int MIN_PERCENTAGE = 0;

    public DefaultMemoryUsageProvider(RedisProvider redisProvider, Vertx vertx, int memoryUsageCheckIntervalSec) {
        this.redisProvider = redisProvider;
        updateCurrentMemoryUsage();
        vertx.setPeriodic(memoryUsageCheckIntervalSec * 1000L, event -> updateCurrentMemoryUsage());
    }

    public Optional currentMemoryUsagePercentage() {
        return currentMemoryUsagePercentageOpt;
    }

    private void updateCurrentMemoryUsage() {
        redisProvider.redis()
                .onFailure( ex -> log.warn("TODO error handling", ex))
                .onSuccess(redisAPI -> redisAPI.info(Collections.singletonList("memory"))
                .onComplete(memoryInfoEvent -> {
                    if (memoryInfoEvent.failed()) {
                        log.error("Unable to get memory information from redis", memoryInfoEvent.cause());
                        currentMemoryUsagePercentageOpt = Optional.empty();
                        return;
                    }

                    String memoryInfo = memoryInfoEvent.result().toString();

                    Optional totalSystemMemory = totalSystemMemory(memoryInfo);
                    if (totalSystemMemory.isEmpty()) {
                        currentMemoryUsagePercentageOpt = Optional.empty();
                        return;
                    }

                    Optional usedMemory = usedMemory(memoryInfo);
                    if (usedMemory.isEmpty()) {
                        currentMemoryUsagePercentageOpt = Optional.empty();
                        return;
                    }

                    float currentMemoryUsagePercentage = ((float) usedMemory.get() / totalSystemMemory.get()) * 100;
                    if (currentMemoryUsagePercentage > MAX_PERCENTAGE) {
                        currentMemoryUsagePercentage = MAX_PERCENTAGE;
                    } else if (currentMemoryUsagePercentage < MIN_PERCENTAGE) {
                        currentMemoryUsagePercentage = MIN_PERCENTAGE;
                    }

                    int roundedValue = Math.round(currentMemoryUsagePercentage);
                    log.info("Current memory usage is {}%", roundedValue);
                    currentMemoryUsagePercentageOpt = Optional.of(roundedValue);
                })).onFailure(throwable -> {
                    log.error("Redis: Unable to get memory information from redis", throwable);
                    currentMemoryUsagePercentageOpt = Optional.empty();
                });
    }

    private Optional totalSystemMemory(String memoryInfo) {
        long totalSystemMemory;
        try {
            Optional totalSystemMemoryOpt = memoryInfo
                    .lines()
                    .filter(source -> source.startsWith("total_system_memory:"))
                    .findAny();
            if (totalSystemMemoryOpt.isEmpty()) {
                log.warn("No 'total_system_memory' section received from redis. Unable to calculate the current memory usage");
                return Optional.empty();
            }
            totalSystemMemory = Long.parseLong(totalSystemMemoryOpt.get().split(":")[1]);
            if (totalSystemMemory == 0L) {
                log.warn("'total_system_memory' value 0 received from redis. Unable to calculate the current memory usage");
                return Optional.empty();
            }

        } catch (NumberFormatException ex) {
            logPropertyWarning("total_system_memory", ex);
            return Optional.empty();
        }

        return Optional.of(totalSystemMemory);
    }

    private Optional usedMemory(String memoryInfo) {
        try {
            Optional usedMemoryOpt = memoryInfo
                    .lines()
                    .filter(source -> source.startsWith("used_memory:"))
                    .findAny();
            if (usedMemoryOpt.isEmpty()) {
                log.warn("No 'used_memory' section received from redis. Unable to calculate the current memory usage");
                return Optional.empty();
            }
            return Optional.of(Long.parseLong(usedMemoryOpt.get().split(":")[1]));
        } catch (NumberFormatException ex) {
            logPropertyWarning("used_memory", ex);
            return Optional.empty();
        }
    }

    private void logPropertyWarning(String property, Exception ex) {
        log.warn("No or invalid '{}' value received from redis. Unable to calculate the current memory usage.", property, ex);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy