init
This commit is contained in:
27
sentinel/sentinel-extension/sentinel-metric-exporter/pom.xml
Normal file
27
sentinel/sentinel-extension/sentinel-metric-exporter/pom.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>sentinel-extension</artifactId>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>sentinel-metric-exporter</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.csp</groupId>
|
||||
<artifactId>sentinel-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric;
|
||||
|
||||
import com.alibaba.csp.sentinel.init.InitFunc;
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
import com.alibaba.csp.sentinel.metric.collector.MetricCollector;
|
||||
import com.alibaba.csp.sentinel.metric.exporter.MetricExporter;
|
||||
import com.alibaba.csp.sentinel.metric.exporter.jmx.JMXMetricExporter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The{@link MetricExporterInit} work on load Metric exporters.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 19:58
|
||||
* @since 1.8.3
|
||||
*/
|
||||
public class MetricExporterInit implements InitFunc {
|
||||
|
||||
/**
|
||||
* the list of metric exporters.
|
||||
*/
|
||||
private static List<MetricExporter> metricExporters = new ArrayList<>();
|
||||
|
||||
/*
|
||||
load metric exporters.
|
||||
*/
|
||||
static {
|
||||
// now we use this simple way to load MetricExporter.
|
||||
metricExporters.add(new JMXMetricExporter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws Exception {
|
||||
RecordLog.info("[MetricExporterInit] MetricExporter start init.");
|
||||
// start the metric exporters.
|
||||
for (MetricExporter metricExporter : metricExporters) {
|
||||
try {
|
||||
metricExporter.start();
|
||||
} catch (Exception e) {
|
||||
RecordLog.warn("[MetricExporterInit] MetricExporterInit start the metricExport[{}] failed, will ignore it.",
|
||||
metricExporter.getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// add shutdown hook.
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(
|
||||
() -> metricExporters.forEach(metricExporter -> {
|
||||
try {
|
||||
metricExporter.shutdown();
|
||||
} catch (Exception e) {
|
||||
RecordLog.warn("[MetricExporterInit] MetricExporterInit shutdown the metricExport[{}] failed, will ignore it.",
|
||||
metricExporter.getClass().getName(), e);
|
||||
}
|
||||
})
|
||||
));
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric.collector;
|
||||
|
||||
import com.alibaba.csp.sentinel.Constants;
|
||||
import com.alibaba.csp.sentinel.node.ClusterNode;
|
||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
|
||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
|
||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
||||
import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@link MetricCollector} work on collecting metrics in {@link MetricNode}.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 20:01
|
||||
* @since 1.8.3
|
||||
*/
|
||||
public class MetricCollector {
|
||||
|
||||
/**
|
||||
* collect the metrics in {@link MetricNode}.
|
||||
*
|
||||
* @return the metric grouped by resource name.
|
||||
*/
|
||||
public Map<String, MetricNode> collectMetric() {
|
||||
final long currentTime = TimeUtil.currentTimeMillis();
|
||||
final long maxTime = currentTime - currentTime % 1000;
|
||||
final long minTime = maxTime - 1000;
|
||||
Map<String, MetricNode> metricNodeMap = new HashMap<>();
|
||||
for (Map.Entry<ResourceWrapper, ClusterNode> e : ClusterBuilderSlot.getClusterNodeMap().entrySet()) {
|
||||
ClusterNode node = e.getValue();
|
||||
List<MetricNode> metrics = getLastMetrics(node, minTime, maxTime);
|
||||
aggregate(metricNodeMap, metrics, node);
|
||||
}
|
||||
aggregate(metricNodeMap, getLastMetrics(Constants.ENTRY_NODE, minTime, maxTime), Constants.ENTRY_NODE);
|
||||
return metricNodeMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the last second {@link MetricNode} of {@link ClusterNode}
|
||||
* @param node {@link ClusterNode}
|
||||
* @param minTime the min time.
|
||||
* @param maxTime the max time.
|
||||
* @return the list of {@link MetricNode}
|
||||
*/
|
||||
private List<MetricNode> getLastMetrics(ClusterNode node, long minTime, long maxTime) {
|
||||
return node.rawMetricsInMin(time -> time >= minTime && time < maxTime);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* aggregate the metrics, the metrics under the same resource will left the lasted value
|
||||
* @param metricNodeMap metrics map
|
||||
* @param metrics metrics info group by timestamp
|
||||
* @param node the node
|
||||
*/
|
||||
private void aggregate(Map<String, MetricNode> metricNodeMap, List<MetricNode> metrics, ClusterNode node) {
|
||||
if (metrics == null || metrics.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (MetricNode metricNode : metrics) {
|
||||
String resource = node.getName();
|
||||
metricNode.setResource(resource);
|
||||
metricNode.setClassification(node.getResourceType());
|
||||
MetricNode existMetricNode = metricNodeMap.get(resource);
|
||||
// always keep the MetricNode is the last
|
||||
if (existMetricNode != null && existMetricNode.getTimestamp() > metricNode.getTimestamp()) {
|
||||
continue;
|
||||
}
|
||||
metricNodeMap.put(resource, metricNode);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric.exporter;
|
||||
|
||||
/**
|
||||
* {@link MetricExporter} work on export metric to target monitor.
|
||||
* you can implement your export ways by this class.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 21:16
|
||||
*/
|
||||
public interface MetricExporter {
|
||||
|
||||
/**
|
||||
* start the {@link MetricExporter}.
|
||||
*
|
||||
* @throws Exception start exception.
|
||||
*/
|
||||
void start() throws Exception;
|
||||
|
||||
/**
|
||||
* export the data to target monitor by the implement.
|
||||
*
|
||||
* @throws Exception export exception.
|
||||
*/
|
||||
void export() throws Exception;
|
||||
|
||||
/**
|
||||
* shutdown the {@link MetricExporter}.
|
||||
*
|
||||
* @throws Exception shutdown exception.
|
||||
*/
|
||||
void shutdown() throws Exception;
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric.exporter.jmx;
|
||||
|
||||
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
import com.alibaba.csp.sentinel.metric.collector.MetricCollector;
|
||||
import com.alibaba.csp.sentinel.metric.exporter.MetricExporter;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* The JMX metric exporter, mainly for write metric datas to JMX bean. It implement {@link MetricExporter}, provide method
|
||||
* start, export and shutdown. The mainly design for the jmx is refresh the JMX bean data scheduled.
|
||||
* {@link JMXExportTask} work on export data to {@link MetricBean}.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 20:02
|
||||
* @since 1.8.3
|
||||
*/
|
||||
public class JMXMetricExporter implements MetricExporter {
|
||||
|
||||
/**
|
||||
* schedule executor.
|
||||
*/
|
||||
private final ScheduledExecutorService jmxExporterSchedule;
|
||||
|
||||
/**
|
||||
* JMX metric writer, write metric datas to {@link MetricBean}.
|
||||
*/
|
||||
private final MetricBeanWriter metricBeanWriter = new MetricBeanWriter();
|
||||
|
||||
/**
|
||||
* global metrics collector.
|
||||
*/
|
||||
private final MetricCollector metricCollector = new MetricCollector();
|
||||
|
||||
public JMXMetricExporter() {
|
||||
jmxExporterSchedule = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("sentinel-metrics-jmx-exporter-task", true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
jmxExporterSchedule.scheduleAtFixedRate(new JMXExportTask(), 1, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void export() throws Exception {
|
||||
metricBeanWriter.write(metricCollector.collectMetric());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws Exception {
|
||||
jmxExporterSchedule.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* JMXExportTask mainly work on execute the JMX metric export.
|
||||
*/
|
||||
class JMXExportTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
export();
|
||||
} catch (Exception e) {
|
||||
RecordLog.warn("[JMX Metric Exporter] export to JMX MetricBean failed.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric.exporter.jmx;
|
||||
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
|
||||
import javax.management.JMException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerFactory;
|
||||
import javax.management.ObjectName;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* This class provides a unified interface for registering/unregistering of Metric MBean.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 20:02
|
||||
* @since 1.8.3
|
||||
*/
|
||||
public class MBeanRegistry {
|
||||
|
||||
private static volatile MBeanRegistry instance = new MBeanRegistry();
|
||||
|
||||
private Map<MetricBean, String> mapBean2Name= new ConcurrentHashMap<>(8);
|
||||
|
||||
private Map<String, MetricBean> mapName2Bean = new ConcurrentHashMap<>(8);
|
||||
|
||||
private MBeanServer mBeanServer;
|
||||
|
||||
public static MBeanRegistry getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public MBeanRegistry() {
|
||||
try {
|
||||
mBeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
} catch (Error e) {
|
||||
// Account for running within IKVM and create a new MBeanServer
|
||||
// if the PlatformMBeanServer does not exist.
|
||||
mBeanServer = MBeanServerFactory.createMBeanServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new MBean with the platform MBean server.
|
||||
* @param bean the bean being registered
|
||||
* @param mBeanName the mBeanName
|
||||
* @throws JMException MBean can not register exception
|
||||
*/
|
||||
public void register(MetricBean bean, String mBeanName) throws JMException {
|
||||
assert bean != null;
|
||||
try {
|
||||
ObjectName oname = new ObjectName(mBeanName);
|
||||
mBeanServer.registerMBean(bean, oname);
|
||||
mapBean2Name.put(bean, mBeanName);
|
||||
mapName2Bean.put(mBeanName, bean);
|
||||
} catch (JMException e) {
|
||||
RecordLog.warn("[MBeanRegistry] Failed to register MBean " + mBeanName, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister the MetricBean
|
||||
* @param bean MetricBean
|
||||
*/
|
||||
public void unRegister(MetricBean bean) {
|
||||
assert bean != null;
|
||||
String beanName = mapBean2Name.get(bean);
|
||||
if (beanName == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ObjectName objectName = new ObjectName(beanName);
|
||||
mBeanServer.unregisterMBean(objectName);
|
||||
mapBean2Name.remove(bean);
|
||||
mapName2Bean.remove(beanName);
|
||||
} catch (JMException e) {
|
||||
RecordLog.warn("[MBeanRegistry] UnRegister the MetricBean fail", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find the MBean by BeanName
|
||||
* @param mBeanName mBeanName
|
||||
* @return MetricMBean
|
||||
*/
|
||||
public MetricBean findMBean(String mBeanName) {
|
||||
if (mBeanName == null) {
|
||||
return null;
|
||||
}
|
||||
return mapName2Bean.get(mBeanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* list all MBeans which is registered into MBeanRegistry
|
||||
* @return MetricBeans
|
||||
*/
|
||||
public List<MetricBean> listAllMBeans() {
|
||||
return new ArrayList<>(mapName2Bean.values());
|
||||
}
|
||||
}
|
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric.exporter.jmx;
|
||||
|
||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
|
||||
|
||||
/**
|
||||
* the MetricBean for JMX expose.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 20:02
|
||||
* @since 1.8.3
|
||||
*/
|
||||
public class MetricBean implements MetricMXBean {
|
||||
|
||||
private String resource;
|
||||
|
||||
/**
|
||||
* Resource classification (e.g. SQL or RPC)
|
||||
*/
|
||||
private int classification;
|
||||
|
||||
private long timestamp;
|
||||
|
||||
private long passQps;
|
||||
|
||||
private long blockQps;
|
||||
|
||||
private long successQps;
|
||||
|
||||
private long exceptionQps;
|
||||
|
||||
private long rt;
|
||||
|
||||
private long occupiedPassQps;
|
||||
|
||||
private int concurrency;
|
||||
|
||||
private long version;
|
||||
|
||||
@Override
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClassification() {
|
||||
return classification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPassQps() {
|
||||
return passQps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBlockQps() {
|
||||
return blockQps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSuccessQps() {
|
||||
return successQps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExceptionQps() {
|
||||
return exceptionQps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRt() {
|
||||
return rt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOccupiedPassQps() {
|
||||
return occupiedPassQps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConcurrency() {
|
||||
return concurrency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the version to current Mbean.
|
||||
*
|
||||
* @param version current version.
|
||||
*/
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the MBean value to the initialized value.
|
||||
*/
|
||||
public void reset() {
|
||||
this.blockQps = 0;
|
||||
this.passQps = 0;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
this.exceptionQps = 0;
|
||||
this.occupiedPassQps = 0;
|
||||
this.successQps = 0;
|
||||
this.rt = 0;
|
||||
this.concurrency = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the MetricBean's value which from MetricNode.
|
||||
*
|
||||
* @param metricNode metric Node for write file
|
||||
*/
|
||||
public void setValueFromNode(MetricNode metricNode) {
|
||||
if (metricNode == null) {
|
||||
return;
|
||||
}
|
||||
this.successQps = metricNode.getSuccessQps();
|
||||
this.blockQps = metricNode.getBlockQps();
|
||||
this.passQps = metricNode.getPassQps();
|
||||
this.occupiedPassQps = metricNode.getOccupiedPassQps();
|
||||
this.exceptionQps = metricNode.getExceptionQps();
|
||||
this.timestamp = metricNode.getTimestamp();
|
||||
this.classification = metricNode.getClassification();
|
||||
this.concurrency = metricNode.getConcurrency();
|
||||
this.resource = metricNode.getResource();
|
||||
this.rt = metricNode.getRt();
|
||||
}
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric.exporter.jmx;
|
||||
|
||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* the metric bean writer, it provides {@link MetricBeanWriter#write} method for register the
|
||||
* MetricBean in {@link MBeanRegistry} or update the value of MetricBean
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 20:02
|
||||
* @since 1.8.3
|
||||
*/
|
||||
public class MetricBeanWriter {
|
||||
|
||||
private final MBeanRegistry mBeanRegistry = MBeanRegistry.getInstance();
|
||||
|
||||
private static final String DEFAULT_APP_NAME = "sentinel-application";
|
||||
|
||||
/**
|
||||
* write the MetricNode value to MetricBean
|
||||
* if the MetricBean is not registered into {@link MBeanRegistry},
|
||||
* it will be created and registered into {@link MBeanRegistry}.
|
||||
* else it will update the value of MetricBean.
|
||||
* Notes. if the MetricNode is null, then {@link MetricBean} will be reset.
|
||||
* @param map metricNode value group by resource
|
||||
* @throws Exception write failed exception
|
||||
*/
|
||||
public synchronized void write(Map<String, MetricNode> map) throws Exception {
|
||||
if (map == null || map.isEmpty()) {
|
||||
List<MetricBean> metricNodes = mBeanRegistry.listAllMBeans();
|
||||
if (metricNodes == null || metricNodes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (MetricBean metricNode : metricNodes) {
|
||||
metricNode.reset();
|
||||
}
|
||||
return;
|
||||
}
|
||||
String appName = SentinelConfig.getAppName();
|
||||
if (appName == null) {
|
||||
appName = DEFAULT_APP_NAME;
|
||||
}
|
||||
long version = System.currentTimeMillis();
|
||||
// set or update the new value
|
||||
for (MetricNode metricNode : map.values()) {
|
||||
final String mBeanName = "Sentinel:type=" + appName + ",name=\"" + metricNode.getResource()
|
||||
+"\",classification=\"" + metricNode.getClassification() +"\"";
|
||||
MetricBean metricBean = mBeanRegistry.findMBean(mBeanName);
|
||||
if (metricBean != null) {
|
||||
metricBean.setValueFromNode(metricNode);
|
||||
metricBean.setVersion(version);
|
||||
} else {
|
||||
metricBean = new MetricBean();
|
||||
metricBean.setValueFromNode(metricNode);
|
||||
metricBean.setVersion(version);
|
||||
mBeanRegistry.register(metricBean, mBeanName);
|
||||
RecordLog.info("[MetricBeanWriter] Registering with JMX as Metric MBean [{}]", mBeanName);
|
||||
}
|
||||
}
|
||||
// reset the old value
|
||||
List<MetricBean> metricBeans = mBeanRegistry.listAllMBeans();
|
||||
if (metricBeans == null || metricBeans.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (MetricBean metricBean : metricBeans) {
|
||||
if (!Objects.equals(metricBean.getVersion(), version)) {
|
||||
metricBean.reset();
|
||||
mBeanRegistry.unRegister(metricBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 1999-2021 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.metric.exporter.jmx;
|
||||
|
||||
/**
|
||||
* the Metric JMX Bean interface.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 20:02
|
||||
* @since 1.8.3
|
||||
*/
|
||||
public interface MetricMXBean {
|
||||
|
||||
long getTimestamp();
|
||||
|
||||
long getOccupiedPassQps();
|
||||
|
||||
long getSuccessQps();
|
||||
|
||||
long getPassQps();
|
||||
|
||||
long getExceptionQps();
|
||||
|
||||
long getBlockQps();
|
||||
|
||||
long getRt();
|
||||
|
||||
String getResource();
|
||||
|
||||
int getClassification();
|
||||
|
||||
int getConcurrency();
|
||||
|
||||
long getVersion();
|
||||
}
|
@@ -0,0 +1 @@
|
||||
com.alibaba.csp.sentinel.metric.MetricExporterInit
|
@@ -0,0 +1,34 @@
|
||||
package com.alibaba.cps.sentinel.metric.exporter;
|
||||
|
||||
import com.alibaba.csp.sentinel.metric.exporter.jmx.MBeanRegistry;
|
||||
import com.alibaba.csp.sentinel.metric.exporter.jmx.MetricBean;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.management.JMException;
|
||||
|
||||
/**
|
||||
* {@link com.alibaba.csp.sentinel.metric.exporter.jmx.MBeanRegistry} unit test.
|
||||
*
|
||||
* @author chenglu
|
||||
* @date 2021-07-01 23:07
|
||||
*/
|
||||
public class MBeanRegistryTest {
|
||||
|
||||
@Test
|
||||
public void testMBeanRegistry() throws JMException {
|
||||
MBeanRegistry mBeanRegistry = MBeanRegistry.getInstance();
|
||||
|
||||
MetricBean metricBean = new MetricBean();
|
||||
String mBeanName = "Sentinel:type=test,name=test";
|
||||
mBeanRegistry.register(metricBean, mBeanName);
|
||||
|
||||
MetricBean mb1 = mBeanRegistry.findMBean(mBeanName);
|
||||
Assert.assertEquals(mb1, metricBean);
|
||||
|
||||
mBeanRegistry.unRegister(metricBean);
|
||||
|
||||
MetricBean mb2 = mBeanRegistry.findMBean(mBeanName);
|
||||
Assert.assertNull(mb2);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user