From 32f814a2cc1def49893ea50d6877270453a119bd Mon Sep 17 00:00:00 2001 From: Bill Oley Date: Tue, 19 Dec 2023 14:06:50 -0500 Subject: [PATCH] Update query-metric service to generate HTML response via Spring MVC --- api/pom.xml | 5 + .../BaseQueryMetricListResponse.java | 166 +----------- .../querymetric/QueryGeometryResponse.java | 69 ++--- .../querymetric/QueryMetricListResponse.java | 166 +++--------- .../querymetric/QueryMetricModel.java | 245 +++++++++++++++++ .../QueryMetricSummaryResponse.java | 183 +++++++++++++ .../QueryMetricsDetailListResponse.java | 251 ------------------ .../QueryMetricsSummaryResponse.java | 212 --------------- .../main/resources/static/css/queryMap.css | 0 api/src/main/resources/static/css/theme.css | 8 + .../static/js/query-interactive-parens.js | 9 +- .../src/main/resources/static/js/queryMap.js | 0 .../templates/querymetric-horizontal.html | 152 +++++++++++ .../main/resources/templates/querymetric.html | 134 ++++++++++ .../templates/querymetricgeometry.html | 26 ++ .../templates/querymetricsummary.html | 45 ++++ .../querymetricsummaryexceptions.html | 19 ++ service/pom.xml | 4 + .../querymetric/QueryMetricOperations.java | 117 ++++++-- .../BaseQueryMetricListResponseFactory.java | 2 - .../QueryMetricListResponseFactory.java | 6 - .../handler/BaseQueryMetricHandler.java | 8 +- .../handler/QueryMetricHandler.java | 4 +- .../handler/ShardTableQueryMetricHandler.java | 7 +- .../src/main/resources/config/bootstrap.yml | 1 + .../querymetric/QueryMetricTestBase.java | 2 +- 26 files changed, 1001 insertions(+), 840 deletions(-) create mode 100644 api/src/main/java/datawave/microservice/querymetric/QueryMetricModel.java create mode 100644 api/src/main/java/datawave/microservice/querymetric/QueryMetricSummaryResponse.java delete mode 100644 api/src/main/java/datawave/microservice/querymetric/QueryMetricsDetailListResponse.java delete mode 100644 api/src/main/java/datawave/microservice/querymetric/QueryMetricsSummaryResponse.java rename {service => api}/src/main/resources/static/css/queryMap.css (100%) rename {service => api}/src/main/resources/static/js/queryMap.js (100%) create mode 100644 api/src/main/resources/templates/querymetric-horizontal.html create mode 100644 api/src/main/resources/templates/querymetric.html create mode 100644 api/src/main/resources/templates/querymetricgeometry.html create mode 100644 api/src/main/resources/templates/querymetricsummary.html create mode 100644 api/src/main/resources/templates/querymetricsummaryexceptions.html diff --git a/api/pom.xml b/api/pom.xml index 2cd0deeb..763a9054 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -189,6 +189,11 @@ org.slf4j slf4j-api + + org.springframework + spring-webmvc + 5.3.21 + org.junit.jupiter junit-jupiter-engine diff --git a/api/src/main/java/datawave/microservice/querymetric/BaseQueryMetricListResponse.java b/api/src/main/java/datawave/microservice/querymetric/BaseQueryMetricListResponse.java index 809118f5..bb2089de 100644 --- a/api/src/main/java/datawave/microservice/querymetric/BaseQueryMetricListResponse.java +++ b/api/src/main/java/datawave/microservice/querymetric/BaseQueryMetricListResponse.java @@ -1,31 +1,18 @@ package datawave.microservice.querymetric; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.TreeMap; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlTransient; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; +import org.springframework.web.servlet.ModelAndView; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import datawave.microservice.querymetric.BaseQueryMetric.PageMetric; -import datawave.webservice.HtmlProvider; import datawave.webservice.result.BaseResponse; -public abstract class BaseQueryMetricListResponse extends BaseResponse implements HtmlProvider { +public abstract class BaseQueryMetricListResponse extends BaseResponse { private static final long serialVersionUID = 1L; - private static final String TITLE = "Query Metrics"; - private static final String EMPTY = ""; @XmlElementWrapper(name = "queryMetrics") @XmlElement(name = "queryMetric") protected List result = null; @@ -35,22 +22,12 @@ public abstract class BaseQueryMetricListResponse ext protected boolean isGeoQuery = false; @XmlTransient private boolean administratorMode = false; - private String JQUERY_INCLUDES; - protected String BASE_URL = "/DataWave/Query/Metrics"; - - public BaseQueryMetricListResponse() { - setHtmlIncludePaths(new HashMap<>()); - } + protected String basePath = "/DataWave/Query/Metrics"; - public void setHtmlIncludePaths(Map pathMap) { - // @formatter:off - JQUERY_INCLUDES = - "\n"; - // @formatter:on - } + protected String viewName = "querymetric"; - public void setBaseUrl(String baseUrl) { - this.BASE_URL = baseUrl; + public void setBasePath(String basePath) { + this.basePath = basePath; } private static String numToString(long number) { @@ -90,131 +67,12 @@ public void setGeoQuery(boolean geoQuery) { isGeoQuery = geoQuery; } - @JsonIgnore - @XmlTransient - @Override - public String getTitle() { - return TITLE; + public void setViewName(String viewName) { + this.viewName = viewName; } - @JsonIgnore - @XmlTransient - @Override - public String getPageHeader() { - return getTitle(); - } - - @JsonIgnore - @XmlTransient - @Override - public String getHeadContent() { - if (isGeoQuery) { - // @formatter:off - return JQUERY_INCLUDES + - ""; - // @formatter: on - } else { - return EMPTY; - } - } - - @JsonIgnore - @XmlTransient - @Override - public String getMainContent() { - StringBuilder builder = new StringBuilder(); - - builder.append("\n"); - builder.append("\n"); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append("\n\n"); - - TreeMap metricMap = new TreeMap(Collections.reverseOrder()); - - for (T metric : this.getResult()) { - metricMap.put(metric.getCreateDate(), metric); - } - - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HHmmss"); - - int x = 0; - for (T metric : metricMap.values()) { - // highlight alternating rows - if (x % 2 == 0) { - builder.append("\n"); - } else { - builder.append("\n"); - } - x++; - - builder.append(""); - builder.append(""); - builder.append(""); - String userDN = metric.getUserDN(); - builder.append(""); - String proxyServers = metric.getProxyServers() == null ? "" : StringUtils.join(metric.getProxyServers(), "
"); - builder.append(""); - if (this.isAdministratorMode()) { - builder.append(""); - } else { - builder.append(""); - } - builder.append(""); - builder.append(""); - builder.append(""); - - String beginDate = metric.getBeginDate() == null ? "" : sdf.format(metric.getBeginDate()); - builder.append(""); - String endDate = metric.getEndDate() == null ? "" : sdf.format(metric.getEndDate()); - builder.append(""); - String queryAuths = metric.getQueryAuthorizations() == null ? "" : metric.getQueryAuthorizations().replaceAll(",", " "); - builder.append(""); - - builder.append(""); - builder.append(""); - builder.append("\n"); - builder.append(""); - builder.append(""); - long count = 0l; - long callTime = 0l; - long serializationTime = 0l; - long bytesSent = 0l; - for (PageMetric p : metric.getPageTimes()) { - count += p.getReturnTime(); - callTime += (p.getCallTime()) == -1 ? 0 : p.getCallTime(); - serializationTime += (p.getSerializationTime()) == -1 ? 0 : p.getSerializationTime(); - bytesSent += (p.getBytesWritten()) == -1 ? 0 : p.getBytesWritten(); - } - builder.append("\n"); - builder.append("\n"); - builder.append("\n"); - builder.append("\n"); - builder.append(""); - builder.append(""); - String errorCode = metric.getErrorCode(); - builder.append(""); - String errorMessage = metric.getErrorMessage(); - builder.append(""); - - builder.append("\n\n"); - } - - builder.append("
VisibilityQuery DateUserUserDNProxy Server(s)Query IDQuery TypeQuery LogicQueryBegin DateEnd DateQuery AuthsServerQuery Setup Time (ms)Query Setup Call Time (ms)Number PagesNumber ResultsTotal Page Time (ms)Total Page Call Time (ms)Total Page Serialization Time (ms)Total Page Bytes Sent (uncompressed)LifecycleElapsed TimeError CodeError Message
").append(metric.getColumnVisibility()).append("").append(sdf.format(metric.getCreateDate())).append("").append(metric.getUser()).append("").append(userDN == null ? "" : userDN).append("").append(proxyServers).append("").append(metric.getQueryId()).append("").append(metric.getQueryId()) - .append("").append(metric.getQueryType()).append("").append(metric.getQueryLogic()).append("").append(StringEscapeUtils.escapeHtml4(metric.getQuery())).append("").append(beginDate).append("").append(endDate).append("").append(queryAuths).append("").append(metric.getHost()).append("").append(numToString(metric.getSetupTime())).append("").append(numToString(metric.getCreateCallTime())).append("").append(metric.getNumPages()).append("").append(metric.getNumResults()).append("").append(count).append("").append(numToString(callTime)).append("").append(numToString(serializationTime)).append("").append(numToString(bytesSent)).append("").append(metric.getLifecycle()).append("").append(metric.getElapsedTime()).append("").append((errorCode == null) ? "" : StringEscapeUtils.escapeHtml4(errorCode)).append("").append((errorMessage == null) ? "" : StringEscapeUtils.escapeHtml4(errorMessage)) - .append("
\n"); - - return builder.toString(); - } + /** + * @return the ModelAndView for template html page + */ + abstract public ModelAndView createModelAndView(); } diff --git a/api/src/main/java/datawave/microservice/querymetric/QueryGeometryResponse.java b/api/src/main/java/datawave/microservice/querymetric/QueryGeometryResponse.java index 38a57c23..81b62206 100644 --- a/api/src/main/java/datawave/microservice/querymetric/QueryGeometryResponse.java +++ b/api/src/main/java/datawave/microservice/querymetric/QueryGeometryResponse.java @@ -14,9 +14,10 @@ import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; +import org.springframework.web.servlet.ModelAndView; + import com.fasterxml.jackson.annotation.JsonIgnore; -import datawave.webservice.HtmlProvider; import datawave.webservice.result.BaseResponse; /** @@ -25,15 +26,11 @@ @XmlRootElement(name = "QueryGeometry") @XmlAccessorType(XmlAccessType.NONE) @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) -public class QueryGeometryResponse extends BaseResponse implements HtmlProvider { +public class QueryGeometryResponse extends BaseResponse { private static final long serialVersionUID = 1L; - private static final String TITLE = "Query Geometry"; - - private String LEAFLET_INCLUDES; - private String JQUERY_INCLUDES; - private String MAP_INCLUDES; + private Map pathPrefixMap = new HashMap<>(); public QueryGeometryResponse() { this(null, null); @@ -42,20 +39,22 @@ public QueryGeometryResponse() { public QueryGeometryResponse(String queryId, String basemaps) { this.queryId = queryId; this.basemaps = basemaps; - setHtmlIncludePaths(new HashMap<>()); } - public void setHtmlIncludePaths(Map pathMap) { - // @formatter:off - LEAFLET_INCLUDES = - "\n" + - "\n"; - JQUERY_INCLUDES = - "\n"; - MAP_INCLUDES = - "\n" + - ""; - // @formatter:on + public void setPathPrefixMap(Map pathPrefixMap) { + this.pathPrefixMap = pathPrefixMap; + } + + public ModelAndView createModelAndView() { + ModelAndView mav = new ModelAndView(); + mav.setViewName("querymetricgeometry"); + mav.addObject("basemapScript", "var basemaps = " + this.basemaps + ";"); + mav.addObject("geoJsonFeaturesScript", "var features = " + toGeoJsonFeatures() + ";"); + mav.addObject("jqueryPrefix", this.pathPrefixMap.getOrDefault("jquery", "")); + mav.addObject("leafletPrefix", this.pathPrefixMap.getOrDefault("leaflet", "")); + mav.addObject("cssPrefix", this.pathPrefixMap.getOrDefault("css", "")); + mav.addObject("jsPrefix", this.pathPrefixMap.getOrDefault("js", "")); + return mav; } @XmlElement(name = "queryId", nillable = true) @@ -69,38 +68,6 @@ public void setHtmlIncludePaths(Map pathMap) { @XmlElement(name = "feature") protected List result = null; - @JsonIgnore - @XmlTransient - @Override - public String getTitle() { - if (queryId != null) - return TITLE + " - " + queryId; - return TITLE; - } - - @JsonIgnore - @XmlTransient - @Override - public String getHeadContent() { - String basemapData = "\n"; - String featureData = "\n"; - return String.join("\n", featureData, JQUERY_INCLUDES, LEAFLET_INCLUDES, basemapData, MAP_INCLUDES); - } - - @JsonIgnore - @XmlTransient - @Override - public String getPageHeader() { - return getTitle(); - } - - @JsonIgnore - @XmlTransient - @Override - public String getMainContent() { - return "
"; - } - private String toGeoJsonFeatures() { if (!this.result.isEmpty()) return "[ " + this.result.stream().map(QueryGeometry::toGeoJsonFeature).collect(Collectors.joining(", ")) + " ]"; diff --git a/api/src/main/java/datawave/microservice/querymetric/QueryMetricListResponse.java b/api/src/main/java/datawave/microservice/querymetric/QueryMetricListResponse.java index a4b8ff24..1330a7ae 100644 --- a/api/src/main/java/datawave/microservice/querymetric/QueryMetricListResponse.java +++ b/api/src/main/java/datawave/microservice/querymetric/QueryMetricListResponse.java @@ -1,156 +1,70 @@ package datawave.microservice.querymetric; -import java.io.IOException; +import java.text.NumberFormat; import java.util.ArrayList; -import java.util.LinkedList; +import java.util.Collections; +import java.util.Date; import java.util.List; +import java.util.TreeMap; import javax.xml.bind.annotation.XmlAccessOrder; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorOrder; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import datawave.webservice.HtmlProvider; -import datawave.webservice.query.exception.QueryExceptionType; -import io.protostuff.Input; -import io.protostuff.Message; -import io.protostuff.Output; -import io.protostuff.Schema; +import org.springframework.web.servlet.ModelAndView; + +import datawave.microservice.querymetric.BaseQueryMetric.PageMetric; @XmlRootElement(name = "QueryMetricListResponse") @XmlAccessorType(XmlAccessType.NONE) @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) -public class QueryMetricListResponse extends BaseQueryMetricListResponse implements Message, HtmlProvider { +public class QueryMetricListResponse extends BaseQueryMetricListResponse { private static final long serialVersionUID = 1L; + private NumberFormat nf = NumberFormat.getIntegerInstance(); - public static Schema getSchema() { - return SCHEMA; - } - + /** + * Creates the ModelAndView for the detailed query metrics page (querymetric.html) + * + * @return the ModelAndView for querymetric.html + */ @Override - public Schema cachedSchema() { - return SCHEMA; - } - - @XmlTransient - private static final Schema SCHEMA = new Schema() { - // schema methods + public ModelAndView createModelAndView() { + ModelAndView mav = new ModelAndView(); - public QueryMetricListResponse newMessage() { - return new QueryMetricListResponse(); - } + mav.setViewName(viewName); - public Class typeClass() { - return QueryMetricListResponse.class; - } + TreeMap metricMap = new TreeMap<>(Collections.reverseOrder()); - public String messageName() { - return QueryMetricListResponse.class.getSimpleName(); + for (QueryMetric metric : this.getResult()) { + metricMap.put(metric.getCreateDate(), metric); } - public String messageFullName() { - return QueryMetricListResponse.class.getName(); - } + List metricList = new ArrayList<>(); - public boolean isInitialized(QueryMetricListResponse message) { - return true; - } - - public void writeTo(Output output, QueryMetricListResponse message) throws IOException { - output.writeUInt64(1, message.getOperationTimeMS(), false); - - List messages = message.getMessages(); - if (messages != null) { - for (String msg : messages) { - if (msg != null) - output.writeString(2, msg, true); - } - } - - List exceptions = message.getExceptions(); - if (exceptions != null) { - for (QueryExceptionType exception : exceptions) { - if (exception != null) - output.writeObject(3, exception, QueryExceptionType.getSchema(), true); - } - } - - if (message.result != null) { - for (QueryMetric result : message.result) { - if (result != null) - output.writeObject(4, result, QueryMetric.getSchema(), true); - } - } - - output.writeInt32(5, message.numResults, false); - } - - public void mergeFrom(Input input, QueryMetricListResponse message) throws IOException { - LinkedList exceptions = null; - int number; - while ((number = input.readFieldNumber(this)) != 0) { - switch (number) { - case 1: - message.setOperationTimeMS(input.readUInt64()); - break; - case 2: - message.addMessage(input.readString()); - break; - case 3: - if (exceptions == null) - exceptions = new LinkedList(); - exceptions.add(input.mergeObject(null, QueryExceptionType.getSchema())); - break; - case 4: - if (message.result == null) - message.result = new ArrayList(); - message.result.add(input.mergeObject(null, QueryMetric.getSchema())); - break; - - case 5: - message.numResults = input.readInt32(); - break; - default: - input.handleUnknownField(number, this); - break; - } - } - if (exceptions != null) - message.setExceptions(exceptions); - } - - public String getFieldName(int number) { - switch (number) { - case 1: - return "operationTimeMs"; - case 2: - return "messages"; - case 3: - return "exceptions"; - case 4: - return "result"; - case 5: - return "numResults"; - default: - return null; + for (QueryMetric metric : metricMap.values()) { + QueryMetricModel metricModel = new QueryMetricModel(metric, basePath); + for (PageMetric p : metric.getPageTimes()) { + metricModel.totalPageTime += p.getReturnTime(); + metricModel.totalPageCallTime += (p.getCallTime()) == -1 ? 0 : p.getCallTime(); + metricModel.totalSerializationTime += (p.getSerializationTime()) == -1 ? 0 : p.getSerializationTime(); + metricModel.totalBytesSent += (p.getBytesWritten()) == -1 ? 0 : p.getBytesWritten(); } + metricList.add(metricModel); } - public int getFieldNumber(String name) { - final Integer number = fieldMap.get(name); - return number == null ? 0 : number.intValue(); + mav.addObject("screenCssUrl", basePath + "/css/screen.css"); + mav.addObject("themeCssUrl", basePath + "/css/theme.css"); + if (isGeoQuery) { + mav.addObject("jqueryMinJsUrl", basePath + "/webjars/jquery/jquery.min.js"); + } else { + mav.addObject("jqueryMinJsUrl", ""); } - - final java.util.HashMap fieldMap = new java.util.HashMap(); - { - fieldMap.put("operationTimeMs", 1); - fieldMap.put("messages", 2); - fieldMap.put("exceptions", 3); - fieldMap.put("result", 4); - fieldMap.put("numResults", 5); - } - }; + mav.addObject("basePath", this.basePath); + mav.addObject("isGeoQuery", this.isGeoQuery()); + mav.addObject("metricList", metricList); + return mav; + } } diff --git a/api/src/main/java/datawave/microservice/querymetric/QueryMetricModel.java b/api/src/main/java/datawave/microservice/querymetric/QueryMetricModel.java new file mode 100644 index 00000000..dd6a429e --- /dev/null +++ b/api/src/main/java/datawave/microservice/querymetric/QueryMetricModel.java @@ -0,0 +1,245 @@ +package datawave.microservice.querymetric; + +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; + +import datawave.webservice.query.QueryImpl; + +public class QueryMetricModel extends QueryMetric { + + public long totalPageTime = 0; + public long totalPageCallTime = 0; + public long totalSerializationTime = 0; + public long totalBytesSent = 0; + + private String basePath; + private NumberFormat nf = NumberFormat.getIntegerInstance(); + private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HHmmss"); + + public QueryMetricModel(QueryMetric queryMetric, String basePath) { + super(queryMetric); + this.basePath = basePath; + } + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + public String getCreateDateStr() { + return sdf.format(createDate); + } + + @Override + public String getUser() { + return user == null ? "" : user; + } + + public String getBeginDateStr() { + return sdf.format(beginDate); + } + + public String getEndDateStr() { + return sdf.format(endDate); + } + + public String getQueryIdUrl() { + return basePath + "/v1/id/" + queryId; + } + + public String getProxyServersStr() { + return getProxyServers() == null ? "" : StringUtils.join(getProxyServers(), "
"); + } + + public String getQueryStyle() { + return isJexlQuery(parameters) ? "white-space: pre; word-wrap: break-word;" : "word-wrap: break-word;"; + } + + public String getParametersStr() { + return parameters == null ? "" : toFormattedParametersString(parameters); + } + + public String getQueryAuthorizationsStr() { + return getQueryAuthorizations() == null ? "" : getQueryAuthorizations().replaceAll(",", " "); + } + + public String getPredictionsStr() { + StringBuilder builder = new StringBuilder(); + if (predictions != null && !predictions.isEmpty()) { + String delimiter = ""; + List predictionsList = new ArrayList<>(predictions); + Collections.sort(predictionsList); + for (Prediction p : predictionsList) { + builder.append(delimiter).append(p.getName()).append(" = ").append(p.getPrediction()); + delimiter = "
"; + } + } else { + builder.append(""); + } + return builder.toString(); + } + + public String getLoginTimeStr() { + return numToString(getLoginTime(), 0); + } + + public String getSetupTimeStr() { + return numToString(getSetupTime(), 0); + } + + public String getCreateCallTimeStr() { + return numToString(getCreateCallTime(), 0); + } + + public String getNumPagesStr() { + return nf.format(numPages); + } + + public String getNumResultsStr() { + return nf.format(numResults); + } + + public String getDocRangesStr() { + return nf.format(docRanges); + } + + public String getFiRangesStr() { + return nf.format(fiRanges); + } + + public String getSourceCountStr() { + return nf.format(sourceCount); + } + + public String getNextCountStr() { + return nf.format(nextCount); + } + + public String getSeekCountStr() { + return nf.format(seekCount); + } + + public String getYieldCountStr() { + return nf.format(yieldCount); + } + + public String getVersionStr() { + return versionMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("
")); + } + + public String getTotalPageTimeStr() { + return nf.format(totalPageTime); + } + + public String getTotalPageCallTimeStr() { + return nf.format(totalPageCallTime); + } + + public String getTotalSerializationTimeStr() { + return nf.format(totalSerializationTime); + } + + public String getTotalBytesSentStr() { + return nf.format(totalBytesSent); + } + + public String getElapsedTimeStr() { + return nf.format(getElapsedTime()); + } + + @Override + public String getErrorCode() { + return errorCode == null ? "" : StringEscapeUtils.escapeHtml4(errorCode); + } + + @Override + public String getErrorMessage() { + return errorMessage == null ? "" : StringEscapeUtils.escapeHtml4(errorMessage); + } + + public List getPageTimeModels() { + return super.getPageTimes().stream().map(p -> new PageMetricModel(p)).collect(Collectors.toList()); + } + + private static boolean isJexlQuery(Set params) { + return params.stream().anyMatch(p -> p.getParameterName().equals("query.syntax") && p.getParameterValue().equals("JEXL")); + } + + private String numToString(long number, long minValue) { + return number < minValue ? "" : nf.format(number); + } + + private static String toFormattedParametersString(final Set parameters) { + final StringBuilder params = new StringBuilder(); + final String PARAMETER_SEPARATOR = ";"; + final String PARAMETER_NAME_VALUE_SEPARATOR = ":"; + final String NEWLINE = System.getProperty("line.separator"); + + if (null != parameters) { + for (final QueryImpl.Parameter param : parameters) { + if (params.length() > 0) { + params.append(PARAMETER_SEPARATOR + NEWLINE); + } + + params.append(param.getParameterName()); + params.append(PARAMETER_NAME_VALUE_SEPARATOR); + params.append(param.getParameterValue()); + } + } + + return params.toString(); + } + + public class PageMetricModel extends PageMetric { + + private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HHmmss"); + + public PageMetricModel(PageMetric pageMetric) { + super(pageMetric); + } + + public String getPageNumberStr() { + return numToString(getPageNumber(), 1); + } + + public String getPageRequestedStr() { + return getPageRequested() > 0 ? sdf.format(new Date(getPageRequested())) : ""; + } + + public String getPageReturnedStr() { + return getPageReturned() > 0 ? sdf.format(new Date(getPageReturned())) : ""; + } + + public String getReturnTimeStr() { + return nf.format(getReturnTime()); + } + + public String getPageSizeStr() { + return nf.format(getPagesize()); + } + + public String getCallTimeStr() { + return numToString(getCallTime(), 0); + } + + public String getLoginTimeStr() { + return numToString(getLoginTime(), 0); + } + + public String getSerializationTimeStr() { + return numToString(getSerializationTime(), 0); + } + + public String getBytesWrittenStr() { + return numToString(getBytesWritten(), 0); + } + } +} diff --git a/api/src/main/java/datawave/microservice/querymetric/QueryMetricSummaryResponse.java b/api/src/main/java/datawave/microservice/querymetric/QueryMetricSummaryResponse.java new file mode 100644 index 00000000..b6bbab8c --- /dev/null +++ b/api/src/main/java/datawave/microservice/querymetric/QueryMetricSummaryResponse.java @@ -0,0 +1,183 @@ +package datawave.microservice.querymetric; + +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlAccessOrder; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorOrder; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import org.springframework.web.servlet.ModelAndView; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import datawave.webservice.query.exception.QueryExceptionType; +import datawave.webservice.result.BaseResponse; + +@XmlRootElement(name = "QueryMetricsSummaryResponse") +@XmlAccessorType(XmlAccessType.NONE) +@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) +public class QueryMetricSummaryResponse extends BaseResponse { + + private static final long serialVersionUID = 1L; + + @XmlElement(name = "OneHour") + protected QueryMetricSummary hour1 = new QueryMetricSummary(); + @XmlElement(name = "SixHours") + protected QueryMetricSummary hour6 = new QueryMetricSummary(); + @XmlElement(name = "TwelveHours") + protected QueryMetricSummary hour12 = new QueryMetricSummary(); + @XmlElement(name = "OneDay") + protected QueryMetricSummary day1 = new QueryMetricSummary(); + @XmlElement(name = "SevenDays") + protected QueryMetricSummary day7 = new QueryMetricSummary(); + @XmlElement(name = "ThirtyDays") + protected QueryMetricSummary day30 = new QueryMetricSummary(); + @XmlElement(name = "SixtyDays") + protected QueryMetricSummary day60 = new QueryMetricSummary(); + @XmlElement(name = "NinetyDays") + protected QueryMetricSummary day90 = new QueryMetricSummary(); + @XmlElement(name = "All") + protected QueryMetricSummary all = new QueryMetricSummary(); + + private String basePath = "/DataWave/Query/Metrics"; + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + public QueryMetricSummary getHour1() { + return hour1; + } + + public void setHour1(QueryMetricSummary hour1) { + this.hour1 = hour1; + } + + public QueryMetricSummary getHour6() { + return hour6; + } + + public void setHour6(QueryMetricSummary hour6) { + this.hour6 = hour6; + } + + public QueryMetricSummary getHour12() { + return hour12; + } + + public void setHour12(QueryMetricSummary hour12) { + this.hour12 = hour12; + } + + public QueryMetricSummary getDay1() { + return day1; + } + + public void setDay1(QueryMetricSummary day1) { + this.day1 = day1; + } + + public QueryMetricSummary getDay7() { + return day7; + } + + public void setDay7(QueryMetricSummary day7) { + this.day7 = day7; + } + + public QueryMetricSummary getDay30() { + return day30; + } + + public void setDay30(QueryMetricSummary day30) { + this.day30 = day30; + } + + public QueryMetricSummary getDay60() { + return day60; + } + + public void setDay60(QueryMetricSummary day60) { + this.day60 = day60; + } + + public QueryMetricSummary getDay90() { + return day90; + } + + public void setDay90(QueryMetricSummary day90) { + this.day90 = day90; + } + + public QueryMetricSummary getAll() { + return all; + } + + public void setAll(QueryMetricSummary all) { + this.all = all; + } + + protected void addSummary(List> summaryTableContent, QueryMetricSummary summary, String interval) { + NumberFormat formatter = NumberFormat.getInstance(); + Map summaryData = new HashMap<>(); + + summaryData.put("interval", interval); + summaryData.put("queryCount", formatter.format(summary.getQueryCount())); + summaryData.put("totalPages", formatter.format(summary.getTotalPages())); + summaryData.put("totalPageResultSize", formatter.format(summary.getTotalPageResultSize())); + summaryData.put("minPageResultSize", formatter.format(summary.getMinPageResultSize())); + summaryData.put("maxPageResultSize", formatter.format(summary.getMaxPageResultSize())); + summaryData.put("avgPageResultSize", formatter.format(summary.getAvgPageResultSize())); + summaryData.put("totalPageResponseTime", formatter.format(summary.getTotalPageResponseTime())); + summaryData.put("minPageResponseTime", formatter.format(summary.getMinPageResponseTime())); + summaryData.put("maxPageResponseTime", formatter.format(summary.getMaxPageResponseTime())); + summaryData.put("avgPageResponseTime", formatter.format(summary.getAvgPageResponseTime())); + summaryData.put("avgResultsPerSecond", formatter.format(summary.getAverageResultsPerSecond())); + summaryData.put("avgPagesPerSecond", formatter.format(summary.getAveragePagesPerSecond())); + + summaryTableContent.add(summaryData); + } + + public ModelAndView createModelAndView() { + List> summaryTableContent = new ArrayList<>(); + ModelAndView mav = new ModelAndView(); + + if (getExceptions() == null || getExceptions().isEmpty()) { + mav.setViewName("querymetricsummary"); + + NumberFormat formatter = NumberFormat.getInstance(); + formatter.setGroupingUsed(true); + formatter.setMaximumFractionDigits(2); + formatter.setParseIntegerOnly(false); + + addSummary(summaryTableContent, hour1, "1 hour"); + addSummary(summaryTableContent, hour6, "6 hours"); + addSummary(summaryTableContent, hour12, "12 hours"); + addSummary(summaryTableContent, day1, "1 day"); + addSummary(summaryTableContent, day7, "7 day"); + addSummary(summaryTableContent, day30, "30 days"); + addSummary(summaryTableContent, day60, "60 days"); + addSummary(summaryTableContent, day90, "90 days"); + addSummary(summaryTableContent, all, "all"); + + mav.addObject("summaryTableContent", summaryTableContent); + mav.addObject("screenCssUrl", basePath + "/css/screen.css"); + } else { + mav.setViewName("querymetricsummaryexceptions"); + + List exceptions = getExceptions(); + mav.addObject("exceptions", exceptions); + mav.addObject("schema", QueryExceptionType.getSchema()); + } + + return mav; + } +} diff --git a/api/src/main/java/datawave/microservice/querymetric/QueryMetricsDetailListResponse.java b/api/src/main/java/datawave/microservice/querymetric/QueryMetricsDetailListResponse.java deleted file mode 100644 index ed388e58..00000000 --- a/api/src/main/java/datawave/microservice/querymetric/QueryMetricsDetailListResponse.java +++ /dev/null @@ -1,251 +0,0 @@ -package datawave.microservice.querymetric; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.TreeMap; -import java.util.stream.Collectors; - -import javax.xml.bind.annotation.XmlAccessOrder; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorOrder; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -import datawave.microservice.querymetric.BaseQueryMetric.PageMetric; -import datawave.microservice.querymetric.BaseQueryMetric.Prediction; -import datawave.webservice.query.QueryImpl.Parameter; - -@XmlRootElement(name = "QueryMetricListResponse") -@XmlAccessorType(XmlAccessType.NONE) -@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) -public class QueryMetricsDetailListResponse extends QueryMetricListResponse { - - private static final long serialVersionUID = 1L; - private static final String NEWLINE = System.getProperty("line.separator"); - - @Override - public String getHeadContent() { - return super.getHeadContent() + ""; // styling for microservices query - // metric page - } - - @JsonIgnore - @XmlTransient - @Override - public String getMainContent() { - StringBuilder builder = new StringBuilder(), pageTimesBuilder = new StringBuilder(); - - builder.append("\n"); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - - builder.append(""); - builder.append(""); - - builder.append(""); - builder.append(""); - builder.append("\n"); - - pageTimesBuilder.append("
VisibilityQuery DateUserUserDNProxy Server(s)Query IDQuery TypeQuery LogicQueryQuery PlanQuery NameBegin DateEnd DateParametersQuery AuthsServerPredictionsLogin Time (ms)Query Setup Time (ms)Query Setup Call Time (ms)Number PagesNumber ResultsDoc RangesFI RangesSourcesNext CallsSeek CallsYield CountVersionsTotal Page Time (ms)Total Page Call Time (ms)Total Page Serialization Time (ms)Total Page Bytes Sent (uncompressed)LifecycleElapsed TimeError CodeError Message
\n"); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - - TreeMap metricMap = new TreeMap<>(Collections.reverseOrder()); - - for (QueryMetric metric : this.getResult()) { - metricMap.put(metric.getCreateDate(), metric); - } - - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HHmmss"); - - int x = 0; - for (QueryMetric metric : metricMap.values()) { - Set parameters = metric.getParameters(); - - // highlight alternating rows - if (x % 2 == 0) { - builder.append("\n"); - } else { - builder.append("\n"); - } - x++; - - builder.append(""); - builder.append(""); - builder.append(""); - String userDN = metric.getUserDN(); - builder.append(""); - String proxyServers = metric.getProxyServers() == null ? "" : StringUtils.join(metric.getProxyServers(), "
"); - builder.append(""); - if (this.isAdministratorMode()) { - builder.append(""); - } else { - builder.append(""); - } - builder.append(""); - builder.append(""); - // Note the query and query plan are added to the table later (see the javascript at the end of this for loop) - builder.append(isJexlQuery(parameters) ? ""); - builder.append(""); - builder.append(""); - - String beginDate = metric.getBeginDate() == null ? "" : sdf.format(metric.getBeginDate()); - builder.append(""); - String endDate = metric.getEndDate() == null ? "" : sdf.format(metric.getEndDate()); - builder.append(""); - builder.append(""); - String queryAuths = metric.getQueryAuthorizations() == null ? "" : metric.getQueryAuthorizations().replaceAll(",", " "); - builder.append(""); - - builder.append(""); - if (metric.getPredictions() != null && !metric.getPredictions().isEmpty()) { - builder.append(""); - builder.append(""); - builder.append("\n"); - builder.append(""); - builder.append(""); - - builder.append(""); - builder.append(""); - - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - String versions = metric.getVersionMap().entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("
")); - builder.append(""); - - long count = 0l; - long callTime = 0l; - long serializationTime = 0l; - long bytesSent = 0l; - int y = 0; - for (PageMetric p : metric.getPageTimes()) { - count += p.getReturnTime(); - callTime += (p.getCallTime()) == -1 ? 0 : p.getCallTime(); - serializationTime += (p.getSerializationTime()) == -1 ? 0 : p.getSerializationTime(); - bytesSent += (p.getBytesWritten()) == -1 ? 0 : p.getBytesWritten(); - if (y % 2 == 0) { - pageTimesBuilder.append(""); - } else { - pageTimesBuilder.append(""); - } - y++; - - String pageRequestedStr = ""; - long pageRequested = p.getPageRequested(); - if (pageRequested > 0) { - pageRequestedStr = sdf.format(new Date(pageRequested)); - } - - String pageReturnedStr = ""; - long pageReturned = p.getPageReturned(); - if (pageReturned > 0) { - pageReturnedStr = sdf.format(new Date(pageReturned)); - } - - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - pageTimesBuilder.append(""); - } - builder.append("\n"); - builder.append("\n"); - builder.append("\n"); - builder.append("\n"); - builder.append(""); - builder.append(""); - String errorCode = metric.getErrorCode(); - builder.append(""); - String errorMessage = metric.getErrorMessage(); - builder.append(""); - builder.append("\n\n"); - - /* - * javascript to make the metric's query and the metric's query plan interactive (highlight matching parens on mouse over, clicking a paren brings - * you to its matching paren) - */ - builder.append(""); - builder.append(""); // for microservices query metrics page - builder.append(""); // for webservers query metric page - } - - builder.append("
Page numberPage requestedPage returnedResponse time (ms)Page sizeCall time (ms)Login time (ms)Serialization time (ms)Bytes written (uncompressed)
").append(metric.getColumnVisibility()).append("").append(sdf.format(metric.getCreateDate())).append("").append(metric.getUser()).append("").append(userDN == null ? "" : userDN).append("").append(proxyServers).append("").append(metric.getQueryId()).append("").append(metric.getQueryId()) - .append("").append(metric.getQueryType()).append("").append(metric.getQueryLogic()).append("" - : "").append("").append("").append(metric.getQueryName()).append("").append(beginDate).append("").append(endDate).append("").append(parameters == null ? "" : toFormattedParametersString(parameters)) - .append("").append(queryAuths).append("").append(metric.getHost()).append(""); - String delimiter = ""; - List predictions = new ArrayList<>(metric.getPredictions()); - Collections.sort(predictions); - for (Prediction prediction : predictions) { - builder.append(delimiter).append(prediction.getName()).append(" = ").append(prediction.getPrediction()); - delimiter = "
"; - } - } else { - builder.append("
"); - } - builder.append("").append(numToString(metric.getLoginTime(), 0)).append("").append(numToString(metric.getSetupTime(), 0)).append("").append(numToString(metric.getCreateCallTime(), 0)).append("").append(metric.getNumPages()).append("").append(metric.getNumResults()).append("").append(metric.getDocRanges()).append("").append(metric.getFiRanges()).append("").append(metric.getSourceCount()).append("").append(metric.getNextCount()).append("").append(metric.getSeekCount()).append("").append(metric.getYieldCount()).append("").append(versions).append("
").append(numToString(p.getPageNumber(), 1)).append("").append(pageRequestedStr).append("").append(pageReturnedStr).append("").append(p.getReturnTime()).append("").append(p.getPagesize()).append("").append(numToString(p.getCallTime(), 0)).append("").append(numToString(p.getLoginTime(), 0)).append("").append(numToString(p.getSerializationTime(), 0)).append("").append(numToString(p.getBytesWritten(), 0)).append("
").append(count).append("").append(numToString(callTime, 0)).append("").append(numToString(serializationTime, 0)).append("").append(numToString(bytesSent, 0)).append("").append(metric.getLifecycle()).append("").append(metric.getElapsedTime()).append("").append((errorCode == null) ? "" : StringEscapeUtils.escapeHtml4(errorCode)).append("").append((errorMessage == null) ? "" : StringEscapeUtils.escapeHtml4(errorMessage)) - .append("
\n
\n"); - pageTimesBuilder.append("\n"); - - builder.append(pageTimesBuilder); - - return builder.toString(); - } - - private static boolean isJexlQuery(Set params) { - return params.stream().anyMatch(p -> p.getParameterName().equals("query.syntax") && p.getParameterValue().equals("JEXL")); - } - - private static String numToString(long number, long minValue) { - return number < minValue ? "" : Long.toString(number); - } - - private static String toFormattedParametersString(final Set parameters) { - final StringBuilder params = new StringBuilder(); - final String PARAMETER_SEPARATOR = ";"; - final String PARAMETER_NAME_VALUE_SEPARATOR = ":"; - final String NEWLINE = System.getProperty("line.separator"); - - if (null != parameters) { - for (final Parameter param : parameters) { - if (params.length() > 0) { - params.append(PARAMETER_SEPARATOR + NEWLINE); - } - - params.append(param.getParameterName()); - params.append(PARAMETER_NAME_VALUE_SEPARATOR); - params.append(param.getParameterValue()); - } - } - - return params.toString(); - } -} diff --git a/api/src/main/java/datawave/microservice/querymetric/QueryMetricsSummaryResponse.java b/api/src/main/java/datawave/microservice/querymetric/QueryMetricsSummaryResponse.java deleted file mode 100644 index d311b1d7..00000000 --- a/api/src/main/java/datawave/microservice/querymetric/QueryMetricsSummaryResponse.java +++ /dev/null @@ -1,212 +0,0 @@ -package datawave.microservice.querymetric; - -import java.text.NumberFormat; -import java.util.List; - -import javax.xml.bind.annotation.XmlAccessOrder; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorOrder; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -import datawave.webservice.HtmlProvider; -import datawave.webservice.query.exception.QueryExceptionType; -import datawave.webservice.result.BaseResponse; - -@XmlRootElement(name = "QueryMetricsSummaryResponse") -@XmlAccessorType(XmlAccessType.NONE) -@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) -public class QueryMetricsSummaryResponse extends BaseResponse implements HtmlProvider { - - private static final long serialVersionUID = 1L; - private static final String TITLE = "Query Metrics Summary", EMPTY = ""; - private static final String START_CELL = "", END_CELL = ""; - - @XmlElement(name = "OneHour") - protected QueryMetricSummary hour1 = new QueryMetricSummary(); - @XmlElement(name = "SixHours") - protected QueryMetricSummary hour6 = new QueryMetricSummary(); - @XmlElement(name = "TwelveHours") - protected QueryMetricSummary hour12 = new QueryMetricSummary(); - @XmlElement(name = "OneDay") - protected QueryMetricSummary day1 = new QueryMetricSummary(); - @XmlElement(name = "SevenDays") - protected QueryMetricSummary day7 = new QueryMetricSummary(); - @XmlElement(name = "ThirtyDays") - protected QueryMetricSummary day30 = new QueryMetricSummary(); - @XmlElement(name = "SixtyDays") - protected QueryMetricSummary day60 = new QueryMetricSummary(); - @XmlElement(name = "NinetyDays") - protected QueryMetricSummary day90 = new QueryMetricSummary(); - @XmlElement(name = "All") - protected QueryMetricSummary all = new QueryMetricSummary(); - - public QueryMetricSummary getHour1() { - return hour1; - } - - public void setHour1(QueryMetricSummary hour1) { - this.hour1 = hour1; - } - - public QueryMetricSummary getHour6() { - return hour6; - } - - public void setHour6(QueryMetricSummary hour6) { - this.hour6 = hour6; - } - - public QueryMetricSummary getHour12() { - return hour12; - } - - public void setHour12(QueryMetricSummary hour12) { - this.hour12 = hour12; - } - - public QueryMetricSummary getDay1() { - return day1; - } - - public void setDay1(QueryMetricSummary day1) { - this.day1 = day1; - } - - public QueryMetricSummary getDay7() { - return day7; - } - - public void setDay7(QueryMetricSummary day7) { - this.day7 = day7; - } - - public QueryMetricSummary getDay30() { - return day30; - } - - public void setDay30(QueryMetricSummary day30) { - this.day30 = day30; - } - - public QueryMetricSummary getDay60() { - return day60; - } - - public void setDay60(QueryMetricSummary day60) { - this.day60 = day60; - } - - public QueryMetricSummary getDay90() { - return day90; - } - - public void setDay90(QueryMetricSummary day90) { - this.day90 = day90; - } - - public QueryMetricSummary getAll() { - return all; - } - - public void setAll(QueryMetricSummary all) { - this.all = all; - } - - @Override - public String getTitle() { - return TITLE; - } - - /* - * (non-Javadoc) - * - * @see datawave.webservice.HtmlProvider#getPageHeader() - */ - @Override - public String getPageHeader() { - return (getExceptions() == null || getExceptions().isEmpty()) ? getTitle() : EMPTY; - } - - /* - * (non-Javadoc) - * - * @see datawave.webservice.HtmlProvider#getHeadContent() - */ - @Override - public String getHeadContent() { - return EMPTY; - } - - protected StringBuilder addSummary(StringBuilder builder, QueryMetricSummary summary, String name, boolean highlight) { - NumberFormat formatter = NumberFormat.getInstance(); - if (highlight) { - builder.append(""); - } else { - builder.append(""); - } - builder.append(START_CELL).append(name).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getQueryCount())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getTotalPages())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getTotalPageResultSize())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getMinPageResultSize())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getMaxPageResultSize())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getAvgPageResultSize())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getTotalPageResponseTime())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getMinPageResponseTime())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getMaxPageResponseTime())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getAvgPageResponseTime())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getAverageResultsPerSecond())).append(END_CELL); - builder.append(START_CELL).append(formatter.format(summary.getAveragePagesPerSecond())).append(END_CELL); - builder.append("\n"); - return builder; - } - - @Override - public String getMainContent() { - - StringBuilder builder = new StringBuilder(); - if (getExceptions() == null || getExceptions().isEmpty()) { - NumberFormat formatter = NumberFormat.getInstance(); - formatter.setGroupingUsed(true); - formatter.setMaximumFractionDigits(2); - formatter.setParseIntegerOnly(false); - - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - builder.append(""); - addSummary(builder, hour1, "1 hour", false); - addSummary(builder, hour6, "6 hours", true); - addSummary(builder, hour12, "12 hours", false); - addSummary(builder, day1, "1 day", true); - addSummary(builder, day7, "7 day", false); - addSummary(builder, day30, "30 days", true); - addSummary(builder, day60, "60 days", false); - addSummary(builder, day90, "90 days", true); - addSummary(builder, all, "all", false); - builder.append("
IntervalQueries SubmittedPages ReturnedTotal ResultsMin Page SizeMax Page SizeAvg Page SizeTotal Page Response Time (ms)Min Page Response Time (ms)Max Page Response Time (ms)Avg Page Response Time (ms)Avg Results Per SecondAvg Pages Per Second
"); - } else { - builder.append("EXCEPTIONS:").append("
"); - List exceptions = getExceptions(); - if (exceptions != null) { - for (QueryExceptionType exception : exceptions) { - if (exception != null) - builder.append(exception).append(", ").append(QueryExceptionType.getSchema()).append("
"); - } - } - } - return builder.toString(); - } -} diff --git a/service/src/main/resources/static/css/queryMap.css b/api/src/main/resources/static/css/queryMap.css similarity index 100% rename from service/src/main/resources/static/css/queryMap.css rename to api/src/main/resources/static/css/queryMap.css diff --git a/api/src/main/resources/static/css/theme.css b/api/src/main/resources/static/css/theme.css index e9aa5d8d..c787da32 100644 --- a/api/src/main/resources/static/css/theme.css +++ b/api/src/main/resources/static/css/theme.css @@ -108,3 +108,11 @@ .unary-minus { color: #7D4F50; } + +table.metric tr td:first-child { + font-size: 11pt; + font-weight: bold; + color: #333333; + text-align: left; + vertical-align: center; +} \ No newline at end of file diff --git a/api/src/main/resources/static/js/query-interactive-parens.js b/api/src/main/resources/static/js/query-interactive-parens.js index a54d0177..06acaba7 100644 --- a/api/src/main/resources/static/js/query-interactive-parens.js +++ b/api/src/main/resources/static/js/query-interactive-parens.js @@ -9,8 +9,7 @@ function unhighlight(line) { } // Function to make the provided query or query plan's parenthesis interactive -function interactiveParens(query = '', isQueryPlan = false) { - const metricNum = getMetricNum(); +function interactiveParens(query = '', isQueryPlan = false, metricNum) { const lines = query.split(/\r?\n/); for (let i = 0; i < lines.length; i++) { // If the line is 0 or more spaces followed by and ending with an open paren, find its matching closing paren (on a different line) @@ -69,8 +68,4 @@ function interactiveParens(query = '', isQueryPlan = false) { document.getElementById(`query-plan${metricNum}`).innerHTML = lines.join('\n'); else document.getElementById(`query${metricNum}`).innerHTML = lines.join('\n'); -} - -// Call interactiveParens for the query and query plan -interactiveParens(getQuery(), false); -interactiveParens(getPlan(), true); \ No newline at end of file +} \ No newline at end of file diff --git a/service/src/main/resources/static/js/queryMap.js b/api/src/main/resources/static/js/queryMap.js similarity index 100% rename from service/src/main/resources/static/js/queryMap.js rename to api/src/main/resources/static/js/queryMap.js diff --git a/api/src/main/resources/templates/querymetric-horizontal.html b/api/src/main/resources/templates/querymetric-horizontal.html new file mode 100644 index 00000000..6ff6c9b2 --- /dev/null +++ b/api/src/main/resources/templates/querymetric-horizontal.html @@ -0,0 +1,152 @@ + + + + + DATAWAVE - Query Metrics + + + + + + +

Query Metrics

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VisibilityQuery DateUserUserDNProxy Server(s)Query IDQuery TypeQuery LogicQueryQuery PlanQuery NameBegin DateEnd DateParametersQuery AuthsServerPredictionsLogin Time (ms)Query Setup Time (ms)Query Setup Call Time (ms)Number PagesNumber ResultsDoc RangesFI RangesSourcesNext CallsSeek CallsYield CountVersionTotal Page Time (ms)Total Page Call Time (ms)Total Page Serialization Time (ms)Total Page Bytes Sent (uncompressed)LifecycleElapsed TimeError CodeError Message
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Page numberPage requestedPage returnedResponse time (ms)Page sizeCall time (ms)Login time (ms)Serialization time (ms)Bytes written (uncompressed)
+
+
+
+ + diff --git a/api/src/main/resources/templates/querymetric.html b/api/src/main/resources/templates/querymetric.html new file mode 100644 index 00000000..50ef4ec2 --- /dev/null +++ b/api/src/main/resources/templates/querymetric.html @@ -0,0 +1,134 @@ + + + + + DATAWAVE - Query Metrics + + + + + + +

Query Metrics

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Visibility
Query Date
User
UserDN
Proxy Server(s)
Query ID
Query Logic
Query Name
Query Type
Begin Date
End Date
Server
Version
Elapsed Time
Lifecycle
Number Pages
Number Results
Error Code
Error Message
Parameters
Query Auths
Predictions
Login Time (ms)
Query Setup Time (ms)
Query Setup Call Time (ms)
Doc Ranges
FI Ranges
Sources
Next Calls
Seek Calls
Yield Count
Total Page Time (ms)
Total Page Call Time (ms)
Total Page Serialization Time (ms)
Total Page Bytes Sent (uncompressed)
Query (show)click link to show/hide
Query Plan (show)click link to show/hide
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Page numberPage requestedPage returnedResponse time (ms)Page sizeCall time (ms)Login time (ms)Serialization time (ms)Bytes written (uncompressed)
+
+
+
+ + \ No newline at end of file diff --git a/api/src/main/resources/templates/querymetricgeometry.html b/api/src/main/resources/templates/querymetricgeometry.html new file mode 100644 index 00000000..91e9767d --- /dev/null +++ b/api/src/main/resources/templates/querymetricgeometry.html @@ -0,0 +1,26 @@ + + + + + DATAWAVE - Query Geometry + +