Fix the bug that error occurs in JMX metrics exporter when resource name contains '*' (#2992)
This commit is contained in:
parent
9f3712eed7
commit
59a32994cd
|
|
@ -20,12 +20,13 @@ package com.alibaba.csp.sentinel.metric.exporter.jmx;
|
||||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
|
import com.alibaba.csp.sentinel.node.metric.MetricNode;
|
||||||
|
import com.alibaba.csp.sentinel.util.StringUtil;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import javax.management.ObjectName;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the metric bean writer, it provides {@link MetricBeanWriter#write} method for register the
|
* the metric bean writer, it provides {@link MetricBeanWriter#write} method for register the
|
||||||
|
|
@ -41,6 +42,8 @@ public class MetricBeanWriter {
|
||||||
|
|
||||||
private static final String DEFAULT_APP_NAME = "sentinel-application";
|
private static final String DEFAULT_APP_NAME = "sentinel-application";
|
||||||
|
|
||||||
|
private static final Pattern SPECIAL_CHARACTER_PATTERN = Pattern.compile("[*?=:\"\n]");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write the MetricNode value to MetricBean
|
* write the MetricNode value to MetricBean
|
||||||
* if the MetricBean is not registered into {@link MBeanRegistry},
|
* if the MetricBean is not registered into {@link MBeanRegistry},
|
||||||
|
|
@ -68,7 +71,10 @@ public class MetricBeanWriter {
|
||||||
long version = System.currentTimeMillis();
|
long version = System.currentTimeMillis();
|
||||||
// set or update the new metric value
|
// set or update the new metric value
|
||||||
for (MetricNode metricNode : map.values()) {
|
for (MetricNode metricNode : map.values()) {
|
||||||
final String mBeanName = "Sentinel:type=Metric,resource=" + metricNode.getResource()
|
// Fix JMX Metrics export error: https://github.com/alibaba/Sentinel/issues/2989
|
||||||
|
// Without escape, it will throw "cannot add mbean for pattern name" or "invalid character in value part of property" exception
|
||||||
|
String resourceName = escapeSpecialCharacter(metricNode.getResource());
|
||||||
|
final String mBeanName = "Sentinel:type=Metric,resource=" + resourceName
|
||||||
+",classification=" + metricNode.getClassification()
|
+",classification=" + metricNode.getClassification()
|
||||||
+",appName=" + appName;
|
+",appName=" + appName;
|
||||||
MetricBean metricBean = mBeanRegistry.findMBean(mBeanName);
|
MetricBean metricBean = mBeanRegistry.findMBean(mBeanName);
|
||||||
|
|
@ -95,4 +101,17 @@ public class MetricBeanWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* escape only when arg has special character eg.(*,?,\n,\")
|
||||||
|
*
|
||||||
|
* @param resourceName need escape resource name
|
||||||
|
* @return escaped characters
|
||||||
|
*/
|
||||||
|
public static String escapeSpecialCharacter(String resourceName) {
|
||||||
|
if (StringUtil.isBlank(resourceName) || !SPECIAL_CHARACTER_PATTERN.matcher(resourceName).find()) {
|
||||||
|
return resourceName;
|
||||||
|
}
|
||||||
|
return ObjectName.quote(resourceName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2022 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.cps.sentinel.metric.exporter;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.metric.exporter.jmx.MetricBeanWriter;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link com.alibaba.csp.sentinel.metric.exporter.jmx.MetricBeanWriter} unit test
|
||||||
|
*
|
||||||
|
* @author quguai
|
||||||
|
* @date 2022/12/7 21:33
|
||||||
|
*/
|
||||||
|
public class MetricBeanWriterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeSpecialCharacter() {
|
||||||
|
String character = MetricBeanWriter.escapeSpecialCharacter(null);
|
||||||
|
Assert.assertNull(character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter("");
|
||||||
|
Assert.assertEquals("", character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter("sentinel");
|
||||||
|
Assert.assertEquals("sentinel", character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter("*sentinel");
|
||||||
|
Assert.assertEquals("\"\\*sentinel\"", character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter("?sentinel");
|
||||||
|
Assert.assertEquals("\"\\?sentinel\"", character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter("\nsentinel");
|
||||||
|
Assert.assertEquals("\"\\nsentinel\"", character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter("\"sentinel");
|
||||||
|
Assert.assertEquals("\"\\\"sentinel\"", character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter("=sentinel");
|
||||||
|
Assert.assertEquals("\"=sentinel\"", character);
|
||||||
|
|
||||||
|
character = MetricBeanWriter.escapeSpecialCharacter(":sentinel");
|
||||||
|
Assert.assertEquals("\":sentinel\"", character);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue