Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,9 @@ public int getFieldNumber(String name) {
@XmlElement
protected String plan = null;
@XmlElement
@XmlJavaTypeAdapter(StringRangeCountMapAdapter.class)
protected Map<String,RangeCounts> subPlans = new HashMap<>();
@XmlElement
protected long loginTime = -1;
@XmlElementWrapper(name = "predictions")
@XmlElement(name = "prediction")
Expand All @@ -699,6 +702,46 @@ public enum Lifecycle {
NONE, DEFINED, INITIALIZED, RESULTS, CLOSED, CANCELLED, MAXRESULTS, NEXTTIMEOUT, TIMEOUT, SHUTDOWN, MAXWORK
}

public void addSubPlan(String plan, RangeCounts rangeCounts) {
synchronized (this.subPlans) {
if (subPlans.containsKey(plan)) {
RangeCounts combinedCounts = new RangeCounts();
RangeCounts currentCounts = subPlans.get(plan);
combinedCounts.setDocumentRangeCount(currentCounts.getDocumentRangeCount() + rangeCounts.getDocumentRangeCount());
combinedCounts.setShardRangeCount(currentCounts.getShardRangeCount() + rangeCounts.getShardRangeCount());
subPlans.put(plan, combinedCounts);
} else {
subPlans.put(plan, rangeCounts);
}
}
}

public void addSubPlans(Map<String,RangeCounts> subplanMap) {
synchronized (this.subPlans) {
if (subplanMap != null && !subplanMap.isEmpty()) {
for (Map.Entry<String,RangeCounts> entry : subplanMap.entrySet()) {
if (subPlans.containsKey(entry.getKey())) {
RangeCounts combinedCounts = new RangeCounts();
RangeCounts currentCounts = subPlans.get(entry.getKey());
combinedCounts.setDocumentRangeCount(currentCounts.getDocumentRangeCount() + entry.getValue().getDocumentRangeCount());
combinedCounts.setShardRangeCount(currentCounts.getShardRangeCount() + entry.getValue().getShardRangeCount());
subPlans.put(entry.getKey(), combinedCounts);
} else {
subPlans.put(entry.getKey(), entry.getValue());
}
}
}
}
}

public Map<String,RangeCounts> getSubPlans() {
return subPlans;
}

public void setSubPlans(Map<String,RangeCounts> subPlans) {
this.subPlans = subPlans;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the synchronized in addSubplan / addSubplans really necessary? If so, by returning the object in getSubplans, you are likely allowing non-synchronized access. Also, if multiple threads are accessing this calss, then setSubplans runs the risk of replacing the object that you have synchronized on. Or.... maybe you don't really have multile threads accessing a metric at the same time?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the synchronized. I do not think multiple threads are accessing a metric at the same time. But... this might need to be double checked.

public String getQueryType() {
return queryType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public void setViewName(String viewName) {

abstract public ModelAndView createModelAndView();

abstract public ModelAndView createSubplanModelAndView();

public void setHeader(String header) {
this.header = header;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ public QueryMetric(QueryMetric other) {
this.predictions.add(p.duplicate());
}
}
if (other.subPlans != null) {
this.subPlans = new HashMap<>();
if (!other.subPlans.isEmpty()) {
this.subPlans.putAll(other.subPlans);
}
}
}

@Override
Expand Down Expand Up @@ -142,8 +148,8 @@ public int hashCode() {
.append(this.getErrorMessage()).append(this.getCreateCallTime()).append(this.getErrorCode()).append(this.getQueryName())
.append(this.getParameters()).append(this.getSourceCount()).append(this.getNextCount()).append(this.getSeekCount())
.append(this.getYieldCount()).append(this.getDocSize()).append(this.getDocRanges()).append(this.getFiRanges()).append(this.getPlan())
.append(this.getLoginTime()).append(this.getPredictions()).append(this.getMarkings()).append(this.getNumUpdates())
.append(this.getVersionMap()).toHashCode();
.append(this.getLoginTime()).append(this.getPredictions()).append(this.getSubPlans()).append(this.getMarkings())
.append(this.getNumUpdates()).append(this.getVersionMap()).toHashCode();
}

@Override
Expand Down Expand Up @@ -171,8 +177,9 @@ public boolean equals(Object o) {
.append(this.getYieldCount(), other.getYieldCount()).append(this.getDocSize(), other.getDocSize())
.append(this.getDocRanges(), other.getDocRanges()).append(this.getFiRanges(), other.getFiRanges())
.append(this.getPlan(), other.getPlan()).append(this.getLoginTime(), other.getLoginTime())
.append(this.getPredictions(), other.getPredictions()).append(this.getMarkings(), other.getMarkings())
.append(this.getNumUpdates(), other.getNumUpdates()).append(this.getVersionMap(), other.getVersionMap()).isEquals();
.append(this.getPredictions(), other.getPredictions()).append(this.getSubPlans(), other.getSubPlans())
.append(this.getMarkings(), other.getMarkings()).append(this.getNumUpdates(), other.getNumUpdates())
.append(this.getVersionMap(), other.getVersionMap()).isEquals();
} else {
return false;
}
Expand All @@ -188,6 +195,7 @@ public String toString() {
buf.append(" QueryId: ").append(queryId);
buf.append(" Query: ").append(query);
buf.append(" Query Plan: ").append(this.getPlan());
buf.append(" Query SubPlans: ").append(this.getSubPlans());
buf.append(" Query Type: ").append(queryType);
buf.append(" Query Logic: ").append(queryLogic);
buf.append(" Query Name: ").append(queryName);
Expand Down Expand Up @@ -408,6 +416,12 @@ public void writeTo(Output output, QueryMetric message) throws IOException {
}

output.writeInt64(39, message.docSize, false);

if (message.subPlans != null) {
for (Map.Entry<String,RangeCounts> entry : message.subPlans.entrySet()) {
output.writeString(40, StringUtils.join(Arrays.asList(entry.getKey(), StringUtils.join(entry.getValue(), ",")), "\0"), true);
}
}
}

public void mergeFrom(Input input, QueryMetric message) throws IOException {
Expand Down Expand Up @@ -559,6 +573,26 @@ public void mergeFrom(Input input, QueryMetric message) throws IOException {
case 39:
message.docSize = input.readInt64();
break;
case 40:
if (message.subPlans == null) {
message.subPlans = new TreeMap<>();
}
String encodedPlans = input.readString();
String[] splitPlans = StringUtils.split(encodedPlans, "\0");
if (splitPlans.length == 2) {
RangeCounts rangeCounts = new RangeCounts();
int index = 0;
for (String count : StringUtils.split(splitPlans[1], ",")) {
if (index == 0) {
rangeCounts.setDocumentRangeCount(Integer.parseInt(count));
} else if (index == 1) {
rangeCounts.setShardRangeCount(Integer.parseInt(count));
}
index++;
}
message.subPlans.put(splitPlans[0], rangeCounts);
}
break;
default:
input.handleUnknownField(number, this);
break;
Expand Down Expand Up @@ -647,6 +681,8 @@ public String getFieldName(int number) {
return "versionMap";
case 39:
return "docSize";
case 40:
return "subPlans";
default:
return null;
}
Expand Down Expand Up @@ -699,6 +735,7 @@ public int getFieldNumber(String name) {
fieldMap.put("version", 37);
fieldMap.put("versionMap", 38);
fieldMap.put("docSize", 39);
fieldMap.put("subPlans", 40);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,32 @@ public ModelAndView createModelAndView() {
mav.addObject("footer", footer);
return mav;
}

/**
* Creates the ModelAndView for the detailed query subplans page (querysubplans.html)
*
* @return the ModelAndView for querysubplans.html
*/
@Override
public ModelAndView createSubplanModelAndView() {
ModelAndView mav = new ModelAndView();

mav.setViewName("querysubplans");

TreeMap<Date,QueryMetric> metricMap = new TreeMap<>(Collections.reverseOrder());

for (QueryMetric metric : this.getResult()) {
metricMap.put(metric.getCreateDate(), metric);
}

List<QueryMetricModel> metricModelList = new ArrayList<>();

for (QueryMetric metric : metricMap.values()) {
QueryMetricModel metricModel = new QueryMetricModel(metric, basePath);
metricModelList.add(metricModel);
}
mav.addObject("basePath", this.basePath);
mav.addObject("metricList", metricModelList);
return mav;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -76,6 +77,10 @@ public String getQueryIdUrl() {
return basePath + "/v1/id/" + queryId;
}

public String getQuerySubplansUrl() {
return basePath + "/v1/id/" + queryId + "/subplans/";
}

public String getProxyServersStr() {
return getProxyServers() == null ? "" : StringUtils.join(getProxyServers(), "<BR/>");
}
Expand All @@ -101,6 +106,10 @@ public String getPredictionsStr() {
return getPredictionsStr(predictions);
}

public Map<String,RangeCounts> getSubplansStr() {
return super.getSubPlans();
}

public String getLoginTimeStr() {
return numToString(getLoginTime(), 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
Expand All @@ -28,6 +29,8 @@ public interface QueryMetricModelFormat {

String getQueryIdUrl();

String getQuerySubplansUrl();

String getProxyServersStr();

String getParametersStr();
Expand All @@ -36,6 +39,8 @@ public interface QueryMetricModelFormat {

String getPredictionsStr();

Map<String,RangeCounts> getSubplansStr();

String getLoginTimeStr();

String getSetupTimeStr();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package datawave.microservice.querymetric;

import java.io.Serializable;
import java.util.Objects;

import org.apache.commons.lang3.builder.EqualsBuilder;

public class RangeCounts implements Serializable {

private long documentRangeCount;
private long shardRangeCount;

public long getDocumentRangeCount() {
return documentRangeCount;
}

public long getShardRangeCount() {
return shardRangeCount;
}

public void setDocumentRangeCount(long newDocumentRangeCount) {
this.documentRangeCount = newDocumentRangeCount;
}

public void setShardRangeCount(long newShardRangeCount) {
this.shardRangeCount = newShardRangeCount;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}

if (o == null || getClass() != o.getClass()) {
return false;
}

RangeCounts that = (RangeCounts) o;

return new EqualsBuilder().append(documentRangeCount, that.documentRangeCount).append(shardRangeCount, that.shardRangeCount).isEquals();
}

@Override
public int hashCode() {
return Objects.hash(documentRangeCount, shardRangeCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package datawave.microservice.querymetric;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlAdapter;

/**
* Provides JAX-B marshalling/unmarshalling of {@link Map} of String to RangeCount. This allows the marshalled type to be in our own namespace rather than in
* the "default" one, which when triggered will then assume the "" prefix and push all of our own elements into the "ns2" prefix.
*/
public class StringRangeCountMapAdapter extends XmlAdapter<StringRangeCountMapAdapter.StringRangeCountMap,Map<String,RangeCounts>> {

@Override
public Map<String,RangeCounts> unmarshal(StringRangeCountMap v) throws Exception {
HashMap<String,RangeCounts> map = new HashMap<>();
for (StringRangeCountMapEntry entry : v.entries) {
RangeCounts unmarshalledRangeCounts = new RangeCounts();
unmarshalledRangeCounts.setDocumentRangeCount(Long.parseLong(entry.value.split(",")[0]));
unmarshalledRangeCounts.setShardRangeCount(Long.parseLong(entry.value.split(",")[1]));
map.put(entry.key, unmarshalledRangeCounts);
}
return map;
}

@Override
public StringRangeCountMap marshal(Map<String,RangeCounts> v) throws Exception {
StringRangeCountMap map = new StringRangeCountMap();
for (Map.Entry<String,RangeCounts> entry : v.entrySet()) {
map.entries.add(new StringRangeCountMapEntry(entry.getKey(), toText(entry.getValue())));
}
return map;
}

public String toText(RangeCounts counts) {
return counts.getDocumentRangeCount() + "," + counts.getShardRangeCount();
}

public static class StringRangeCountMap {
@XmlElement(name = "entry")
private List<StringRangeCountMapEntry> entries = new ArrayList<>();
}

public static class StringRangeCountMapEntry {
@XmlAttribute(name = "name")
private String key;
@XmlValue
private String value;

public StringRangeCountMapEntry() {}

public StringRangeCountMapEntry(String key, String value) {
this.key = key;
this.value = value;
}
}
}
Loading
Loading