package act.metric;
/*-
* #%L
* ACT Framework
* %%
* Copyright (C) 2014 - 2017 ActFramework
* %%
* 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.
* #L%
*/
import act.cli.tree.FilteredTreeNode;
import act.cli.tree.TreeNode;
import act.cli.tree.TreeNodeFilter;
import org.osgl.$;
import org.osgl.util.C;
import org.osgl.util.S;
import java.util.List;
import java.util.Map;
public class MetricInfoTree {
private C.Map<String, MetricInfo> infoMap = C.newMap();
private MetricInfoNode root;
private C.Map<String, MetricInfoNode> nodeMap = C.newMap();
private TreeNodeFilter filter = null;
public MetricInfoTree(List<MetricInfo> infoList, $.Predicate<String> filter) {
for (MetricInfo info : infoList) {
infoMap.put(info.getName(), info);
}
if (filter != $.F.TRUE) {
this.filter = TreeNodeFilter.Common.pathMatches(filter);
}
buildTree();
}
public TreeNode root(NodeDecorator decorator) {
return null == filter ? decorator.decorate(root) : new FilteredTreeNode(decorator.decorate(root), filter);
}
MetricInfoNode getNode(MetricInfo info) {
MetricInfoNode node = nodeMap.get(info.getName());
if (null == node) {
node = new MetricInfoNode(info);
nodeMap.put(info.getName(), node);
}
return node;
}
MetricInfo getMetricInfo(String name) {
return infoMap.get(name);
}
void buildTree() {
for (Map.Entry<String, MetricInfo> entry: infoMap.entrySet()) {
String path = entry.getKey();
MetricInfo info = entry.getValue();
MetricInfoNode node = getNode(info);
if (node.isRoot) {
root = node;
}
}
}
class MetricInfoNode implements TreeNode {
MetricInfo info;
C.List<TreeNode> children = C.newList();
private boolean isRoot;
MetricInfoNode(MetricInfo info) {
this.info = $.notNull(info);
this.isRoot = !addToParent();
}
@Override
public String id() {
return S.str(info.getName()).afterLast(Metric.PATH_SEPARATOR).toString();
}
@Override
public String label() {
return info.getName();
}
@Override
public C.List<TreeNode> children() {
return children;
}
public String getParentPath() {
String path = info.getName();
if (path.contains(Metric.PATH_SEPARATOR)) {
return S.beforeLast(path, Metric.PATH_SEPARATOR);
}
return "";
}
boolean addToParent() {
String parentPath = getParentPath();
if (S.blank(parentPath)) {
return false;
}
MetricInfo parent = getMetricInfo(parentPath);
if (null == parent) {
return false;
}
MetricInfoNode parentNode = getNode(parent);
parentNode.children.add(this);
return true;
}
}
public static class NodeDecorator {
$.Function<MetricInfo, String> labelGetter;
NodeDecorator($.Function<MetricInfo, String> labelGetter) {
this.labelGetter = $.notNull(labelGetter);
}
TreeNode decorate(final MetricInfoNode node) {
return new TreeNode() {
@Override
public String id() {
return node.id();
}
@Override
public String label() {
return labelGetter.apply(node.info);
}
@Override
public List<TreeNode> children() {
return node.children().map(new $.Transformer<TreeNode, TreeNode>() {
@Override
public TreeNode transform(TreeNode treeNode) {
return decorate((MetricInfoNode) treeNode);
}
});
}
};
}
}
static final NodeDecorator COUNTER = new NodeDecorator(new $.Transformer<MetricInfo, String>() {
@Override
public String transform(MetricInfo metricInfo) {
return S.fmt("%s: %s", metricInfo.getName(), metricInfo.getCountAsStr());
}
});
static final NodeDecorator TIMER = new NodeDecorator(new $.Transformer<MetricInfo, String>() {
@Override
public String transform(MetricInfo metricInfo) {
return S.fmt("%s: %s / %s = %s", metricInfo.getName(), metricInfo.getAccumulated(), metricInfo.getCountAsStr(), metricInfo.getAvg());
}
});
}