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 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 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 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 from,
                        @QueryParam("to") String to,
                        @QueryParam("past") String past,
                        @QueryParam("instance") String instance,
                        @QueryParam("type") String type,
                        @QueryParam("reset") boolean reset) {
        if( reset ){
            log.info("Resetting current stats");
            Endoscope.resetStats();
        }

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

    @GET
    @Path("/data/details")
    @Produces("application/json")
    public Response details(@QueryParam("id") String id,
                            @QueryParam("from") String from,
                            @QueryParam("to") String to,
                            @QueryParam("past") String past,
                            @QueryParam("instance") String instance,
                            @QueryParam("type") String type){
        StatDetails details = detailsForRange(id, new TimeRange(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 from,
                            @QueryParam("to") String to,
                            @QueryParam("past") String past,
                            @QueryParam("instance") String instance,
                            @QueryParam("type") String type,
                            @QueryParam("lastGroupId") String lastGroupId){
        lastGroupId = StringUtils.trimToNull(lastGroupId);
        Histogram histogram = histogramForRange(id, new TimeRange(from, to, past, instance, type), lastGroupId);
        return noCacheResponse(jsonUtil.toJson(histogram));
    }

    private Stats topLevelForRange(TimeRange range) {
        Stats result;
        if( canSearch(range) ){
            result = getStorage().loadAggregated(true, range.getFromDate(), range.getToDate(), range.getInstance(), range.getType());
            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, TimeRange range) {
        StatDetails result;
        if( canSearch(range) ){
            result = getStorage().loadDetails(id, range.getFromDate(), range.getToDate(), range.getInstance(), range.getType());
            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, TimeRange range, String lastGroupId) {
        Histogram result;
        if( canSearch(range) ){
            result = getStorage().loadHistogram(id, range.getFromDate(), range.getToDate(), range.getInstance(), range.getType(), lastGroupId);

            if( inMemoryInRange(range) && result.isLastHistogramPart() ){
                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());
        }
        result.setInfo(result.getInfo() + ", " + range.toString() );
        return (result != null) ? result : new Histogram(id);
    }

    private boolean inMemoryInRange(TimeRange range){
        return range.isIncludeCurrent()
                && (isBlank(range.getInstance()) || StringUtils.equals(range.getInstance(), Properties.getAppInstance()))
                && (isBlank(range.getType()) || StringUtils.equals(range.getType(), Properties.getAppType()));
    }

    private boolean canSearch(TimeRange range){
        return range.getFromDate() != null && range.getToDate() != 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 from,
                            @QueryParam("to") String to,
                            @QueryParam("past") String past){
        TimeRange range = new TimeRange(from, to, past, null, null);
        Filters filters = null;
        if( canSearch(range) ){
            filters = getStorage().findFilters(range.getFromDate(), range.getToDate(), 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"
        );
    }

    @GET
    @Path("/data/queue-size")
    @Produces("application/json")
    public Response queueCount() {
        return noCacheResponse("{\"count\": " + Endoscope.getQueueSize() + "}");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy