Skip to content

Commit

Permalink
Fix JMX Metrics export error, link: #2989
Browse files Browse the repository at this point in the history
  • Loading branch information
LiYangSir committed Dec 8, 2022
1 parent 0561959 commit 35ede3a
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.log.RecordLog;
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.Map;
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
Expand All @@ -40,6 +41,8 @@ public class MetricBeanWriter {
private final MBeanRegistry mBeanRegistry = MBeanRegistry.getInstance();

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
Expand Down Expand Up @@ -68,7 +71,10 @@ public synchronized void write(Map<String, MetricNode> map) throws Exception {
long version = System.currentTimeMillis();
// set or update the new metric value
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()
+",appName=" + appName;
MetricBean metricBean = mBeanRegistry.findMBean(mBeanName);
Expand All @@ -95,4 +101,17 @@ public synchronized void write(Map<String, MetricNode> map) throws Exception {
}
}
}

/**
* 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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2007-present the original author or authors.
*
* 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);
}
}

0 comments on commit 35ede3a

Please sign in to comment.