Skip to content

Commit

Permalink
Add cache diagnostic features
Browse files Browse the repository at this point in the history
1) Added "secondary size" for query caches (# of results)
2) Added "dump cache content to log" feature

Also other minor changes e.g. renaming MatchingRule.isSupported(type)
to supports(type).
  • Loading branch information
mederly committed Apr 27, 2020
1 parent 4845cac commit 355acb9
Show file tree
Hide file tree
Showing 57 changed files with 1,131 additions and 647 deletions.
Expand Up @@ -17,6 +17,7 @@ <h3><wicket:message key="PageInternals.title.cache"/></h3>
<p></p>
<div class="main-button-bar">
<a class="btn btn-primary" wicket:id="clearCaches"/>
<a class="btn btn-primary" wicket:id="dumpContent"/>
</div>

</div>
Expand Down
Expand Up @@ -10,6 +10,8 @@
import com.evolveum.midpoint.util.Holder;
import com.evolveum.midpoint.util.KeyValueTreeNode;
import com.evolveum.midpoint.util.TreeNode;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.AceEditor;
import com.evolveum.midpoint.web.component.AjaxButton;
import com.evolveum.midpoint.web.security.MidPointApplication;
Expand All @@ -24,11 +26,16 @@
import java.util.ArrayList;
import java.util.List;

import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;

public class InternalsCachePanel extends BasePanel<Void>{

private static final long serialVersionUID = 1L;

private static final Trace LOGGER = TraceManager.getTrace(InternalsCachePanel.class);

private static final String ID_CLEAR_CACHES_BUTTON = "clearCaches";
private static final String ID_DUMP_CONTENT_BUTTON = "dumpContent";
private static final String ID_INFORMATION = "information";

public InternalsCachePanel(String id) {
Expand Down Expand Up @@ -58,7 +65,7 @@ public void setObject(String object) {
informationText.setMode(null);
add(informationText);

AjaxButton clearCaches = new AjaxButton(ID_CLEAR_CACHES_BUTTON, createStringResource("InternalsCachePanel.button.clearCaches")) {
add(new AjaxButton(ID_CLEAR_CACHES_BUTTON, createStringResource("InternalsCachePanel.button.clearCaches")) {

private static final long serialVersionUID = 1L;

Expand All @@ -67,54 +74,89 @@ public void onClick(AjaxRequestTarget target) {
getPageBase().getCacheDispatcher().dispatchInvalidation(null, null, true, null);
target.add(InternalsCachePanel.this);
}
};
});

add(new AjaxButton(ID_DUMP_CONTENT_BUTTON, createStringResource("InternalsCachePanel.button.dumpContent")) {

private static final long serialVersionUID = 1L;

@Override
public void onClick(AjaxRequestTarget target) {
String cacheInformation = getCacheInformation();
LOGGER.info("Dumping the content of the caches.\nCurrent counters:\n{}\n", cacheInformation);
MidPointApplication.get().getCacheRegistry().dumpContent();

add(clearCaches);
getSession().success(getPageBase().getString("InternalsCachePanel.result.dumped"));
target.add(getPageBase());
}
});
}

private static class SizeInformation {
private final int size;
private final int secondarySize;

private SizeInformation(SingleCacheStateInformationType info) {
size = defaultIfNull(info.getSize(), 0);
secondarySize = defaultIfNull(info.getSecondarySize(), 0);
}

private SizeInformation(ComponentSizeInformationType info) {
size = defaultIfNull(info.getSize(), 0);
secondarySize = defaultIfNull(info.getSecondarySize(), 0);
}
}

private String getCacheInformation() {
StringBuilder sb = new StringBuilder();
MidPointApplication midPointApplication = MidPointApplication.get();
if (midPointApplication != null) {
CachesStateInformationType state = midPointApplication.getCacheRegistry().getStateInformation();
List<KeyValueTreeNode<String, Integer>> trees = new ArrayList<>();
for (SingleCacheStateInformationType entry : state.getEntry()) {
KeyValueTreeNode<String, Integer> root = new KeyValueTreeNode<>(entry.getName(), entry.getSize());
trees.add(root);
addComponents(root, entry.getComponent());
}
Holder<Integer> maxLabelLength = new Holder<>(0);
Holder<Integer> maxSize = new Holder<>(0);
trees.forEach(tree -> tree.acceptDepthFirst(node -> {
int labelLength = node.getUserObject().getKey().length() + node.getDepth() * 2;
Integer size = node.getUserObject().getValue();
if (labelLength > maxLabelLength.getValue()) {
maxLabelLength.setValue(labelLength);
}
if (size != null && size > maxSize.getValue()) {
maxSize.setValue(size);
}
}));
int labelSize = Math.max(maxLabelLength.getValue() + 1, 30);
int sizeSize = Math.max((int) Math.log10(maxSize.getValue()) + 2, 7);
int firstPart = labelSize + 3;
int secondPart = sizeSize + 3;
String headerFormatString = " %-" + labelSize + "s | %" + sizeSize + "s \n";
String valueFormatString = " %-" + labelSize + "s | %" + sizeSize + "d \n";
//System.out.println("valueFormatString = " + valueFormatString);
sb.append("\n");
sb.append(String.format(headerFormatString, "Cache", "Size"));
sb.append(StringUtils.repeat("=", firstPart)).append("+").append(StringUtils.repeat("=", secondPart)).append("\n");
trees.forEach(tree -> {
tree.acceptDepthFirst(node -> printNode(sb, valueFormatString, node));
sb.append(StringUtils.repeat("-", firstPart)).append("+").append(StringUtils.repeat("-", secondPart)).append("\n");
});
CachesStateInformationType state = MidPointApplication.get().getCacheRegistry().getStateInformation();
List<KeyValueTreeNode<String, SizeInformation>> trees = new ArrayList<>();
for (SingleCacheStateInformationType entry : state.getEntry()) {
KeyValueTreeNode<String, SizeInformation> root = new KeyValueTreeNode<>(entry.getName(), new SizeInformation(entry));
trees.add(root);
addComponents(root, entry.getComponent());
}
Holder<Integer> maxLabelLength = new Holder<>(0);
Holder<Integer> maxSize = new Holder<>(1); // to avoid issues with log10
Holder<Integer> maxSecondarySize = new Holder<>(1); // to avoid issues with log10
trees.forEach(tree -> tree.acceptDepthFirst(node -> {
int labelLength = node.getUserObject().getKey().length() + node.getDepth() * 2;
int size = node.getUserObject().getValue().size;
int secondarySize = node.getUserObject().getValue().secondarySize;
if (labelLength > maxLabelLength.getValue()) {
maxLabelLength.setValue(labelLength);
}
if (size > maxSize.getValue()) {
maxSize.setValue(size);
}
if (secondarySize > maxSecondarySize.getValue()) {
maxSecondarySize.setValue(secondarySize);
}
}));
int labelSize = Math.max(maxLabelLength.getValue() + 1, 30);
int sizeSize = Math.max((int) Math.log10(maxSize.getValue()) + 2, 7);
int secondarySizeSize = Math.max((int) Math.log10(maxSecondarySize.getValue()) + 2, 8);
int firstPart = labelSize + 3;
int secondPart = sizeSize + 2;
int thirdPart = secondarySizeSize + 3;
String headerFormatString = " %-" + labelSize + "s | %" + sizeSize + "s | %" + secondarySizeSize + "s\n";
String valueFormatString = " %-" + labelSize + "s | %" + sizeSize + "d | %" + secondarySizeSize + "s\n";
sb.append("\n");
sb.append(String.format(headerFormatString, "Cache", "Size", "Sec. size"));
sb.append(StringUtils.repeat("=", firstPart)).append("+")
.append(StringUtils.repeat("=", secondPart)).append("+")
.append(StringUtils.repeat("=", thirdPart)).append("\n");
trees.forEach(tree -> {
tree.acceptDepthFirst(node -> printNode(sb, valueFormatString, node));
sb.append(StringUtils.repeat("-", firstPart)).append("+")
.append(StringUtils.repeat("-", secondPart)).append("+")
.append(StringUtils.repeat("-", thirdPart)).append("\n");
});
return sb.toString();
}

private void printNode(StringBuilder sb, String formatString, TreeNode<Pair<String, Integer>> node) {
Pair<String, Integer> pair = node.getUserObject();
private void printNode(StringBuilder sb, String formatString, TreeNode<Pair<String, SizeInformation>> node) {
Pair<String, SizeInformation> pair = node.getUserObject();
if (pair != null) {
int depth = node.getDepth();
StringBuilder prefix = new StringBuilder();
Expand All @@ -124,13 +166,22 @@ private void printNode(StringBuilder sb, String formatString, TreeNode<Pair<Stri
}
prefix.append("- ");
}
sb.append(String.format(formatString, prefix + pair.getKey(), pair.getValue()));
sb.append(String.format(formatString, prefix + pair.getKey(), pair.getValue().size,
emptyIfZero(pair.getValue().secondarySize)));
}
}

private String emptyIfZero(int number) {
if (number != 0) {
return String.valueOf(number);
} else {
return "";
}
}

private void addComponents(KeyValueTreeNode<String, Integer> node, List<ComponentSizeInformationType> components) {
private void addComponents(KeyValueTreeNode<String, SizeInformation> node, List<ComponentSizeInformationType> components) {
for (ComponentSizeInformationType component : components) {
KeyValueTreeNode<String, Integer> child = node.createChild(component.getName(), component.getSize());
KeyValueTreeNode<String, SizeInformation> child = node.createChild(component.getName(), new SizeInformation(component));
addComponents(child, component.getComponent());
}
}
Expand Down
Expand Up @@ -29,7 +29,7 @@ public interface MatchingRule<T> {
/**
* Returns true if the rule can be applied to the specified XSD type.
*/
boolean isSupported(QName xsdType);
boolean supports(QName xsdType);

/**
* Matches two objects.
Expand Down
Expand Up @@ -34,7 +34,7 @@ public QName getName() {
* @see com.evolveum.midpoint.model.match.MatchingRule#isSupported(java.lang.Class, javax.xml.namespace.QName)
*/
@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
// We support everything. We are the default.
return true;
}
Expand Down
Expand Up @@ -34,7 +34,7 @@ public QName getName() {
}

@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (DOMUtil.XSD_STRING.equals(xsdType));
}

Expand Down
Expand Up @@ -29,7 +29,7 @@ public QName getName() {
}

@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (DOMUtil.XSD_STRING.equals(xsdType));
}

Expand Down
Expand Up @@ -23,7 +23,7 @@
public class MatchingRuleRegistryImpl implements MatchingRuleRegistry {

@NotNull private final MatchingRule<?> defaultMatchingRule;
@NotNull private final Map<QName, ? extends MatchingRule<?>> matchingRules = new HashMap<>();
@NotNull private final Map<QName, MatchingRule<?>> matchingRules = new HashMap<>();

MatchingRuleRegistryImpl() {
this.defaultMatchingRule = new DefaultMatchingRule<>();
Expand All @@ -34,27 +34,39 @@ public class MatchingRuleRegistryImpl implements MatchingRuleRegistry {
@NotNull
public <T> MatchingRule<T> getMatchingRule(QName ruleName, QName typeQName) throws SchemaException {
if (ruleName == null) {
//noinspection unchecked
return (MatchingRule<T>) defaultMatchingRule;
}
MatchingRule<T> matchingRule = (MatchingRule<T>) matchingRules.get(ruleName);
if (matchingRule == null) {
//try match according to the localPart
if (QNameUtil.matchAny(ruleName, matchingRules.keySet())){
ruleName = QNameUtil.resolveNs(ruleName, matchingRules.keySet());
matchingRule = (MatchingRule<T>) matchingRules.get(ruleName);
}
if (matchingRule == null) {
throw new SchemaException("Unknown matching rule for name " + ruleName);
}
}
if (typeQName != null && !matchingRule.isSupported(typeQName)) {
throw new SchemaException("Matching rule "+ruleName+" does not support type "+typeQName);
MatchingRule<T> matchingRule = findMatchingRule(ruleName);
if (typeQName == null || matchingRule.supports(typeQName)) {
return matchingRule;
} else {
throw new SchemaException("Matching rule " + ruleName + " does not support type " + typeQName);
}
return matchingRule;
}

<T> void registerMatchingRule(MatchingRule<T> rule) {
((Map)this.matchingRules).put(rule.getName(), rule);
@NotNull
private <T> MatchingRule<T> findMatchingRule(QName ruleName) throws SchemaException {
//noinspection unchecked
MatchingRule<T> rule = (MatchingRule<T>) matchingRules.get(ruleName);
if (rule != null) {
return rule;
}

// try match according to the localPart
QName qualifiedRuleName = QNameUtil.resolveNs(ruleName, matchingRules.keySet());
if (qualifiedRuleName != null) {
//noinspection unchecked
MatchingRule<T> ruleAfterQualification = (MatchingRule<T>) matchingRules.get(qualifiedRuleName);
if (ruleAfterQualification != null) {
return ruleAfterQualification;
}
}

throw new SchemaException("Couldn't find matching rule named '" + ruleName + "'");
}

void registerMatchingRule(MatchingRule<?> rule) {
matchingRules.put(rule.getName(), rule);
}
}
Expand Up @@ -34,7 +34,7 @@ public QName getName() {
* @see com.evolveum.midpoint.prism.match.MatchingRule#isSupported(java.lang.Class, javax.xml.namespace.QName)
*/
@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (PolyStringType.COMPLEX_TYPE.equals(xsdType));
}

Expand Down
Expand Up @@ -34,7 +34,7 @@ public QName getName() {
* @see com.evolveum.midpoint.prism.match.MatchingRule#isSupported(java.lang.Class, javax.xml.namespace.QName)
*/
@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (PolyStringType.COMPLEX_TYPE.equals(xsdType));
}

Expand Down
Expand Up @@ -13,7 +13,6 @@
import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.match.MatchingRule;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

/**
Expand All @@ -34,7 +33,7 @@ public QName getName() {
* @see com.evolveum.midpoint.prism.match.MatchingRule#isSupported(java.lang.Class, javax.xml.namespace.QName)
*/
@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (PolyStringType.COMPLEX_TYPE.equals(xsdType));
}

Expand Down
Expand Up @@ -31,7 +31,7 @@ public QName getName() {
}

@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (DOMUtil.XSD_STRING.equals(xsdType));
}

Expand Down
Expand Up @@ -33,7 +33,7 @@ public QName getName() {
}

@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (DOMUtil.XSD_STRING.equals(xsdType));
}

Expand Down
Expand Up @@ -37,7 +37,7 @@ public QName getName() {
}

@Override
public boolean isSupported(QName xsdType) {
public boolean supports(QName xsdType) {
return (DOMUtil.XSD_STRING.equals(xsdType));
}

Expand Down
Expand Up @@ -6,16 +6,17 @@
*/
package com.evolveum.midpoint.schema.expression;

import java.util.HashMap;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* @author semancik
*
*/
public class ExpressionProfiles {

private final Map<String,ExpressionProfile> profiles = new HashMap<>();
private final Map<String,ExpressionProfile> profiles = new ConcurrentHashMap<>();

public ExpressionProfile getProfile(String identifier) {
return profiles.get(identifier);
Expand All @@ -28,4 +29,8 @@ public void add(ExpressionProfile profile) {
public int size() {
return profiles.size();
}

public Map<String, ExpressionProfile> getProfiles() {
return Collections.unmodifiableMap(profiles);
}
}

0 comments on commit 355acb9

Please sign in to comment.