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

com.github.endoscope.cdiui.StatsDataController Maven / Gradle / Ivy

package com.github.endoscope.cdiui;

import com.github.endoscope.Endoscope;
import com.github.endoscope.core.Stat;
import com.github.endoscope.core.Stats;
import com.github.endoscope.properties.Properties;
import com.github.endoscope.storage.Filters;
import com.github.endoscope.storage.Histogram;
import com.github.endoscope.storage.StatDetails;
import com.github.endoscope.storage.StatHistory;
import com.github.endoscope.storage.Storage;
import com.github.endoscope.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.slf4j.LoggerFactory.getLogger;

@Path("/endoscope")
public class StatsDataController {
    private static final Logger log = getLogger(StatsDataController.class);

    private JsonUtil jsonUtil = new JsonUtil();

    protected Response noCacheResponse( Object entity ) {
        CacheControl cc = new CacheControl();
        cc.setNoCache( true );
        cc.setMaxAge( -1 );
        cc.setMustRevalidate( true );

        return Response.ok( entity ).cacheControl( cc ).build();
    }

    @GET
    @Path("/data/top")
    @Produces("application/json")
    public Response top(@QueryParam("from") String fromS,
                        @QueryParam("to") String toS,
                        @QueryParam("past") String pastS,
                        @QueryParam("instance") String instance,
                        @QueryParam("type") String type,
                        @QueryParam("reset") boolean reset) {
        Long from = toLong(fromS), to = toLong(toS), past = toLong(pastS);

        if( reset ){
            log.info("Resetting current stats");
            Endoscope.resetStats();
        }

        Stats stats = topLevelForRange(new Range(from, to, past, instance, type));
        return noCacheResponse(jsonUtil.toJson(stats));
    }

    private Long toLong(String value){
        if( value == null || value.trim().length() == 0 ){
            return null;
        }
        return Long.valueOf(value);
    }

    @GET
    @Path("/data/details")
    @Produces("application/json")
    public Response details(@QueryParam("id") String id,
                            @QueryParam("from") String fromS,
                            @QueryParam("to") String toS,
                            @QueryParam("past") String pastS,
                            @QueryParam("instance") String instance,
                            @QueryParam("type") String type){
        Long from = toLong(fromS), to = toLong(toS), past = toLong(pastS);
        StatDetails details = detailsForRange(id, new Range(from, to, past, instance, type));
        return noCacheResponse(jsonUtil.toJson(details));
    }

    @GET
    @Path("/data/histogram")
    @Produces("application/json")
    public Response histogram(@QueryParam("id") String id,
                            @QueryParam("from") String fromS,
                            @QueryParam("to") String toS,
                            @QueryParam("past") String pastS,
                            @QueryParam("instance") String instance,
                            @QueryParam("type") String type){
        Long from = toLong(fromS), to = toLong(toS), past = toLong(pastS);
        Histogram histogram = histogramForRange(id, new Range(from, to, past, instance, type));
        return noCacheResponse(jsonUtil.toJson(histogram));
    }

    private static class Range {
        public Range(Long from, Long to, Long past, String instance, String type){
            this.instance = instance;
            this.type = type;
            if( past != null ){
                if( past > 0 ){
                    toDate = new Date();
                    fromDate = new Date(toDate.getTime() - past);
                }
            } else {
                if( from != null ){
                    fromDate = new Date(from);

                    //to requires from
                    if( to != null ){
                        toDate = new Date(to);
                        includeCurrent = false;
                    } else {
                        toDate = new Date();
                    }
                }
            }
        }

        Date fromDate = null;
        Date toDate = null;
        String instance;
        String type;
        boolean includeCurrent = true;
    }

    private Stats topLevelForRange(Range range) {
        Stats result;
        if( canSearch(range) ){
            result = getStorage().loadAggregated(true, range.fromDate, range.toDate, range.instance, range.type);
            if( inMemoryInRange(range) ){
                Stats current = topLevelInMemory();
                result.merge(current, false);
                result.setInfo("Added in-memory data. Original info: " + result.getInfo());
            }
        } else{
            result = topLevelInMemory();
            result.setInfo("in-memory data only. Original info: " + result.getInfo());
        }
        return result;
    }

    private StatDetails detailsForRange(String id, Range range) {
        StatDetails result;
        if( canSearch(range) ){
            result = getStorage().loadDetails(id, range.fromDate, range.toDate, range.instance, range.type);
            if( inMemoryInRange(range) ){
                StatDetails current = detailsInMemory(id);
                if( current != null ){
                    //we don't want to merge not set stats as it would reset min value to 0
                    result.getMerged().merge(current.getMerged(), true);
                }
                result.setInfo("Added in-memory data. Original info: " + result.getInfo());
            }
        } else {
            result = detailsInMemory(id);
            result.setInfo("in-memory data only. Original info: " + result.getInfo());
        }
        return (result != null) ? result : new StatDetails(id, Stat.emptyStat());
    }

    private Histogram histogramForRange(String id, Range range) {
        Histogram result;
        if( canSearch(range) ){
            result = getStorage().loadHistogram(id, range.fromDate, range.toDate, range.instance, range.type);
            if( inMemoryInRange(range) ){
                Histogram current = histogramInMemory(id);
                if( current != null ){
                    result.getHistogram().addAll(current.getHistogram());
                }
                result.setInfo("Added in-memory data. Original info: " + result.getInfo());
            }
        } else {
            result = histogramInMemory(id);
            result.setInfo("in-memory data only. Original info: " + result.getInfo());
        }
        return (result != null) ? result : new Histogram(id);
    }

    private boolean inMemoryInRange(Range range){
        return range.includeCurrent
                && (isBlank(range.instance) || StringUtils.equals(range.instance, Properties.getAppInstance()))
                && (isBlank(range.type) || StringUtils.equals(range.type, Properties.getAppType()));
    }

    private boolean canSearch(Range range){
        return range.fromDate != null && range.toDate != null
                && Endoscope.getStatsStorage() != null;
    }

    private Stats topLevelInMemory() {
        return Endoscope.processStats(stats -> stats.deepCopy(false) );
    }

    private StatDetails detailsInMemory(String id) {
        return Endoscope.processStats(stats -> {
            Stat s = stats.getMap().get(id);
            if( s == null ){//might happen when stats get saved and/or reset in the mean time
                return null;
            }
            s = s.deepCopy();
            StatDetails result = new StatDetails(id, s);
            return result;
        });
    }

    private Histogram histogramInMemory(String id) {
        return Endoscope.processStats(stats -> {
            Stat s = stats.getMap().get(id);
            if( s == null ){//might happen when stats get saved and/or reset in the mean time
                return null;
            }
            Histogram result = new Histogram(id);
            result.getHistogram().add(
                    new StatHistory(s, stats.getStartDate(), new Date())
            );
            return result;
        });
    }

    private Storage getStorage() {
        Storage storage;
        try{
            storage = Endoscope.getStatsStorage();
            if( storage == null ){
                throw new RuntimeException("Storage not supported");
            }
        }catch(ClassCastException e){
            throw new RuntimeException("Range search is not supported");
        }
        return storage;
    }


    @GET
    @Path("/data/filters")
    @Produces("application/json")
    public Response filters(@QueryParam("from") String fromS,
                            @QueryParam("to") String toS,
                            @QueryParam("past") String pastS){
        Long from = toLong(fromS), to = toLong(toS), past = toLong(pastS);
        Range range = new Range(from, to, past, null, null);
        Filters filters = null;
        if( canSearch(range) ){
            filters = getStorage().findFilters(range.fromDate, range.toDate, null);
        }
        if( filters == null){
            filters = new Filters(null, null);
        }
        filters.setInstances(addDefaultAndSort(filters.getInstances(), Properties.getAppInstance()));
        filters.setTypes(    addDefaultAndSort(filters.getTypes(),     Properties.getAppType()));
        return noCacheResponse(jsonUtil.toJson(filters));
    }

    private List addDefaultAndSort(List list, String defaultValue){
        if( list == null ){
            list = new ArrayList<>();
        }
        list = list.stream()
                .filter(element -> element != null)
                .collect(Collectors.toList());

        if( !list.contains(defaultValue) ){
            list.add(defaultValue);
        }
        Collections.sort(list);
        return list;
    }

    @GET
    @Path("/res-dynamic/endoscopeAppType.js")
    @Produces("application/javascript")
    public Response defaultSettings() {
        return noCacheResponse(
                "window.endoscopeAppType = \"" + Properties.getAppType() + "\";\n" +
                "window.endoscopeAppInstance = \"" + Properties.getAppInstance() + "\";\n"
        );
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy