package com.griddynamics.jagger.dbapi; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.griddynamics.jagger.dbapi.dto.DecisionPerMetricDto; import com.griddynamics.jagger.dbapi.dto.DecisionPerSessionDto; import com.griddynamics.jagger.dbapi.dto.DecisionPerTestDto; import com.griddynamics.jagger.dbapi.dto.DecisionPerTestGroupDto; import com.griddynamics.jagger.dbapi.dto.MetricNameDto; import com.griddynamics.jagger.dbapi.dto.NodeInfoDto; import com.griddynamics.jagger.dbapi.dto.NodeInfoPerSessionDto; import com.griddynamics.jagger.dbapi.dto.PlotIntegratedDto; import com.griddynamics.jagger.dbapi.dto.PlotSingleDto; import com.griddynamics.jagger.dbapi.dto.SummaryIntegratedDto; import com.griddynamics.jagger.dbapi.dto.SummaryMetricValueDto; import com.griddynamics.jagger.dbapi.dto.SummarySingleDto; import com.griddynamics.jagger.dbapi.dto.TaskDataDto; import com.griddynamics.jagger.dbapi.dto.TaskDecisionDto; import com.griddynamics.jagger.dbapi.dto.TestInfoDto; import com.griddynamics.jagger.dbapi.entity.DecisionPerMetricEntity; import com.griddynamics.jagger.dbapi.entity.DecisionPerSessionEntity; import com.griddynamics.jagger.dbapi.entity.DecisionPerTaskEntity; import com.griddynamics.jagger.dbapi.entity.NodeInfoEntity; import com.griddynamics.jagger.dbapi.entity.NodePropertyEntity; import com.griddynamics.jagger.dbapi.entity.TaskData; import com.griddynamics.jagger.dbapi.fetcher.CustomMetricPlotFetcher; import com.griddynamics.jagger.dbapi.fetcher.CustomMetricSummaryFetcher; import com.griddynamics.jagger.dbapi.fetcher.CustomTestGroupMetricPlotFetcher; import com.griddynamics.jagger.dbapi.fetcher.CustomTestGroupMetricSummaryFetcher; import com.griddynamics.jagger.dbapi.fetcher.MetricDataFetcher; import com.griddynamics.jagger.dbapi.fetcher.PlotsDbMetricDataFetcher; import com.griddynamics.jagger.dbapi.fetcher.SessionScopeTestGroupMetricPlotFetcher; import com.griddynamics.jagger.dbapi.fetcher.ValidatorSummaryFetcher; import com.griddynamics.jagger.dbapi.model.DetailsNode; import com.griddynamics.jagger.dbapi.model.LegendNode; import com.griddynamics.jagger.dbapi.model.MetricGroupNode; import com.griddynamics.jagger.dbapi.model.MetricNode; import com.griddynamics.jagger.dbapi.model.MetricRankingProvider; import com.griddynamics.jagger.dbapi.model.NameTokens; import com.griddynamics.jagger.dbapi.model.PlotNode; import com.griddynamics.jagger.dbapi.model.RootNode; import com.griddynamics.jagger.dbapi.model.SessionInfoNode; import com.griddynamics.jagger.dbapi.model.SummaryNode; import com.griddynamics.jagger.dbapi.model.TestDetailsNode; import com.griddynamics.jagger.dbapi.model.TestInfoNode; import com.griddynamics.jagger.dbapi.model.TestNode; import com.griddynamics.jagger.dbapi.model.rules.LegendTreeViewGroupRuleProvider; import com.griddynamics.jagger.dbapi.model.rules.TreeViewGroupMetricsToNodeRule; import com.griddynamics.jagger.dbapi.model.rules.TreeViewGroupMetricsToNodeRuleProvider; import com.griddynamics.jagger.dbapi.model.rules.TreeViewGroupRule; import com.griddynamics.jagger.dbapi.model.rules.TreeViewGroupRuleProvider; import com.griddynamics.jagger.dbapi.parameter.DefaultMonitoringParameters; import com.griddynamics.jagger.dbapi.parameter.GroupKey; import com.griddynamics.jagger.dbapi.provider.CustomMetricNameProvider; import com.griddynamics.jagger.dbapi.provider.CustomMetricPlotNameProvider; import com.griddynamics.jagger.dbapi.provider.SessionInfoProvider; import com.griddynamics.jagger.dbapi.provider.SessionInfoProviderImpl; import com.griddynamics.jagger.dbapi.provider.ValidatorNamesProvider; import com.griddynamics.jagger.dbapi.util.CommonUtils; import com.griddynamics.jagger.dbapi.util.DataProcessingUtil; import com.griddynamics.jagger.dbapi.util.FetchUtil; import com.griddynamics.jagger.dbapi.util.LegendProvider; import com.griddynamics.jagger.dbapi.util.MetricNameUtil; import com.griddynamics.jagger.dbapi.util.SessionMatchingSetup; import com.griddynamics.jagger.util.Decision; import com.griddynamics.jagger.util.MonitoringIdUtils; import com.griddynamics.jagger.util.Pair; import com.griddynamics.jagger.util.StandardMetricsNamesUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceException; import java.math.BigInteger; 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.Objects; import java.util.PriorityQueue; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.stream.Collectors; import static com.google.common.collect.Lists.newArrayList; import static com.griddynamics.jagger.dbapi.dto.MetricNameDto.Origin.TEST_GROUP_METRIC; import static java.util.stream.Collectors.toList; /** * Created by kgribov on 4/2/14. */ @SuppressWarnings({"unchecked", "SpellCheckingInspection", "DefaultFileTemplate"}) @Service("databaseService") public class DatabaseServiceImpl implements DatabaseService { private Logger log = LoggerFactory.getLogger(this.getClass()); @PersistenceContext private EntityManager entityManager; @Autowired @Qualifier("executorService") private ExecutorService threadPool; @Autowired private LegendProvider legendProvider; @Resource private Map<GroupKey, DefaultMonitoringParameters[]> monitoringPlotGroups; private Map<String, Set<String>> defaultMonitoringParams = new HashMap<>(); @Autowired private CustomMetricPlotNameProvider customMetricPlotNameProvider; @Autowired private CustomMetricNameProvider customMetricNameProvider; @Autowired private ValidatorNamesProvider validatorNamesProvider; @Autowired private SessionInfoProviderImpl sessionInfoServiceImpl; @Autowired private TreeViewGroupRuleProvider treeViewGroupRuleProvider; @Autowired private LegendTreeViewGroupRuleProvider legendTreeViewGroupRuleProvider; @Autowired private TreeViewGroupMetricsToNodeRuleProvider treeViewGroupMetricsToNodeRuleProvider; @Autowired private CustomMetricPlotFetcher customMetricPlotFetcher; @Autowired private CustomTestGroupMetricPlotFetcher customTestGroupMetricPlotFetcher; @Autowired private SessionScopeTestGroupMetricPlotFetcher sessionScopeTestGroupMetricPlotFetcher; @Autowired private CustomMetricSummaryFetcher customMetricSummaryFetcher; @Autowired private CustomTestGroupMetricSummaryFetcher customTestGroupMetricSummaryFetcher; @Autowired private ValidatorSummaryFetcher validatorSummaryFetcher; @Autowired private FetchUtil fetchUtil; @PostConstruct public void postConstruct() { this.defaultMonitoringParams = getDefaultMonitoringParametersMap(monitoringPlotGroups); this.sessionInfoServiceImpl.setIsTagsStorageAvailable(checkIfTagsStorageAvailable()); this.sessionInfoServiceImpl.setIsUserCommentStorageAvailable(checkIfUserCommentStorageAvailable()); } //=========================== //=======Get plot data======= //=========================== @Override public Map<MetricNode, PlotIntegratedDto> getPlotDataByMetricNode(Set<MetricNode> metricNodes) { if (metricNodes.isEmpty()) { return Collections.emptyMap(); } long startTime = System.currentTimeMillis(); Set<MetricNameDto> metricNameDtoSet = MetricNameUtil.getMetricNameDtoSet(metricNodes); Map<MetricNameDto, List<PlotSingleDto>> resultMap = getPlotDataByMetricNameDto(metricNameDtoSet); Multimap<MetricNode, PlotSingleDto> tempMultiMap = ArrayListMultimap.create(); for (Map.Entry<MetricNameDto, List<PlotSingleDto>> entry : resultMap.entrySet()) { for (MetricNode metricNode : metricNodes) { if (metricNode.getMetricNameDtoList().contains(entry.getKey())) { tempMultiMap.putAll(metricNode, entry.getValue()); break; } } } Map<MetricNode, PlotIntegratedDto> result = new HashMap<>(); for (MetricNode metricNode : metricNodes) { List<PlotSingleDto> plotDatasetDtoList = new ArrayList<>(tempMultiMap.get(metricNode)); // Sort lines by legend Collections.sort(plotDatasetDtoList, (o1, o2) -> { String param1 = o1.getLegend(); String param2 = o2.getLegend(); int res = String.CASE_INSENSITIVE_ORDER.compare(param1, param2); return (res != 0) ? res : param1.compareTo(param2); }); result.put(metricNode, createPlotIntegratedDto(metricNode, plotDatasetDtoList, "Time, sec")); } log.debug("Total time of plots for metricNodes retrieving : {}", System.currentTimeMillis() - startTime); return result; } /** * Creates plot for given MetricNode and lines referred to it * * @param metricNode metric node for witch plot should be created * @param curves lines of plot * @param xAxisLabel x axis label * @return plot for given MetricNode */ private PlotIntegratedDto createPlotIntegratedDto(MetricNode metricNode, List<PlotSingleDto> curves, String xAxisLabel) { String taskName = metricNode.getMetricNameDtoList().get(0).getTest().getTaskName(); MetricNameDto firstMetricNameDto = metricNode.getMetricNameDtoList().get(0); String plotHeader; if (isSessionScopeMetric(firstMetricNameDto)) plotHeader = legendProvider.generateSessionScopePlotHeader(metricNode.getDisplayName()); else plotHeader = legendProvider.generatePlotHeader(taskName, metricNode.getDisplayName()); return new PlotIntegratedDto(createLegendTree(metricNode, curves), xAxisLabel, "", plotHeader); } /** * Creates legend as tree with LegendNode as leafs * * @param metricNode metricNode for witch legend tree should be created * @param curves lines of plot * @return legend tree */ private MetricGroupNode<LegendNode> createLegendTree(MetricNode metricNode, List<PlotSingleDto> curves) { Map<String, List<LegendNode>> legendGroupsMap = new HashMap<>(); Set<String> legendGroups = new HashSet<>(); // used to allow grouping identical legends int i = 1; for (PlotSingleDto curve : curves) { LegendNode mn = new LegendNode(); String legend = curve.getLegend(); mn.setId((i++) + legend); mn.setDisplayName(legend); mn.setLine(curve); // dummy metricNameDto is needed only to use same method of grouping nodes (TreeViewGroupRule.filter()) MetricNameDto metricNameDto = new MetricNameDto(null, mn.getId(), mn.getDisplayName()); mn.setMetricNameDtoList(Collections.singletonList(metricNameDto)); String metricName = LegendProvider.parseMetricName(legend); if (!legendGroupsMap.containsKey(metricName)) { legendGroupsMap.put(metricName, new ArrayList<>()); } legendGroupsMap.get(metricName).add(mn); } List<LegendNode> metricNodeList = new ArrayList<>(); for (Map.Entry<String, List<LegendNode>> entry : legendGroupsMap.entrySet()) { metricNodeList.addAll(entry.getValue()); if (entry.getValue().size() > 1) { for (MetricNode mn : entry.getValue()) { String sessionId = LegendProvider.parseSessionId(mn.getDisplayName()); if (sessionId != null) { mn.setDisplayName(sessionId); } } legendGroups.add(entry.getKey()); } } // only legends with sessions should be grouped // first '[0-9]+' used to escape first number, used to enable grouping identical legends. String legendFormat = "[0-9]+" + legendProvider.generatePlotLegend("[0-9]+", "%s", true); // rules to create legend tree view TreeViewGroupRule groupedNodesRule = legendTreeViewGroupRuleProvider.provide(metricNode.getId(), legendGroups, legendFormat); // tree with metrics distributed by groups return groupedNodesRule.filter(null, metricNodeList); } @Override public Map<MetricNameDto, List<PlotSingleDto>> getPlotDataByMetricNameDto(Set<MetricNameDto> metricNames) throws IllegalArgumentException { if (metricNames.isEmpty()) { return Collections.emptyMap(); } final long temp = System.currentTimeMillis(); final Multimap<PlotsDbMetricDataFetcher, MetricNameDto> fetchMap = ArrayListMultimap.create(); for (MetricNameDto metricNameDto : metricNames) { switch (metricNameDto.getOrigin()) { case METRIC: fetchMap.put(customMetricPlotFetcher, metricNameDto); break; case TEST_GROUP_METRIC: fetchMap.put(customTestGroupMetricPlotFetcher, metricNameDto); break; case SESSION_SCOPE_TG: fetchMap.put(sessionScopeTestGroupMetricPlotFetcher, metricNameDto); break; default: // if anything else log.error("MetricNameDto with origin : {} appears in metric name list for plot retrieving ({})", metricNameDto.getOrigin(), metricNameDto); throw new RuntimeException(String.format( "Unable to get plot for metric %s with origin: %s", metricNameDto.getMetricName(), metricNameDto.getOrigin().toString() )); } } List<Future<Set<Pair<MetricNameDto, List<PlotSingleDto>>>>> futures = new ArrayList<>(); for (final PlotsDbMetricDataFetcher fetcher : fetchMap.keySet()) { futures.add(threadPool.submit(() -> fetcher.getResult(new ArrayList<>(fetchMap.get(fetcher))))); } Set<Pair<MetricNameDto, List<PlotSingleDto>>> resultSet = new HashSet<>(); try { for (Future<Set<Pair<MetricNameDto, List<PlotSingleDto>>>> future : futures) { resultSet.addAll(future.get()); } } catch (Throwable th) { log.error("Exception while plots retrieving", th); throw new RuntimeException("Exception while plots retrieving", th); } Map<MetricNameDto, List<PlotSingleDto>> result = new HashMap<>(); for (Pair<MetricNameDto, List<PlotSingleDto>> pair : resultSet) { result.put(pair.getFirst(), pair.getSecond()); } log.debug("Total time of plots for metricNameDtos retrieving: {}", System.currentTimeMillis() - temp); return result; } //=========================== //=====Get control tree====== //=========================== @Override public RootNode getControlTreeForSessions(Set<String> sessionIds, SessionMatchingSetup sessionMatchingSetup) throws RuntimeException { try { long temp = System.currentTimeMillis(); RootNode rootNode = new RootNode(); List<TaskDataDto> taskList = fetchTaskDatas(sessionIds, sessionMatchingSetup); Future<SummaryNode> summaryFuture = threadPool.submit(new SummaryNodeFetcherThread(taskList)); Future<DetailsNode> detailsNodeFuture = threadPool.submit(new DetailsNodeFetcherThread(sessionIds, taskList)); SummaryNode summaryNode = summaryFuture.get(); DetailsNode detailsNode = detailsNodeFuture.get(); rootNode.setSummaryNode(summaryNode); rootNode.setDetailsNode(detailsNode); log.info("Total time fetching all data for control tree : {} ms", (System.currentTimeMillis() - temp)); return rootNode; } catch (Throwable th) { log.error("Error while creating Control Tree", th); th.printStackTrace(); throw new RuntimeException(th); } } //=========================== //=====Get summary data====== //=========================== @Override public Map<MetricNode, SummaryIntegratedDto> getSummaryByMetricNodes(Set<MetricNode> metricNodes, boolean isEnableDecisionsPerMetricFetching) { if (metricNodes.isEmpty()) { return Collections.emptyMap(); } long temp = System.currentTimeMillis(); Set<MetricNameDto> metricNameDtoSet = MetricNameUtil.getMetricNameDtoSet(metricNodes); Collection<SummarySingleDto> allMetricDto = getSummaryByMetricNameDto(metricNameDtoSet, isEnableDecisionsPerMetricFetching).values(); // filter results by MetricNode Multimap<MetricNode, SummarySingleDto> tempMap = ArrayListMultimap.create(); for (SummarySingleDto singleSumDto : allMetricDto) { for (MetricNode metricNode : metricNodes) { if (metricNode.getMetricNameDtoList().contains(singleSumDto.getMetricName())) { tempMap.put(metricNode, singleSumDto); break; } } } // generate result map Map<MetricNode, SummaryIntegratedDto> resultMap = new HashMap<>(tempMap.size()); for (MetricNode metricNode : tempMap.keySet()) { List<SummarySingleDto> sumCollection = new ArrayList<>(tempMap.get(metricNode)); List<PlotSingleDto> plotSingleDtos = new ArrayList<>(sumCollection.size()); MetricRankingProvider.sortMetrics(sumCollection); plotSingleDtos.addAll(sumCollection.stream().map(DataProcessingUtil::generatePlotSingleDto).collect(toList())); SummaryIntegratedDto summaryDto = new SummaryIntegratedDto(); summaryDto.setSummarySingleDtoList(sumCollection); summaryDto.setPlotIntegratedDto(createPlotIntegratedDto(metricNode, plotSingleDtos, "Sessions")); resultMap.put(metricNode, summaryDto); } log.debug("Total time of Summary Data retrieving for " + metricNodes.size() + " metric nodes : " + (System.currentTimeMillis() - temp)); return resultMap; } @Override public Map<MetricNameDto, SummarySingleDto> getSummaryByMetricNameDto(Set<MetricNameDto> metricNames, boolean isEnableDecisionsPerMetricFetching) { final long temp = System.currentTimeMillis(); final Multimap<MetricDataFetcher<SummarySingleDto>, MetricNameDto> fetchMap = ArrayListMultimap.create(); for (MetricNameDto metricName : metricNames) { switch (metricName.getOrigin()) { case METRIC: fetchMap.put(customMetricSummaryFetcher, metricName); break; case TEST_GROUP_METRIC: fetchMap.put(customTestGroupMetricSummaryFetcher, metricName); break; case VALIDATOR: fetchMap.put(validatorSummaryFetcher, metricName); break; case SESSION_SCOPE_TG: break; default: // if anything else log.error("MetricNameDto with origin : {} appears in metric name list for summary retrieving ({})", metricName.getOrigin(), metricName); throw new RuntimeException("Unable to get summary data for metric " + metricName.getMetricName() + " with origin: " + metricName.getOrigin()); } } List<Future<Set<SummarySingleDto>>> futures = new ArrayList<>(); for (final MetricDataFetcher<SummarySingleDto> fetcher : fetchMap.keySet()) { futures.add(threadPool.submit(() -> fetcher.getResult(new ArrayList<>(fetchMap.get(fetcher))))); } Set<SummarySingleDto> result = new HashSet<>(metricNames.size()); try { for (Future<Set<SummarySingleDto>> future : futures) { result.addAll(future.get()); } } catch (Throwable th) { th.printStackTrace(); log.error("Exception while summary retrieving", th); throw new RuntimeException("Exception while summary retrieving" + th.getMessage()); } // Find what decisions were taken for metrics if (isEnableDecisionsPerMetricFetching) { Map<MetricNameDto, Map<String, Decision>> metricDecisions = getDecisionsPerMetric(metricNames); if (!metricDecisions.isEmpty()) { for (SummarySingleDto metricDto : result) { MetricNameDto metricName = metricDto.getMetricName(); if (metricDecisions.containsKey(metricName)) { Map<String, Decision> decisionPerSession = metricDecisions.get(metricName); for (SummaryMetricValueDto metricValueDto : metricDto.getValues()) { String sessionId = Long.toString(metricValueDto.getSessionId()); if (decisionPerSession.containsKey(sessionId)) { metricValueDto.setDecision(decisionPerSession.get(sessionId)); } } } } } } Map<MetricNameDto, SummarySingleDto> resultMap = new HashMap<>(result.size()); for (SummarySingleDto ssd : result) { resultMap.put(ssd.getMetricName(), ssd); } log.debug("{} ms spent for fetching summary data for {} metrics", System.currentTimeMillis() - temp, metricNames.size()); return resultMap; } @Override public Map<String, Set<String>> getDefaultMonitoringParameters() { return defaultMonitoringParams; } private Map<String, Set<String>> getDefaultMonitoringParametersMap(Map<GroupKey, DefaultMonitoringParameters[]> monitoringPlotGroups) { // relation of old monitoring names from Groupkey (were used in hyperlinks) to // new monitoring metric ids from DefaultMonitoringParameters // necessary to process old hyperlinks by new client Map<String, Set<String>> result = new HashMap<>(); for (Map.Entry<GroupKey, DefaultMonitoringParameters[]> groupKeyEntry : monitoringPlotGroups.entrySet()) { String key = groupKeyEntry.getKey().getUpperName(); if (!result.containsKey(key)) { result.put(key, new HashSet<>()); } for (DefaultMonitoringParameters defaultMonitoringParameters : groupKeyEntry.getValue()) { result.get(key).add(defaultMonitoringParameters.getId()); } } return result; } private Map<TaskDataDto, List<MetricNode>> getTestMetricsMap(final List<TaskDataDto> dtos) { Long time = System.currentTimeMillis(); List<MetricNameDto> list = new ArrayList<>(); try { Future<Set<MetricNameDto>> customMetricNamesFuture = threadPool.submit(() -> customMetricNameProvider.getMetricNames(dtos)); Future<Set<MetricNameDto>> validatorsNamesFuture = threadPool.submit(() -> validatorNamesProvider.getMetricNames(dtos)); list.addAll(customMetricNamesFuture.get()); list.addAll(validatorsNamesFuture.get()); } catch (Exception e) { log.error("Exception occurs while fetching MetricNames for tests : ", e); throw new RuntimeException(e); } log.debug("Search metric names for tasks: {}", dtos); log.info("For {} tasks were found {} metrics names for {} ms", new Object[]{dtos.size(), list.size(), System.currentTimeMillis() - time}); Map<TaskDataDto, List<MetricNode>> result = new HashMap<>(); for (MetricNameDto mnd : list) { if ((mnd.getMetricName() == null) || (mnd.getMetricName().equals(""))) { log.warn("Metric with undefined id detected. It will be ignored. Details: " + mnd); } else { for (TaskDataDto tdd : dtos) { if (tdd.getIds().containsAll(mnd.getTaskIds())) { if (!result.containsKey(tdd)) { result.put(tdd, new ArrayList<>()); } MetricNode mn = new MetricNode(); String id = NameTokens.SUMMARY_PREFIX + tdd.hashCode() + mnd.getMetricName(); mn.init(id, mnd.getMetricDisplayName(), Collections.singletonList(mnd)); result.get(tdd).add(mn); break; } } } } return result; } private Map<TaskDataDto, List<PlotNode>> getTestPlotsMap(Set<String> sessionIds, List<TaskDataDto> taskList) { Map<TaskDataDto, List<PlotNode>> result = new HashMap<>(); List<MetricNameDto> metricNameDtoList = new ArrayList<>(); try { metricNameDtoList.addAll(customMetricPlotNameProvider.getPlotNames(taskList)); log.debug("For sessions {} are available these plots: {}", sessionIds, metricNameDtoList); for (MetricNameDto pnd : metricNameDtoList) { if ((pnd.getMetricName() == null) || (pnd.getMetricName().equals(""))) { log.warn("Metric with undefined id detected. It will be ignored. Details: " + pnd); } else { for (TaskDataDto tdd : taskList) { if (!result.containsKey(tdd)) { result.put(tdd, new ArrayList<>()); } if (tdd.getIds().containsAll(pnd.getTaskIds())) { PlotNode pn = new PlotNode(); String id = NameTokens.METRICS_PREFIX + tdd.hashCode() + pnd.getMetricName() + pnd.getOrigin(); pn.init(id, pnd.getMetricDisplayName(), Collections.singletonList(pnd)); result.get(tdd).add(pn); break; } } } } } catch (Exception e) { log.error("Error was occurred during task scope plots data getting for session IDs " + sessionIds + ", tasks : " + taskList, e); throw new RuntimeException(e); } return result; } @Override public List<TaskDataDto> getTaskDataForSessions(Set<String> sessionIds, SessionMatchingSetup sessionMatchingSetup) { final long timestamp = System.currentTimeMillis(); int havingCount = 0; if (sessionMatchingSetup.isShowOnlyMatchedTests()) { havingCount = sessionIds.size(); } List<Object[]> list = entityManager.createNativeQuery( "select taskData.id, commonTests.name, commonTests.description, taskData.taskId , commonTests.clock, commonTests" + ".clockValue, commonTests.termination, taskData.sessionId" + " from " + "( " + " select test.name, test.description, test.version, test.sessionId, test.taskId, test.clock, test.clockValue, " + "test.termination from " + " ( " + " select " + " l.*, s.name, s.description, s.version " + " from " + " (select * from WorkloadTaskData where sessionId in (:sessions)) as l " + " left outer join " + " (select * from WorkloadDetails) as s " + " on l.scenario_id=s.id " + " ) as test " + " inner join " + " ( " + " select t.* from " + " ( " + " select " + " l.*, s.name, s.description, s.version " + " from " + " (select * from WorkloadTaskData where sessionId in (:sessions)) as l " + " left outer join " + " (select * from WorkloadDetails) as s " + " on l.scenario_id=s.id " + " ) as t " + " group by " + " t.termination, t.clock, t.clockValue, t.name, t.description, t.version " + " having count(t.id)>=" + havingCount + " ) as testArch " + " on " + " test.clock=testArch.clock and " + " test.clockValue=testArch.clockValue and " + " test.termination=testArch.termination and " + " test.name=testArch.name and " + " test.version=testArch.version " + ") as commonTests " + "left outer join " + "(select * from TaskData where sessionId in (:sessions)) as taskData " + "on " + "commonTests.sessionId=taskData.sessionId and " + "commonTests.taskId=taskData.taskId " ) .setParameter("sessions", sessionIds) .getResultList(); //group tests by description HashMap<String, TaskDataDto> map = new HashMap<>(list.size()); HashMap<String, Integer> mapIds = new HashMap<>(list.size()); int i = 0; for (Object[] testData : list) { BigInteger id = (BigInteger) testData[0]; String name = (String) testData[1]; String description = (String) testData[2]; String taskId = (String) testData[3]; // we need clock , and termination here is tool of matching test. String clock = (String) testData[4]; Integer clockValue = (Integer) testData[5]; String termination = (String) testData[6]; String sessionId = (String) testData[7]; int taskIdInt = Integer.parseInt(taskId.substring(5)); // key - defines how to match tests when several sessions are selected StringBuilder key = new StringBuilder(255); // uniqueIdParams - is used to generate unique Ids for nodes in control tree depending on session matching strategy List<String> uniqueIdParams = new ArrayList<>(); // Define matching setup Set<SessionMatchingSetup.MatchBy> matchingSetup = sessionMatchingSetup.getMatchingSetup(); if (matchingSetup.isEmpty()) { // no matching at all key.append(i++); uniqueIdParams.add(description); uniqueIdParams.add(name); uniqueIdParams.add(termination); uniqueIdParams.add(clock); uniqueIdParams.add(clockValue.toString()); // sessionId is required to display tests with all equal attributes (description, name, etc) uniqueIdParams.add(sessionId); } else { if (matchingSetup.contains(SessionMatchingSetup.MatchBy.DESCRIPTION) || (matchingSetup.contains(SessionMatchingSetup.MatchBy.ALL))) { key.append(description); uniqueIdParams.add(description); } if (matchingSetup.contains(SessionMatchingSetup.MatchBy.NAME) || (matchingSetup.contains(SessionMatchingSetup.MatchBy.ALL))) { key.append(name); uniqueIdParams.add(name); } if (matchingSetup.contains(SessionMatchingSetup.MatchBy.TERMINATION) || (matchingSetup.contains(SessionMatchingSetup.MatchBy.ALL))) { key.append(termination); uniqueIdParams.add(termination); } if (matchingSetup.contains(SessionMatchingSetup.MatchBy.CLOCK) || (matchingSetup.contains(SessionMatchingSetup.MatchBy.ALL))) { key.append(clock); uniqueIdParams.add(clock); } if (matchingSetup.contains(SessionMatchingSetup.MatchBy.CLOCK_VALUE) || (matchingSetup.contains(SessionMatchingSetup.MatchBy.ALL))) { key.append(clockValue); uniqueIdParams.add(clockValue.toString()); } } // Provide matching if (map.containsKey(key.toString())) { map.get(key.toString()).getIdToSessionId().put(id.longValue(), sessionId); Integer oldValue = mapIds.get(key.toString()); mapIds.put(key.toString(), (oldValue == null ? 0 : oldValue) + taskIdInt); } else { TaskDataDto taskDataDto = new TaskDataDto(id.longValue(), sessionId, name, description); // generate unique id to make difference between tests with different matching parameters. taskDataDto.setUniqueId(CommonUtils.generateUniqueId(uniqueIdParams)); map.put(key.toString(), taskDataDto); mapIds.put(key.toString(), taskIdInt); } } if (map.isEmpty()) { return Collections.EMPTY_LIST; } PriorityQueue<Object[]> priorityQueue = new PriorityQueue<>(mapIds.size(), (o1, o2) -> ((Comparable) o1[0]).compareTo(o2[0])); for (String key : map.keySet()) { TaskDataDto taskDataDto = map.get(key); priorityQueue.add(new Object[]{mapIds.get(key), taskDataDto}); } ArrayList<TaskDataDto> result = new ArrayList<>(priorityQueue.size()); while (!priorityQueue.isEmpty()) { result.add((TaskDataDto) priorityQueue.poll()[1]); } log.info("For sessions {} was loaded {} tasks for {} ms", new Object[]{sessionIds, result.size(), System.currentTimeMillis() - timestamp}); return result; } public boolean checkIfUserCommentStorageAvailable() { try { // even if table is empty we can set user comments entityManager.createQuery("select count(sm) from SessionMetaDataEntity sm").getSingleResult(); return true; } catch (Exception e) { log.warn("Could not access SessionMetaDataTable"); } return false; } public boolean checkIfTagsStorageAvailable() { try { entityManager.createQuery("select 1 from TagEntity").getSingleResult(); return true; } catch (Exception e) { log.warn("Could not access TagEntity table"); } return false; } private List<TaskDataDto> fetchTaskDatas(Set<String> sessionIds, SessionMatchingSetup sessionMatchingSetup) { long temp = System.currentTimeMillis(); List<TaskDataDto> tddos = getTaskDataForSessions(sessionIds, sessionMatchingSetup); log.debug("load tests : {} for summary with {} ms", tddos, System.currentTimeMillis() - temp); return tddos; } private DetailsNode getDetailsNode(final Set<String> sessionIds, final List<TaskDataDto> taskList) { DetailsNode detailsNode = new DetailsNode(NameTokens.CONTROL_METRICS, NameTokens.CONTROL_METRICS); if (taskList.isEmpty()) return detailsNode; List<TestDetailsNode> taskDataDtoList = new ArrayList<>(); MetricGroupNode<PlotNode> sessionScopeNode = null; try { Future<Map<TaskDataDto, List<PlotNode>>> metricsPlotsMapFuture = threadPool.submit( () -> getTestPlotsMap(sessionIds, taskList)); //a first list element is a map with test nodes //a second is a map with nodes for session scope List<Map<TaskDataDto, List<PlotNode>>> maps = separateTestAndSessionScope(metricsPlotsMapFuture.get()); Map<TaskDataDto, List<PlotNode>> map = maps.get(0); Map<TaskDataDto, List<PlotNode>> mapSs = maps.get(1); // get agent names Set<PlotNode> plotNodeList = new HashSet<>(); for (TaskDataDto taskDataDto : map.keySet()) { plotNodeList.addAll(map.get(taskDataDto)); } Map<String, Set<String>> agentNames = getAgentNamesForMonitoringParameters(plotNodeList); //get nodes for session scope and Session Scope Node Set<PlotNode> ssPlotNodes; if (sessionIds.size() == 1) { String sessionId = sessionIds.iterator().next(); ssPlotNodes = getSessionScopeNodes(mapSs, sessionId); if (ssPlotNodes.size() > 0) { String rootIdSs = NameTokens.SESSION_SCOPE_PLOTS; sessionScopeNode = buildTreeAccordingToRules(rootIdSs, agentNames, null, false, new ArrayList<>(ssPlotNodes)); } } // get tree for (TaskDataDto tdd : taskList) { List<PlotNode> metricNodeList = new ArrayList<>(); if (map.containsKey(tdd)) { metricNodeList.addAll(map.get(tdd)); } String rootId = NameTokens.METRICS_PREFIX + tdd.hashCode(); if (metricNodeList.size() > 0) { // apply rules how to build tree MetricGroupNode<PlotNode> testDetailsNodeBase = buildTreeAccordingToRules(rootId, agentNames, null, false, metricNodeList); // full test details node TestDetailsNode testNode = new TestDetailsNode(testDetailsNodeBase); testNode.setTaskDataDto(tdd); taskDataDtoList.add(testNode); } } MetricRankingProvider.sortPlotNodes(taskDataDtoList); if (sessionScopeNode != null) detailsNode.setSessionScopeNode(sessionScopeNode); detailsNode.setTests(taskDataDtoList); return detailsNode; } catch (Exception e) { log.error("Exception occurs while fetching plotNames for sessions {}, and tests {}", sessionIds, taskList); throw new RuntimeException(e); } } private List<TestNode> getSummaryTaskNodeList(List<TaskDataDto> tasks) { List<TestNode> taskDataDtoList = new ArrayList<>(); Map<TaskDataDto, List<MetricNode>> map = getTestMetricsMap(tasks); // get agent names Set<MetricNode> metricNodeListForAgentNames = new HashSet<>(); for (TaskDataDto taskDataDto : map.keySet()) { metricNodeListForAgentNames.addAll(map.get(taskDataDto)); } Map<String, Set<String>> agentNames = getAgentNamesForMonitoringParameters(metricNodeListForAgentNames); for (TaskDataDto tdd : map.keySet()) { List<MetricNode> metricNodeList = map.get(tdd); String rootId = NameTokens.SUMMARY_PREFIX + tdd.hashCode(); Set<Double> percentiles = getPercentileValuesFromIds(metricNodeList); if (metricNodeList.size() > 0) { // apply rules how to build tree MetricGroupNode<MetricNode> testNodeBase = buildTreeAccordingToRules(rootId, agentNames, percentiles, true, metricNodeList); // full test node with info data TestNode testNode = new TestNode(testNodeBase); testNode.setTaskDataDto(tdd); TestInfoNode tin = new TestInfoNode(NameTokens.TEST_INFO + testNode.getId(), NameTokens.TEST_INFO); testNode.setTestInfo(tin); taskDataDtoList.add(testNode); } } MetricRankingProvider.sortPlotNodes(taskDataDtoList); return taskDataDtoList; } private class SummaryNodeFetcherThread implements Callable<SummaryNode> { private List<TaskDataDto> taskList; SummaryNodeFetcherThread(List<TaskDataDto> taskList) { this.taskList = taskList; } public SummaryNode call() { SummaryNode sn = new SummaryNode(NameTokens.CONTROL_SUMMARY_TRENDS, NameTokens.CONTROL_SUMMARY_TRENDS); SessionInfoNode sin = new SessionInfoNode(NameTokens.SESSION_INFO, NameTokens.SESSION_INFO); sn.setSessionInfo(sin); if (!taskList.isEmpty()) { sn.setTests(getSummaryTaskNodeList(taskList)); } return sn; } } private class DetailsNodeFetcherThread implements Callable<DetailsNode> { private Set<String> sessionIds; private List<TaskDataDto> taskList; DetailsNodeFetcherThread(Set<String> sessionIds, List<TaskDataDto> taskList) { this.sessionIds = sessionIds; this.taskList = taskList; } public DetailsNode call() { return getDetailsNode(sessionIds, taskList); } } private Map<String, Set<String>> getAgentNamesForMonitoringParameters(Set<? extends MetricNode> nodeList) { Map<String, Set<String>> agentNames = new HashMap<>(); for (MetricNode node : nodeList) { node.getMetricNameDtoList().stream() .filter(metricNameDto -> metricNameDto.getOrigin() == TEST_GROUP_METRIC) .map(metricNameDto -> MonitoringIdUtils.splitMonitoringMetricId(metricNameDto.getMetricName())) .filter(Objects::nonNull) .forEach(monitoringId -> defaultMonitoringParams.keySet().stream() .filter(key -> defaultMonitoringParams.get(key).contains(monitoringId.getMonitoringName())) .forEach(key -> { agentNames.putIfAbsent(key, new HashSet<>()); agentNames.get(key).add(monitoringId.getAgentName()); })); } return agentNames; } private Set<Double> getPercentileValuesFromIds(List<? extends MetricNode> nodeList) { Set<Double> percentiles = new HashSet<>(); for (MetricNode mn : nodeList) { mn.getMetricNameDtoList().stream() .filter(mnd -> mnd.getMetricName().matches(StandardMetricsNamesUtil.LATENCY_PERCENTILE_ID_REGEX)) .forEach(mnd -> { Double percentileKey = StandardMetricsNamesUtil.parseLatencyPercentileKey(mnd.getMetricName()); percentiles.add(percentileKey); }); } return percentiles; } /** * Build Tree of nodes according to rules * * @param rootId id of root Node * @param agentNames map of monitoring parameter -> agent names (null if not required) * @param percentiles list of percentiles (null if not required) * @param forSummary tells what node we are building now @n * true for Summary&Trends tab view - we show standard metrics as separate metric nodes @n * false for Metrics tab view - we group metrics (metricnameDto) to single metric node (example Latency, LatencyStdDev -> * Latency) @n * @param metricNodeList list of nodes to build tree * @param <M> Node type that extends MetricNode * @return Tree of nodes */ private <M extends MetricNode> MetricGroupNode<M> buildTreeAccordingToRules(String rootId, Map<String, Set<String>> agentNames, Set<Double> percentiles, boolean forSummary, List<M> metricNodeList) { // rules to unite metrics in single plot TreeViewGroupMetricsToNodeRule unitedMetricsRule = treeViewGroupMetricsToNodeRuleProvider.provide( agentNames, percentiles, forSummary ); // unite metrics and add result to original list List<M> unitedMetrics = unitedMetricsRule.filter(rootId, metricNodeList); if (unitedMetrics != null) { metricNodeList.addAll(unitedMetrics); } Map<String, String> scenarioComponentsIdToDisplayName = new HashMap<>(); metricNodeList.stream() .filter(metricNode -> StandardMetricsNamesUtil.isBelongingToScenario(metricNode.getId())) .forEach(metricNode -> { MetricNameDto metricNameDto = metricNode.getMetricNameDtoList().get(0); scenarioComponentsIdToDisplayName.put(metricNameDto.getMetricName(), metricNameDto.getMetricDisplayName()); }); // rules to create test tree view TreeViewGroupRule groupedNodesRule = treeViewGroupRuleProvider.provide(rootId, rootId, scenarioComponentsIdToDisplayName); // tree with metrics distributed by groups return groupedNodesRule.filter(null, metricNodeList); } @Override public Map<TaskDataDto, Map<String, TestInfoDto>> getTestInfoByTaskDataDto(Collection<TaskDataDto> taskDataDtos) throws RuntimeException { if (taskDataDtos.isEmpty()) { return Collections.emptyMap(); } long temp = System.currentTimeMillis(); Set<Long> taskDataIds = new HashSet<>(); for (TaskDataDto taskDataDto : taskDataDtos) { taskDataIds.addAll(taskDataDto.getIds()); } Map<Long, Map<String, TestInfoDto>> preliminaryResult = getTestInfoByTaskIds(taskDataIds); Map<TaskDataDto, Map<String, TestInfoDto>> resultMap = new HashMap<>(taskDataDtos.size()); for (Map.Entry<Long, Map<String, TestInfoDto>> entry : preliminaryResult.entrySet()) { for (TaskDataDto td : taskDataDtos) { if (td.getIds().contains(entry.getKey())) { if (!resultMap.containsKey(td)) { resultMap.put(td, new HashMap<>()); } resultMap.get(td).putAll(entry.getValue()); break; } } } log.debug("Time spent for testInfo fetching for {} taskDataDtos : {}ms", taskDataDtos.size(), System.currentTimeMillis() - temp); return resultMap; } @Override public Map<Long, Map<String, TestInfoDto>> getTestInfoByTaskIds(Set<Long> taskIds) throws RuntimeException { return fetchUtil.getTestInfoByTaskIds(taskIds); } @Override public SessionInfoProvider getSessionInfoService() { return sessionInfoServiceImpl; } @Override public List<NodeInfoPerSessionDto> getNodeInfo(Set<String> sessionIds) { Long time = System.currentTimeMillis(); List<NodeInfoPerSessionDto> nodeInfoPerSessionDtoList = new ArrayList<>(); try { List<NodeInfoEntity> nodeInfoEntityList = (List<NodeInfoEntity>) entityManager.createQuery("select nie from NodeInfoEntity as nie where nie.sessionId in (:sessionIds)") .setParameter("sessionIds", new ArrayList<>(sessionIds)) .getResultList(); Map<String, List<NodeInfoDto>> sessions = new HashMap<>(); for (NodeInfoEntity nodeInfoEntity : nodeInfoEntityList) { Map<String, String> parameters = new HashMap<>(); parameters.put("CPU model", nodeInfoEntity.getCpuModel()); parameters.put("CPU frequency, MHz", String.valueOf(nodeInfoEntity.getCpuMHz())); parameters.put("CPU number of cores", String.valueOf(nodeInfoEntity.getCpuTotalCores())); parameters.put("CPU number of sockets", String.valueOf(nodeInfoEntity.getCpuTotalSockets())); parameters.put("Jagger Java version", nodeInfoEntity.getJaggerJavaVersion()); parameters.put("OS name", nodeInfoEntity.getOsName()); parameters.put("OS version", nodeInfoEntity.getOsVersion()); parameters.put("System RAM, MB", String.valueOf(nodeInfoEntity.getSystemRAM())); List<NodePropertyEntity> nodePropertyEntityList = nodeInfoEntity.getProperties(); for (NodePropertyEntity nodePropertyEntity : nodePropertyEntityList) { parameters.put("Property '" + nodePropertyEntity.getName() + "'", nodePropertyEntity.getValue()); } NodeInfoDto nodeInfoDto = new NodeInfoDto(nodeInfoEntity.getNodeId(), parameters); String sessionId = nodeInfoEntity.getSessionId(); if (sessions.containsKey(sessionId)) { sessions.get(sessionId).add(nodeInfoDto); } else { List<NodeInfoDto> node = new ArrayList<>(); node.add(nodeInfoDto); sessions.put(sessionId, node); } } nodeInfoPerSessionDtoList.addAll(sessions.entrySet().stream() .map(session -> new NodeInfoPerSessionDto(session.getKey(), session.getValue())).collect(toList())); log.info("For session ids " + sessionIds + " were found node info values in " + (System.currentTimeMillis() - time) + " ms"); } catch (PersistenceException ex) { log.info("No node info data was found for session id " + sessionIds, ex); } catch (Exception ex) { log.error("Error occurred during loading node info data for session ids " + sessionIds, ex); throw new RuntimeException("Error occurred during loading node info data for session ids " + sessionIds, ex); } return nodeInfoPerSessionDtoList; } @Override public List<String> getSessionIdsByTaskIds(Set<Long> taskIds) { return fetchUtil.getSessionIdsByTaskIds(taskIds); } @Override public Map<Long, Set<Long>> getTestGroupIdsByTestIds(Set<Long> taskIds) { Map<Long, Set<Long>> result = new HashMap<>(); Multimap<Long, Long> tempResult = fetchUtil.getTestGroupIdsByTestIds(taskIds); for (Long testGroupId : tempResult.keySet()) { result.put(testGroupId, new HashSet<>(tempResult.get(testGroupId))); } return result; } @Override public Set<TaskDecisionDto> getDecisionsPerTask(Set<Long> taskIds) { if (taskIds.isEmpty()) { return Collections.emptySet(); } Long time = System.currentTimeMillis(); Set<TaskDecisionDto> taskDecisionDtoSet = new HashSet<>(); try { List<DecisionPerTaskEntity> decisionPerTaskEntityList = (List<DecisionPerTaskEntity>) entityManager.createQuery("select dpt from DecisionPerTaskEntity as dpt where dpt.taskData.id in (:taskIds)") .setParameter("taskIds", taskIds) .getResultList(); for (DecisionPerTaskEntity decisionPerTaskEntity : decisionPerTaskEntityList) { TaskDecisionDto taskDecisionDto = new TaskDecisionDto(); taskDecisionDto.setId(decisionPerTaskEntity.getTaskData().getId()); taskDecisionDto.setName(decisionPerTaskEntity.getTaskData().getTaskName()); taskDecisionDto.setDecision(Decision.valueOf(decisionPerTaskEntity.getDecision())); taskDecisionDtoSet.add(taskDecisionDto); } log.debug("For task ids " + taskIds + " were found decisions in " + (System.currentTimeMillis() - time) + " ms"); } catch (NoResultException ex) { log.debug("No decisions were found for task ids " + taskIds, ex); return Collections.emptySet(); } catch (PersistenceException ex) { log.debug("No decisions were found for task ids " + taskIds, ex); return Collections.emptySet(); } catch (Exception ex) { log.error("Error occurred during loading decisions for task ids " + taskIds, ex); throw new RuntimeException("Error occurred during loading decisions for task ids " + taskIds, ex); } return taskDecisionDtoSet; } @Override public Map<MetricNameDto, Map<String, Decision>> getDecisionsPerMetric(Set<MetricNameDto> metricNames) { if (metricNames.isEmpty()) { return Collections.emptyMap(); } Long time = System.currentTimeMillis(); Map<MetricNameDto, Map<String, Decision>> result = new HashMap<>(); Set<String> metricIds = new HashSet<>(); Set<Long> taskIds = new HashSet<>(); Set<Long> taskIdsWhereParentIdIsRequired = new HashSet<>(); for (MetricNameDto metricName : metricNames) { metricIds.add(metricName.getMetricName()); taskIds.addAll(metricName.getTaskIds()); if (metricName.getOrigin().equals(TEST_GROUP_METRIC)) { taskIdsWhereParentIdIsRequired.addAll(metricName.getTaskIds()); } } // add test group task ids when necessary Multimap<Long, Long> testGroupPerTest = null; if (!taskIdsWhereParentIdIsRequired.isEmpty()) { testGroupPerTest = fetchUtil.getTestGroupIdsByTestIds(taskIdsWhereParentIdIsRequired); taskIds.addAll(testGroupPerTest.keySet()); } try { List<DecisionPerMetricEntity> decisionPerMetricEntityList = (List<DecisionPerMetricEntity>) entityManager.createQuery("select dpm from DecisionPerMetricEntity as dpm" + " where dpm.metricDescriptionEntity.taskData.id in (:taskIds) and dpm.metricDescriptionEntity.metricId in (:metricIds)") .setParameter("taskIds", taskIds) .setParameter("metricIds", metricIds) .getResultList(); Map<Long, Map<String, MetricNameDto>> mappedMetricDtos = MetricNameUtil.getMappedMetricDtos(metricNames); for (DecisionPerMetricEntity decisionPerMetricEntity : decisionPerMetricEntityList) { Set<Long> taskIdsForEntity = new HashSet<>(); Long taskId = decisionPerMetricEntity.getMetricDescriptionEntity().getTaskData().getId(); String sessionId = decisionPerMetricEntity.getMetricDescriptionEntity().getTaskData().getSessionId(); String metricId = decisionPerMetricEntity.getMetricDescriptionEntity().getMetricId(); if ((testGroupPerTest != null) && (testGroupPerTest.containsKey(taskId))) { // this is test group task id => we will use tests from this test group taskIdsForEntity.addAll(testGroupPerTest.get(taskId)); } else { taskIdsForEntity.add(taskId); } for (Long testTaskId : taskIdsForEntity) { MetricNameDto metricNameDto; try { metricNameDto = mappedMetricDtos.get(testTaskId).get(metricId); if (metricNameDto == null) { // means that we fetched data that we had not wanted to fetch continue; } } catch (NullPointerException e) { throw new IllegalArgumentException("Could not find appropriate MetricDto with taskId: " + testTaskId + ", metricId: " + metricId); } if (!result.containsKey(metricNameDto)) { result.put(metricNameDto, new HashMap<>()); } result.get(metricNameDto).put(sessionId, Decision.valueOf(decisionPerMetricEntity.getDecision())); } } log.debug("For metrics " + metricNames + " were found decisions in " + (System.currentTimeMillis() - time) + " ms"); } catch (NoResultException ex) { log.debug("No decisions were found for metrics " + metricNames, ex); return Collections.emptyMap(); } catch (PersistenceException ex) { log.debug("No decisions were found for metrics " + metricNames, ex); return Collections.emptyMap(); } catch (Exception ex) { log.error("Error occurred during loading decisions for metrics " + metricNames, ex); throw new RuntimeException("Error occurred during loading decisions for metrics " + metricNames, ex); } return result; } @Override public Map<String, Decision> getDecisionsPerSession(Set<String> sessionIds) { if (sessionIds.isEmpty()) { return Collections.emptyMap(); } Long time = System.currentTimeMillis(); Map<String, Decision> result = new HashMap<>(); try { List<DecisionPerSessionEntity> decisionPerSessionEntityList = (List<DecisionPerSessionEntity>) entityManager.createQuery("select dps from DecisionPerSessionEntity as dps" + " where dps.sessionId in (:sessionIds)") .setParameter("sessionIds", sessionIds) .getResultList(); for (DecisionPerSessionEntity decisionPerSessionEntity : decisionPerSessionEntityList) { result.put(decisionPerSessionEntity.getSessionId(), Decision.valueOf(decisionPerSessionEntity.getDecision())); } log.debug("For session ids " + sessionIds + " were found decisions in " + (System.currentTimeMillis() - time) + " ms"); } catch (NoResultException ex) { log.debug("No decisions were found for session ids " + sessionIds, ex); return Collections.emptyMap(); } catch (PersistenceException ex) { log.debug("No decisions were found for session ids " + sessionIds, ex); return Collections.emptyMap(); } catch (Exception ex) { log.error("Error occurred during loading decisions for session ids " + sessionIds, ex); throw new RuntimeException("Error occurred during loading decisions for session ids " + sessionIds, ex); } return result; } @Override public DecisionPerSessionDto getDecisionPerSession(String sessionId) { DecisionPerSessionDto decisionPerSessionDto = new DecisionPerSessionDto((DecisionPerSessionEntity) entityManager.createQuery( "select dps from DecisionPerSessionEntity as dps where dps.sessionId = :sessionId") .setParameter("sessionId", sessionId) .getSingleResult()); List<DecisionPerTaskEntity> taskDecisions = (List<DecisionPerTaskEntity>) entityManager.createQuery("select dpt from DecisionPerTaskEntity as dpt where dpt.taskData.sessionId = :sessionId") .setParameter("sessionId", sessionId).getResultList(); if (!CollectionUtils.isEmpty(taskDecisions)) { decisionPerSessionDto.setTestGroupDecisions(getDecisionPerTestGroup(taskDecisions)); } return decisionPerSessionDto; } private List<DecisionPerTestGroupDto> getDecisionPerTestGroup(List<DecisionPerTaskEntity> taskDecisions) { Set<Long> taskIds = taskDecisions.stream().map(decision -> decision.getTaskData().getId()).collect(Collectors.toSet()); Map<Long, Set<Long>> testIdsByTestGroupIds = getTestGroupIdsByTestIds(taskIds); List<DecisionPerTestGroupDto> decisionPerTestGroupDtos = new ArrayList<>(); List<DecisionPerTestDto> decisionPerTestDtos = new ArrayList<>(); for (DecisionPerTaskEntity taskDecision : taskDecisions) { // get metric decisions for task List<DecisionPerMetricEntity> metricDecisions = (List<DecisionPerMetricEntity>) entityManager.createQuery( "select dpm from DecisionPerMetricEntity as dpm where dpm.metricDescriptionEntity.taskData.id = :taskId") .setParameter("taskId", taskDecision.getTaskData().getId()) .getResultList(); List<DecisionPerMetricDto> decisionPerMetricDtos = metricDecisions.stream().map(DecisionPerMetricDto::new).collect(toList()); // if task is test group - create new DecisionPerTestGroupDto and add it to list if (testIdsByTestGroupIds.containsKey(taskDecision.getTaskData().getId())) { DecisionPerTestGroupDto decisionPerTestGroupDto = new DecisionPerTestGroupDto(taskDecision); decisionPerTestGroupDto.setMetricDecisions(decisionPerMetricDtos); decisionPerTestGroupDtos.add(decisionPerTestGroupDto); } else { // otherwise create DecisionPerTestDto and add it to list DecisionPerTestDto decisionPerTestDto = new DecisionPerTestDto(taskDecision); decisionPerTestDto.setMetricDecisions(decisionPerMetricDtos); decisionPerTestDtos.add(decisionPerTestDto); } } // fill test group decisions with task decisions for (Map.Entry<Long, Set<Long>> entry : testIdsByTestGroupIds.entrySet()) { Long testGroupId = entry.getKey(); Set<Long> tasks = entry.getValue(); DecisionPerTestGroupDto testGroupDecision = decisionPerTestGroupDtos .stream().filter(decision -> decision.getTaskData().getId().equals(testGroupId)).findFirst().get(); List<DecisionPerTestDto> testGroupTestDecisions = decisionPerTestDtos .stream().filter(decision -> tasks.contains(decision.getTaskData().getId())).collect(toList()); testGroupDecision.setTestDecisions(testGroupTestDecisions); } return decisionPerTestGroupDtos; } @Override public List<DecisionPerSessionDto> getAllDecisions() { List<String> sessions = (List<String>) entityManager.createQuery("select dps.sessionId from DecisionPerSessionEntity as dps") .getResultList(); return sessions.stream().map(this::getDecisionPerSession).collect(toList()); } @Override public TaskData getTaskData(String taskId, String sessionId) { return fetchUtil.getTaskData(taskId, sessionId); } @Override public Map<Long, TaskData> getTaskData(Collection<Long> ids) { return fetchUtil.getTaskData(ids); } private Set<PlotNode> getSessionScopeNodes(Map<TaskDataDto, List<PlotNode>> mapAfterFiltration, String sessionId) { List<String> metricNameList = new ArrayList<>(); Map<String, List<Long>> nameId = new HashMap<>(); Set<PlotNode> ssPlotNodes = new HashSet<>(); for (TaskDataDto taskDataDto : mapAfterFiltration.keySet()) { for (PlotNode plotNode : mapAfterFiltration.get(taskDataDto)) { for (MetricNameDto metricNameDto : plotNode.getMetricNameDtoList()) { // we want to have every metric only one time if (!metricNameList.contains(metricNameDto.getMetricName())) { metricNameList.add(metricNameDto.getMetricName()); PlotNode ssPlotNode = new PlotNode(); TaskDataDto tempTaskDataDto = new TaskDataDto(taskDataDto.getIdToSessionId(), taskDataDto.getTaskName(), taskDataDto.getDescription()); MetricNameDto tempMetricNameDto = new MetricNameDto(tempTaskDataDto, metricNameDto.getMetricName(), metricNameDto.getMetricDisplayName(), metricNameDto.getOrigin()); ssPlotNode.init(NameTokens.SESSION_SCOPE_PREFIX + metricNameDto.getMetricName(), plotNode.getDisplayName(), Collections.singletonList(tempMetricNameDto)); ssPlotNodes.add(ssPlotNode); } //we looking for all Id of TaskDataDto for every MetricNameDto if (!nameId.containsKey(metricNameDto.getMetricName())) nameId.put(metricNameDto.getMetricName(), new ArrayList<>()); nameId.get(metricNameDto.getMetricName()).addAll(metricNameDto.getTaskIds()); } } } for (PlotNode plotNode : ssPlotNodes) for (MetricNameDto metricNameDto : plotNode.getMetricNameDtoList()) for (Long taskId : nameId.get(metricNameDto.getMetricName())) metricNameDto.getTest().getIdToSessionId().put(taskId, sessionId); return ssPlotNodes; } private List<Map<TaskDataDto, List<PlotNode>>> separateTestAndSessionScope(Map<TaskDataDto, List<PlotNode>> map) { Map<TaskDataDto, List<PlotNode>> mapForTests = new HashMap<>(); Map<TaskDataDto, List<PlotNode>> mapForSessionScope = new HashMap<>(); for (TaskDataDto taskDataDto : map.keySet()) { for (PlotNode plotNode : map.get(taskDataDto)) { for (MetricNameDto metricNameDto : plotNode.getMetricNameDtoList()) { if (isSessionScopeMetric(metricNameDto)) { mapForSessionScope.putIfAbsent(taskDataDto, new ArrayList<>()); mapForSessionScope.get(taskDataDto).add(plotNode); } else { mapForTests.putIfAbsent(taskDataDto, new ArrayList<>()); mapForTests.get(taskDataDto).add(plotNode); } } } } return newArrayList(mapForTests, mapForSessionScope); } private boolean isSessionScopeMetric(MetricNameDto metricNameDto) { return metricNameDto.getOrigin() == MetricNameDto.Origin.SESSION_SCOPE_TG; } }