summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Campbell <ryanjcampbell@google.com>2017-07-17 17:23:11 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-07-17 17:23:11 +0000
commit2b532bee21a2b3318435ae55928a769e6f2a3df7 (patch)
treee76b48a424d523884921e273e2f1765c473495a5
parentad3b6e33d9ca954c7d9c9029653325d01722409f (diff)
parent1c1fda4205799fd97452da3b0d9c0d3b21ec1fb0 (diff)
downloaddashboard-2b532bee21a2b3318435ae55928a769e6f2a3df7.tar.gz
Merge changes from topic 'profiling analysis'
* changes: Create profiling tab/entry point. Update test entities to indicate profiling data.
-rw-r--r--src/main/java/com/android/vts/entity/TestEntity.java50
-rw-r--r--src/main/java/com/android/vts/servlet/BaseServlet.java10
-rw-r--r--src/main/java/com/android/vts/servlet/ShowPerformanceDigestServlet.java2
-rw-r--r--src/main/java/com/android/vts/servlet/ShowProfilingListServlet.java76
-rw-r--r--src/main/java/com/android/vts/servlet/ShowProfilingOverviewServlet.java6
-rw-r--r--src/main/java/com/android/vts/util/DatastoreHelper.java23
-rw-r--r--src/main/webapp/WEB-INF/jsp/show_profiling_list.jsp44
-rw-r--r--src/main/webapp/WEB-INF/web.xml10
8 files changed, 202 insertions, 19 deletions
diff --git a/src/main/java/com/android/vts/entity/TestEntity.java b/src/main/java/com/android/vts/entity/TestEntity.java
index bbba6c6..9a8d32a 100644
--- a/src/main/java/com/android/vts/entity/TestEntity.java
+++ b/src/main/java/com/android/vts/entity/TestEntity.java
@@ -17,6 +17,8 @@
package com.android.vts.entity;
import com.google.appengine.api.datastore.Entity;
+import com.google.appengine.api.datastore.Key;
+import com.google.appengine.api.datastore.KeyFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -25,25 +27,61 @@ public class TestEntity implements DashboardEntity {
protected static final Logger logger = Logger.getLogger(TestEntity.class.getName());
public static final String KIND = "Test";
+ public static final String HAS_PROFILING_DATA = "hasProfilingData";
public final String testName;
+ public final Key key;
+ public boolean hasProfilingData;
/**
- * Create a TestEntity object with status metadata.
+ * Create a TestEntity object.
*
* @param testName The name of the test.
+ * @param hasProfilingData True if the test includes profiling data.
*/
- public TestEntity(String testName) {
+ public TestEntity(String testName, boolean hasProfilingData) {
this.testName = testName;
+ this.key = KeyFactory.createKey(KIND, testName);
+ this.hasProfilingData = hasProfilingData;
+ }
+
+ /**
+ * Create a TestEntity object.
+ *
+ * @param testName The name of the test.
+ */
+ public TestEntity(String testName) {
+ this(testName, false);
}
@Override
public Entity toEntity() {
- Entity testEntity = new Entity(KIND, this.testName);
+ Entity testEntity = new Entity(this.key);
+ testEntity.setProperty(HAS_PROFILING_DATA, this.hasProfilingData);
return testEntity;
}
/**
+ * Set to true if the test has profiling data.
+ *
+ * @param hasProfilingData The value to store.
+ */
+ public void setHasProfilingData(boolean hasProfilingData) {
+ this.hasProfilingData = hasProfilingData;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !TestEntity.class.isAssignableFrom(obj.getClass())) {
+ return false;
+ }
+ TestEntity test2 = (TestEntity) obj;
+ return (
+ this.testName.equals(test2.testName) &&
+ this.hasProfilingData == test2.hasProfilingData);
+ }
+
+ /**
* Convert an Entity object to a TestEntity.
*
* @param e The entity to process.
@@ -56,6 +94,10 @@ public class TestEntity implements DashboardEntity {
return null;
}
String testName = e.getKey().getName();
- return new TestEntity(testName);
+ boolean hasProfilingData = false;
+ if (e.hasProperty(HAS_PROFILING_DATA)) {
+ hasProfilingData = (boolean) e.getProperty(HAS_PROFILING_DATA);
+ }
+ return new TestEntity(testName, hasProfilingData);
}
}
diff --git a/src/main/java/com/android/vts/servlet/BaseServlet.java b/src/main/java/com/android/vts/servlet/BaseServlet.java
index d24c111..7382846 100644
--- a/src/main/java/com/android/vts/servlet/BaseServlet.java
+++ b/src/main/java/com/android/vts/servlet/BaseServlet.java
@@ -44,13 +44,15 @@ public abstract class BaseServlet extends HttpServlet {
TOT("ToT", "/"),
RELEASE("Release", "/show_release"),
COVERAGE_OVERVIEW("Coverage", "/show_coverage_overview"),
+ PROFILING_LIST("Profiling", "/show_profiling_list"),
TABLE("", "/show_table"),
TREE("", "/show_tree"),
GRAPH("Profiling", "/show_graph"),
COVERAGE("Coverage", "/show_coverage"),
- PERFORMANCE("Performance Digest", "/show_performance_digest"),
+ PERFORMANCE_DIGEST("Performance Digest", "/show_performance_digest"),
PLAN_RELEASE("", "/show_plan_release"),
- PLAN_RUN("Plan Run", "/show_plan_run");
+ PLAN_RUN("Plan Run", "/show_plan_run"),
+ PROFILING_OVERVIEW("", "/show_profiling_overview");
public final String defaultName;
public final String defaultUrl;
@@ -100,6 +102,7 @@ public abstract class BaseServlet extends HttpServlet {
links.add(new Page(PageType.TOT));
links.add(new Page(PageType.RELEASE));
links.add(new Page(PageType.COVERAGE_OVERVIEW));
+ links.add(new Page(PageType.PROFILING_LIST));
navbarLinks = links;
}
@@ -130,6 +133,9 @@ public abstract class BaseServlet extends HttpServlet {
int activeIndex;
switch (getNavParentType()) {
+ case PROFILING_LIST:
+ activeIndex = 3;
+ break;
case COVERAGE_OVERVIEW:
activeIndex = 2;
break;
diff --git a/src/main/java/com/android/vts/servlet/ShowPerformanceDigestServlet.java b/src/main/java/com/android/vts/servlet/ShowPerformanceDigestServlet.java
index 51b0127..44afbfa 100644
--- a/src/main/java/com/android/vts/servlet/ShowPerformanceDigestServlet.java
+++ b/src/main/java/com/android/vts/servlet/ShowPerformanceDigestServlet.java
@@ -75,7 +75,7 @@ public class ShowPerformanceDigestServlet extends BaseServlet {
List<Page> links = new ArrayList<>();
String testName = request.getParameter("testName");
links.add(new Page(PageType.TABLE, testName, "?testName=" + testName));
- links.add(new Page(PageType.PERFORMANCE, "?testName=" + testName));
+ links.add(new Page(PageType.PERFORMANCE_DIGEST, "?testName=" + testName));
return links;
}
diff --git a/src/main/java/com/android/vts/servlet/ShowProfilingListServlet.java b/src/main/java/com/android/vts/servlet/ShowProfilingListServlet.java
new file mode 100644
index 0000000..cbebd2c
--- /dev/null
+++ b/src/main/java/com/android/vts/servlet/ShowProfilingListServlet.java
@@ -0,0 +1,76 @@
+/*
+ * 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.TestEntity;
+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 java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/** Servlet for handling requests to display profiling tests. */
+public class ShowProfilingListServlet extends BaseServlet {
+ private static final String PROFILING_LIST_JSP = "WEB-INF/jsp/show_profiling_list.jsp";
+
+ @Override
+ public PageType getNavParentType() {
+ return PageType.PROFILING_LIST;
+ }
+
+ @Override
+ public List<Page> getBreadcrumbLinks(HttpServletRequest request) {
+ return null;
+ }
+
+ @Override
+ public void doGetHandler(HttpServletRequest request, HttpServletResponse response)
+ throws IOException {
+ DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
+ Query.Filter profilingFilter = new Query.FilterPredicate(
+ TestEntity.HAS_PROFILING_DATA, Query.FilterOperator.EQUAL, true);
+ Query query = new Query(TestEntity.KIND)
+ .setFilter(profilingFilter)
+ .setKeysOnly();
+ Set<String> profilingTests = new HashSet<>();
+ for (Entity test : datastore.prepare(query).asIterable()) {
+ profilingTests.add(test.getKey().getName());
+ }
+
+ List<String> tests = new ArrayList<>(profilingTests);
+ tests.sort(Comparator.naturalOrder());
+
+ response.setStatus(HttpServletResponse.SC_OK);
+ request.setAttribute("testNames", tests);
+ RequestDispatcher dispatcher = request.getRequestDispatcher(PROFILING_LIST_JSP);
+ try {
+ dispatcher.forward(request, response);
+ } catch (ServletException e) {
+ logger.log(Level.SEVERE, "Servlet Excpetion caught : ", e);
+ }
+ }
+}
diff --git a/src/main/java/com/android/vts/servlet/ShowProfilingOverviewServlet.java b/src/main/java/com/android/vts/servlet/ShowProfilingOverviewServlet.java
index bb1174e..be830e9 100644
--- a/src/main/java/com/android/vts/servlet/ShowProfilingOverviewServlet.java
+++ b/src/main/java/com/android/vts/servlet/ShowProfilingOverviewServlet.java
@@ -61,16 +61,14 @@ public class ShowProfilingOverviewServlet extends BaseServlet {
@Override
public PageType getNavParentType() {
- return PageType.TOT;
+ 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.TABLE, testName, "?testName=" + testName));
-
- links.add(new Page(PageType.GRAPH, "?testName=" + testName));
+ links.add(new Page(PageType.PROFILING_OVERVIEW, testName, "?testName=" + testName));
return links;
}
diff --git a/src/main/java/com/android/vts/util/DatastoreHelper.java b/src/main/java/com/android/vts/util/DatastoreHelper.java
index b738df7..e38555b 100644
--- a/src/main/java/com/android/vts/util/DatastoreHelper.java
+++ b/src/main/java/com/android/vts/util/DatastoreHelper.java
@@ -202,11 +202,11 @@ public class DatastoreHelper {
String testBuildId = report.getBuildInfo().getId().toStringUtf8();
String hostName = report.getHostInfo().getHostname().toStringUtf8();
- Entity testEntity = new TestEntity(testName).toEntity();
+ TestEntity testEntity = new TestEntity(testName);
Key testRunKey =
KeyFactory.createKey(
- testEntity.getKey(), TestRunEntity.KIND, report.getStartTimestamp());
+ testEntity.key, TestRunEntity.KIND, report.getStartTimestamp());
long passCount = 0;
long failCount = 0;
@@ -250,6 +250,7 @@ public class DatastoreHelper {
logger.log(Level.WARNING, "Invalid profiling report in test run " + testRunKey);
}
puts.add(profilingEntity.toEntity());
+ testEntity.setHasProfilingData(true);
}
int lastIndex = testCases.size() - 1;
@@ -321,6 +322,7 @@ public class DatastoreHelper {
logger.log(Level.WARNING, "Invalid profiling report in test run " + testRunKey);
}
puts.add(profilingEntity.toEntity());
+ testEntity.setHasProfilingData(true);
}
List<String> logLinks = new ArrayList<>();
@@ -332,7 +334,7 @@ public class DatastoreHelper {
TestRunEntity testRunEntity =
new TestRunEntity(
- testEntity.getKey(),
+ testEntity.key,
testRunType,
startTimestamp,
endTimestamp,
@@ -347,14 +349,19 @@ public class DatastoreHelper {
puts.add(testRunEntity.toEntity());
int retries = 0;
+ Entity test = testEntity.toEntity();
while (true) {
Transaction txn = datastore.beginTransaction();
try {
// Check if test already exists in the database
try {
- datastore.get(testEntity.getKey());
+ Entity oldTest = datastore.get(testEntity.key);
+ TestEntity oldTestEntity = TestEntity.fromEntity(oldTest);
+ if (oldTestEntity == null || !oldTestEntity.equals(testEntity)) {
+ puts.add(test);
+ }
} catch (EntityNotFoundException e) {
- puts.add(testEntity);
+ puts.add(test);
}
datastore.put(puts);
txn.commit();
@@ -370,12 +377,12 @@ public class DatastoreHelper {
} catch (ConcurrentModificationException
| DatastoreFailureException
| DatastoreTimeoutException e) {
- puts.remove(testEntity);
- logger.log(Level.WARNING, "Retrying test run insert: " + testEntity.getKey());
+ puts.remove(test);
+ logger.log(Level.WARNING, "Retrying test run insert: " + test.getKey());
if (retries++ >= MAX_WRITE_RETRIES) {
logger.log(
Level.SEVERE,
- "Exceeded maximum test run retries: " + testEntity.getKey());
+ "Exceeded maximum test run retries: " + test.getKey());
throw e;
}
} finally {
diff --git a/src/main/webapp/WEB-INF/jsp/show_profiling_list.jsp b/src/main/webapp/WEB-INF/jsp/show_profiling_list.jsp
new file mode 100644
index 0000000..f1615d7
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/show_profiling_list.jsp
@@ -0,0 +1,44 @@
+<%--
+ ~ 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.
+ --%>
+<%@ page contentType='text/html;charset=UTF-8' language='java' %>
+<%@ taglib prefix='fn' uri='http://java.sun.com/jsp/jstl/functions' %>
+<%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core'%>
+
+<html>
+ <link rel='stylesheet' href='/css/show_release.css'>
+ <%@ include file='header.jsp' %>
+ <body>
+ <div class='container'>
+ <div class='row'>
+ <div class='col s12'>
+ <h4 id='section-header'>Profiling Tests</h4>
+ </div>
+ </div>
+ <div class='row' id='options'>
+ <c:forEach items='${testNames}' var='test'>
+ <div>
+ <a href='/show_profiling_overview?testName=${test}'>
+ <div class='col s12 card hoverable option valign-wrapper waves-effect'>
+ <span class='entry valign'>${test}</span>
+ </div>
+ </a>
+ </div>
+ </c:forEach>
+ </div>
+ </div>
+ <%@ include file='footer.jsp' %>
+ </body>
+</html>
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index ad494e7..0dfec12 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -46,6 +46,11 @@ Copyright 2016 Google Inc. All Rights Reserved.
</servlet>
<servlet>
+ <servlet-name>show_profiling_list</servlet-name>
+ <servlet-class>com.android.vts.servlet.ShowProfilingListServlet</servlet-class>
+</servlet>
+
+<servlet>
<servlet-name>show_profiling_overview</servlet-name>
<servlet-class>com.android.vts.servlet.ShowProfilingOverviewServlet</servlet-class>
</servlet>
@@ -141,6 +146,11 @@ Copyright 2016 Google Inc. All Rights Reserved.
</servlet-mapping>
<servlet-mapping>
+ <servlet-name>show_profiling_list</servlet-name>
+ <url-pattern>/show_profiling_list/*</url-pattern>
+</servlet-mapping>
+
+<servlet-mapping>
<servlet-name>show_profiling_overview</servlet-name>
<url-pattern>/show_profiling_overview/*</url-pattern>
</servlet-mapping>