Add basic monitoring command API for cluster token server
- Also add top-K frequent parameter statistic support Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
1b68d0c9a0
commit
f82fcd696f
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.alibaba.csp.sentinel.cluster.flow.statistic;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
* @since 1.4.1
|
||||
*/
|
||||
public class ClusterMetricNode {
|
||||
|
||||
private long timestamp;
|
||||
|
||||
private String resourceName;
|
||||
private long flowId;
|
||||
|
||||
private double passQps;
|
||||
private double blockQps;
|
||||
private long rt;
|
||||
|
||||
private Map<Object, Double> topParams;
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public ClusterMetricNode setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getResourceName() {
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
public ClusterMetricNode setResourceName(String resourceName) {
|
||||
this.resourceName = resourceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getFlowId() {
|
||||
return flowId;
|
||||
}
|
||||
|
||||
public ClusterMetricNode setFlowId(long flowId) {
|
||||
this.flowId = flowId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getPassQps() {
|
||||
return passQps;
|
||||
}
|
||||
|
||||
public ClusterMetricNode setPassQps(double passQps) {
|
||||
this.passQps = passQps;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getBlockQps() {
|
||||
return blockQps;
|
||||
}
|
||||
|
||||
public ClusterMetricNode setBlockQps(double blockQps) {
|
||||
this.blockQps = blockQps;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getRt() {
|
||||
return rt;
|
||||
}
|
||||
|
||||
public ClusterMetricNode setRt(long rt) {
|
||||
this.rt = rt;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<Object, Double> getTopParams() {
|
||||
return topParams;
|
||||
}
|
||||
|
||||
public ClusterMetricNode setTopParams(Map<Object, Double> topParams) {
|
||||
this.topParams = topParams;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClusterMetricNode{" +
|
||||
"timestamp=" + timestamp +
|
||||
", resourceName='" + resourceName + '\'' +
|
||||
", flowId=" + flowId +
|
||||
", passQps=" + passQps +
|
||||
", blockQps=" + blockQps +
|
||||
", rt=" + rt +
|
||||
", topParams=" + topParams +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.alibaba.csp.sentinel.cluster.flow.statistic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterParamFlowRuleManager;
|
||||
import com.alibaba.csp.sentinel.cluster.flow.statistic.data.ClusterFlowEvent;
|
||||
import com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric;
|
||||
import com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterParamMetric;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
|
||||
import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
* @since 1.4.1
|
||||
*/
|
||||
public class ClusterMetricNodeGenerator {
|
||||
|
||||
public static Map<String, List<ClusterMetricNode>> generateCurrentNodeMap(String namespace) {
|
||||
Map<String, List<ClusterMetricNode>> map = new HashMap<>();
|
||||
Set<Long> flowIds = ClusterFlowRuleManager.getFlowIdSet(namespace);
|
||||
Set<Long> paramFlowIds = ClusterParamFlowRuleManager.getFlowIdSet(namespace);
|
||||
for (Long id : flowIds) {
|
||||
ClusterMetricNode node = flowToMetricNode(id);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
putToMap(map, node);
|
||||
}
|
||||
for (Long id : paramFlowIds) {
|
||||
ClusterMetricNode node = paramToMetricNode(id);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
putToMap(map, node);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private static void putToMap(Map<String, List<ClusterMetricNode>> map, ClusterMetricNode node) {
|
||||
List<ClusterMetricNode> nodeList = map.get(node.getResourceName());
|
||||
if (nodeList == null) {
|
||||
nodeList = new ArrayList<>();
|
||||
map.put(node.getResourceName(), nodeList);
|
||||
}
|
||||
nodeList.add(node);
|
||||
}
|
||||
|
||||
public static ClusterMetricNode flowToMetricNode(long flowId) {
|
||||
FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(flowId);
|
||||
if (rule == null) {
|
||||
return null;
|
||||
}
|
||||
ClusterMetric metric = ClusterMetricStatistics.getMetric(flowId);
|
||||
if (metric == null) {
|
||||
return new ClusterMetricNode().setFlowId(flowId)
|
||||
.setResourceName(rule.getResource());
|
||||
}
|
||||
return new ClusterMetricNode()
|
||||
.setFlowId(flowId)
|
||||
.setResourceName(rule.getResource())
|
||||
.setBlockQps(metric.getAvg(ClusterFlowEvent.BLOCK))
|
||||
.setPassQps(metric.getAvg(ClusterFlowEvent.PASS))
|
||||
.setTimestamp(TimeUtil.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static ClusterMetricNode paramToMetricNode(long flowId) {
|
||||
ParamFlowRule rule = ClusterParamFlowRuleManager.getParamRuleById(flowId);
|
||||
if (rule == null) {
|
||||
return null;
|
||||
}
|
||||
ClusterParamMetric metric = ClusterParamMetricStatistics.getMetric(flowId);
|
||||
if (metric == null) {
|
||||
return new ClusterMetricNode().setFlowId(flowId)
|
||||
.setResourceName(rule.getResource())
|
||||
.setTimestamp(TimeUtil.currentTimeMillis())
|
||||
.setTopParams(new HashMap<Object, Double>(0));
|
||||
}
|
||||
return new ClusterMetricNode()
|
||||
.setFlowId(flowId)
|
||||
.setResourceName(rule.getResource())
|
||||
.setTimestamp(TimeUtil.currentTimeMillis())
|
||||
.setTopParams(metric.getTopValues(5));
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,16 @@
|
|||
*/
|
||||
package com.alibaba.csp.sentinel.cluster.flow.statistic.metric;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.alibaba.csp.sentinel.cluster.flow.statistic.data.ClusterFlowEvent;
|
||||
import com.alibaba.csp.sentinel.slots.statistic.base.LongAdder;
|
||||
import com.alibaba.csp.sentinel.slots.statistic.cache.CacheMap;
|
||||
import com.alibaba.csp.sentinel.util.AssertUtil;
|
||||
|
|
@ -79,4 +87,48 @@ public class ClusterParamMetric {
|
|||
public double getAvg(Object value) {
|
||||
return getSum(value) / metric.getIntervalInSecond();
|
||||
}
|
||||
|
||||
public Map<Object, Double> getTopValues(int number) {
|
||||
metric.currentWindow();
|
||||
List<CacheMap<Object, LongAdder>> buckets = metric.values();
|
||||
|
||||
Map<Object, Long> result = new HashMap<>(buckets.size());
|
||||
|
||||
for (CacheMap<Object, LongAdder> b : buckets) {
|
||||
Set<Object> subSet = b.keySet(true);
|
||||
for (Object o : subSet) {
|
||||
Long count = result.get(o);
|
||||
if (count == null) {
|
||||
count = getCount(b.get(o));
|
||||
} else {
|
||||
count += getCount(b.get(o));
|
||||
}
|
||||
result.put(o, count);
|
||||
}
|
||||
}
|
||||
|
||||
// After merge, get the top set one.
|
||||
Set<Entry<Object, Long>> set = result.entrySet();
|
||||
List<Entry<Object, Long>> list = new ArrayList<>(set);
|
||||
Collections.sort(list, new Comparator<Entry<Object, Long>>() {
|
||||
@Override
|
||||
public int compare(Entry<Object, Long> a,
|
||||
Entry<Object, Long> b) {
|
||||
return (int)(b.getValue() == null ? 0 : b.getValue()) - (int)(a.getValue() == null ? 0 : a.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
Map<Object, Double> doubleResult = new HashMap<Object, Double>();
|
||||
|
||||
int size = list.size() > number ? number : list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Map.Entry<Object, Long> x = list.get(i);
|
||||
if (x.getValue() == 0) {
|
||||
break;
|
||||
}
|
||||
doubleResult.put(x.getKey(), ((double)x.getValue()) / metric.getIntervalInSecond());
|
||||
}
|
||||
|
||||
return doubleResult;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.alibaba.csp.sentinel.cluster.server.command.handler;
|
||||
|
||||
import com.alibaba.csp.sentinel.cluster.flow.statistic.ClusterMetricNodeGenerator;
|
||||
import com.alibaba.csp.sentinel.command.CommandHandler;
|
||||
import com.alibaba.csp.sentinel.command.CommandRequest;
|
||||
import com.alibaba.csp.sentinel.command.CommandResponse;
|
||||
import com.alibaba.csp.sentinel.command.annotation.CommandMapping;
|
||||
import com.alibaba.csp.sentinel.util.StringUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
/**
|
||||
* @author Eric Zhao
|
||||
* @since 1.4.1
|
||||
*/
|
||||
@CommandMapping(name = "cluster/server/metricList")
|
||||
public class FetchClusterMetricCommandHandler implements CommandHandler<String> {
|
||||
|
||||
@Override
|
||||
public CommandResponse<String> handle(CommandRequest request) {
|
||||
String namespace = request.getParam("namespace");
|
||||
if (StringUtil.isEmpty(namespace)) {
|
||||
return CommandResponse.ofFailure(new IllegalArgumentException("failed: namespace cannot be empty"));
|
||||
}
|
||||
return CommandResponse.ofSuccess(
|
||||
JSON.toJSONString(ClusterMetricNodeGenerator.generateCurrentNodeMap(namespace))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,4 +6,5 @@ com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterServerTrans
|
|||
com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyServerNamespaceSetHandler
|
||||
com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterFlowRulesCommandHandler
|
||||
com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterParamFlowRulesCommandHandler
|
||||
com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterServerInfoCommandHandler
|
||||
com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterServerInfoCommandHandler
|
||||
com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterMetricCommandHandler
|
||||
Loading…
Reference in New Issue