package com.griddynamics.jagger.dbapi.fetcher; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.griddynamics.jagger.dbapi.dto.MetricNameDto; import com.griddynamics.jagger.dbapi.dto.PlotSingleDto; import com.griddynamics.jagger.dbapi.dto.PointDto; import com.griddynamics.jagger.util.Pair; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static com.griddynamics.jagger.dbapi.util.ColorCodeGenerator.getHexColorCode; import static com.griddynamics.jagger.dbapi.util.PlotPointShapeGenerator.generatePointShape; /** * Abstract class that deal with MetricRawData data to create PlotDatasetDto object * todo : all PlotFetchers can be refactored to extend this abstract class */ public abstract class AbstractMetricPlotFetcher extends PlotsDbMetricDataFetcher { @Override protected Set<Pair<MetricNameDto, List<PlotSingleDto>>> fetchData(List<MetricNameDto> metricNames) { if (metricNames.isEmpty()) { return Collections.emptySet(); } Collection<MetricRawData> allRawData = getAllRawData(metricNames); if (allRawData.isEmpty()) { log.warn("No plot data found for metrics : {}", metricNames); return Collections.emptySet(); } return getResult(allRawData, metricNames); } protected Set<Pair<MetricNameDto, List<PlotSingleDto>>> getResult(Collection<MetricRawData> allRawData, List<MetricNameDto> metricNames) { Map<Long, Multimap<String, MetricRawData>> taskIdMetricIdRawMap = createMappedPlotDatasets(metricNames); for (MetricRawData rawData : allRawData) { String metricId = rawData.getMetricId(); Long taskId = rawData.getWorkloadTaskDataId(); taskIdMetricIdRawMap.get(taskId).put(metricId, rawData); } Multimap<MetricNameDto, PlotSingleDto> metricNamePlotMap = ArrayListMultimap.create(); for (MetricNameDto metricName : metricNames) { for (Long taskId : metricName.getTaskIds()) { Collection<MetricRawData> rawDatas; Multimap<String, MetricRawData> multimap = taskIdMetricIdRawMap.get(taskId); if (multimap == null) { // we did not find metric for given task Id // it could happen if we got 2 sessions with different sets of custom metrics continue; } rawDatas = multimap.get(metricName.getMetricName()); if (rawDatas == null || rawDatas.isEmpty()) { // no data was saved for given taskId and metric Id continue; } metricNamePlotMap.put(metricName, assemble(metricName, rawDatas)); } } Set<Pair<MetricNameDto, List<PlotSingleDto>>> resultSet = new HashSet<>(metricNames.size()); for (MetricNameDto metricName : metricNamePlotMap.keySet()) { List<PlotSingleDto> plotDatasetDtoList = new ArrayList<>(metricNamePlotMap.get(metricName)); resultSet.add( Pair.of( metricName, plotDatasetDtoList )); } return resultSet; } protected PlotSingleDto assemble(MetricNameDto metricNameDto, Collection<MetricRawData> rawDatas) { List<PointDto> points = new ArrayList<>(rawDatas.size()); String sessionId = null; for (MetricRawData metricRawData : rawDatas) { if (sessionId == null) sessionId = metricRawData.getSessionId(); points.add(new PointDto(metricRawData.getTime() / 1000D, metricRawData.getValue())); } return new PlotSingleDto( points, legendProvider.generatePlotLegend( sessionId, metricNameDto.getMetricDisplayName(), true), getHexColorCode(metricNameDto.getMetricName(), sessionId), generatePointShape(metricNameDto.getMetricName(), sessionId)); } /** * method that retrieves all plotdata for given metricNames as MetricRawData * @param metricNames list of MetricNameDto objects for which plots should be retrieved * @return Collection of MetricRawData objects that represents one raw in database (one point on plot) */ protected abstract Collection<MetricRawData> getAllRawData(List<MetricNameDto> metricNames); /** * Map Collection of MetricNameDto first of all by TaskDataDto id, after all by metric name (metric id) * @param metricNameDtos collection of MetricNameDto to be mapped * @return Map<Long, Multimap<String, MetricRawData>> mappedPlotDatasets. */ private Map<Long, Multimap<String, MetricRawData>> createMappedPlotDatasets(Collection<MetricNameDto> metricNameDtos) { Map<Long, Multimap<String, MetricRawData>> taskIdMap = new HashMap<>(); for (MetricNameDto metricName : metricNameDtos) { Set<Long> ids = metricName.getTaskIds(); for (Long id : ids) { if (!taskIdMap.containsKey(id)) { taskIdMap.put(id, ArrayListMultimap.create()); } } } return taskIdMap; } public static class MetricRawData { private String metricId; private Long workloadTaskDataId; private String sessionId; private Long time; private Double value; public void setMetricId(String metricId) { this.metricId = metricId; } public void setWorkloadTaskDataId(Long workloadTaskDataId) { this.workloadTaskDataId = workloadTaskDataId; } public String getMetricId() { return metricId; } public Long getWorkloadTaskDataId() { return workloadTaskDataId; } public String getSessionId() { return sessionId; } public Long getTime() { return time; } public void setTime(Long time) { this.time = time; } public Double getValue() { return value; } public void setValue(Double value) { this.value = value; } public void setSessionId(String sessionId) { this.sessionId = sessionId; } } }