blob: 5dc8c6e35d2816394a760da07befd344c8bbf10c [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.vts.servlet;
import com.android.vts.entity.ProfilingPointEntity;
import com.android.vts.entity.ProfilingPointSummaryEntity;
import com.android.vts.util.BoxPlot;
import com.android.vts.util.DatastoreHelper;
import com.android.vts.util.FilterUtil;
import com.android.vts.util.GraphSerializer;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Servlet for handling requests to load graphs. */
public class ShowProfilingOverviewServlet extends BaseServlet {
private static final String PROFILING_OVERVIEW_JSP = "WEB-INF/jsp/show_profiling_overview.jsp";
@Override
public PageType getNavParentType() {
return PageType.PROFILING_LIST;
}
@Override
public List<Page> getBreadcrumbLinks(HttpServletRequest request) {
List<Page> links = new ArrayList<>();
String testName = request.getParameter("testName");
links.add(new Page(PageType.PROFILING_OVERVIEW, testName, "?testName=" + testName));
return links;
}
@Override
public void doGetHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException {
RequestDispatcher dispatcher = null;
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
String testName = request.getParameter("testName");
long endTime = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
long startTime = endTime - TimeUnit.DAYS.toMicros(30);
// Create a query for test runs matching the time window filter
Map<String, String[]> parameterMap = request.getParameterMap();
boolean hasBranchFilter = parameterMap.containsKey(FilterUtil.FilterKey.BRANCH.getValue());
Filter deviceFilter;
if (hasBranchFilter) {
deviceFilter =
FilterUtil.FilterKey.BRANCH.getFilterForString(
FilterUtil.getFirstParameter(
parameterMap, FilterUtil.FilterKey.BRANCH.getValue()));
} else {
deviceFilter =
FilterUtil.FilterKey.BRANCH.getFilterForString(ProfilingPointSummaryEntity.ALL);
}
boolean hasTargetFilter = parameterMap.containsKey(FilterUtil.FilterKey.TARGET.getValue());
if (hasTargetFilter) {
deviceFilter =
Query.CompositeFilterOperator.and(
deviceFilter,
FilterUtil.FilterKey.TARGET.getFilterForString(
FilterUtil.getFirstParameter(
parameterMap, FilterUtil.FilterKey.TARGET.getValue())));
} else {
deviceFilter =
Query.CompositeFilterOperator.and(
deviceFilter,
FilterUtil.FilterKey.TARGET.getFilterForString(
ProfilingPointSummaryEntity.ALL));
}
Filter startFilter =
new Query.FilterPredicate(
ProfilingPointSummaryEntity.START_TIME,
Query.FilterOperator.GREATER_THAN_OR_EQUAL,
startTime);
Filter endFilter =
new Query.FilterPredicate(
ProfilingPointSummaryEntity.START_TIME,
Query.FilterOperator.LESS_THAN_OR_EQUAL,
endTime);
Filter timeFilter = Query.CompositeFilterOperator.and(startFilter, endFilter);
Filter filter = Query.CompositeFilterOperator.and(timeFilter, deviceFilter);
Query profilingPointQuery =
new Query(ProfilingPointEntity.KIND)
.setFilter(
new Query.FilterPredicate(
ProfilingPointEntity.TEST_NAME,
Query.FilterOperator.EQUAL,
testName));
List<ProfilingPointEntity> profilingPoints = new ArrayList<>();
for (Entity e :
datastore
.prepare(profilingPointQuery)
.asIterable(DatastoreHelper.getLargeBatchOptions())) {
ProfilingPointEntity pp = ProfilingPointEntity.fromEntity(e);
if (pp == null) continue;
profilingPoints.add(pp);
}
Map<ProfilingPointEntity, Iterable<Entity>> asyncEntities = new HashMap<>();
for (ProfilingPointEntity pp : profilingPoints) {
Query profilingQuery =
new Query(ProfilingPointSummaryEntity.KIND)
.setAncestor(pp.getKey())
.setFilter(filter);
asyncEntities.put(
pp,
datastore
.prepare(profilingQuery)
.asIterable(DatastoreHelper.getLargeBatchOptions()));
}
Map<String, BoxPlot> plotMap = new HashMap<>();
for (ProfilingPointEntity pp : profilingPoints) {
if (!plotMap.containsKey(pp.getProfilingPointName())) {
plotMap.put(
pp.getProfilingPointName(), new BoxPlot(pp.getProfilingPointName(), null, pp.getXLabel()));
}
BoxPlot plot = plotMap.get(pp.getProfilingPointName());
Set<Long> timestamps = new HashSet<>();
for (Entity e : asyncEntities.get(pp)) {
ProfilingPointSummaryEntity pps = ProfilingPointSummaryEntity.fromEntity(e);
if (pps == null) continue;
plot.addSeriesData(Long.toString(pps.getStartTime()), pps.getSeries(), pps.getGlobalStats());
timestamps.add(pps.getStartTime());
}
List<Long> timestampList = new ArrayList<>(timestamps);
timestampList.sort(Comparator.reverseOrder());
List<String> timestampStrings =
timestampList.stream().map(Object::toString).collect(Collectors.toList());
plot.setLabels(timestampStrings);
}
List<BoxPlot> plots = new ArrayList<>();
for (String key : plotMap.keySet()) {
BoxPlot plot = plotMap.get(key);
if (plot.size() == 0) continue;
plots.add(plot);
}
plots.sort((b1, b2) -> b1.getName().compareTo(b2.getName()));
Gson gson =
new GsonBuilder()
.registerTypeHierarchyAdapter(BoxPlot.class, new GraphSerializer())
.create();
FilterUtil.setAttributes(request, parameterMap);
request.setAttribute("plots", gson.toJson(plots));
request.setAttribute("testName", request.getParameter("testName"));
request.setAttribute("branches", new Gson().toJson(DatastoreHelper.getAllBranches()));
request.setAttribute("devices", new Gson().toJson(DatastoreHelper.getAllBuildFlavors()));
dispatcher = request.getRequestDispatcher(PROFILING_OVERVIEW_JSP);
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
logger.log(Level.SEVERE, "Servlet Exception caught : ", e);
}
}
}