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

com.github.endoscope.storage.StatsPersistence Maven / Gradle / Ivy

The newest version!
    package com.github.endoscope.storage;

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import com.github.endoscope.core.Stats;
import com.github.endoscope.properties.Properties;
import com.github.endoscope.util.DateUtil;
import org.slf4j.Logger;

import static org.apache.commons.lang3.ObjectUtils.firstNonNull;
import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCause;
import static org.slf4j.LoggerFactory.getLogger;

public class StatsPersistence {
    private static final Logger log = getLogger(StatsPersistence.class);

    private String appType;
    private String appInstance;
    private int saveFreqMinutes;
    private Storage storage = null;
    private DateUtil dateUtil;
    private AtomicLong lastSave = new AtomicLong(0);
    private AtomicLong lastError = new AtomicLong(0);
    private int daysToKeep;

    /**
     *
     * @param storage if null then save is disabled
     */
    public StatsPersistence(Storage storage){
        this(storage,
                new DateUtil(),
                Properties.getAppInstance(),
                Properties.getAppType(),
                Properties.getSaveFreqMinutes(),
                Properties.getDaysToKeepData());
    }

    /**
     *
     * @param storage if null then save is disabled
     * @param dateUtil
     */
    public StatsPersistence(Storage storage, DateUtil dateUtil, String appInstance,
                            String appType, int saveFreqMinutes, int daysToKeep){
        this.storage = storage;
        this.dateUtil = dateUtil;
        lastSave.set(dateUtil.now().getTime());
        this.appType = appType;
        this.appInstance = appInstance;
        this.saveFreqMinutes = saveFreqMinutes;
        this.daysToKeep = daysToKeep;
    }

    public boolean threadSafeShouldSave(){
        if( storage != null && saveFreqMinutes > 0 ){
            Date now = dateUtil.now();

            //do not try to save for some time if error occurred
            long val = lastError.get();
            if( val > 0 ){
                long minutes = TimeUnit.MILLISECONDS.toMinutes(now.getTime() - val);
                if( minutes < 5 ){
                    return false;
                }
            }

            long offset = now.getTime() - lastSave.get();
            long minutes = TimeUnit.MILLISECONDS.toMinutes(offset);
            return minutes >= saveFreqMinutes;
        }
        return false;
    }

    /**
     * @param stats
     * @return true if successfully saved stats - otherwise false
     */
    public boolean safeSave(Stats stats){
        if( storage == null ){
            return false;
        }
        try{
            ensureDatesAreSet(stats);
            long start = System.currentTimeMillis();
            storage.save(stats, appInstance, appType);
            lastSave.set(dateUtil.now().getTime());
            lastError.set(0);
            log.info("Saved stats in {}ms", System.currentTimeMillis() - start);
            return true;
        }catch(Exception e){
            Throwable cause = firstNonNull(getRootCause(e), e);
            log.warn("Failed to save stats - next attempt in 5 minutes. Error type: {}, Message: {}", cause.getClass().getName(), cause.getMessage());
            log.debug("Failed to save stats - next attempt in 5 minutes. ", e);
            lastError.set(dateUtil.now().getTime());
            return false;
        }
    }

    public void safeCleanup() {
        if( daysToKeep <= 0 || lastError.get() > 0 ){
            return;
        }
        try{
            long start = System.currentTimeMillis();
            storage.cleanup(daysToKeep, appType);
            lastSave.set(dateUtil.now().getTime());
            log.info("Performed cleanup in {}ms", System.currentTimeMillis() - start);
        }catch(Exception e){
            Throwable cause = firstNonNull(getRootCause(e), e);
            log.warn("Failed to cleanup stats. Error type: {}, Message: {}", cause.getClass().getName(), cause.getMessage());
            log.debug("Failed to cleanup stats.", e);
        }
    }

    private void ensureDatesAreSet(Stats stats) {
        if( stats.getStartDate() == null ){
            stats.setStartDate(dateUtil.now());
        }
        if( stats.getEndDate() == null ){
            stats.setEndDate(dateUtil.now());
        }
    }

    public Date getLastSaveTime() {
        return new Date(lastSave.get());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy