Skip to content

Commit ccb6d82

Browse files
feat:support stat reporting path aggregation. (#612)
1 parent cf7ed5c commit ccb6d82

File tree

6 files changed

+214
-20
lines changed

6 files changed

+214
-20
lines changed

polaris-common/polaris-model/src/main/java/com/tencent/polaris/api/utils/ClassUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*/
2828
public class ClassUtils {
2929

30-
private static final Logger LOG = LoggerFactory.getLogger(RuleUtils.class);
30+
private static final Logger LOG = LoggerFactory.getLogger(ClassUtils.class);
3131

3232
/**
3333
* Check if class is present.

polaris-plugins/polaris-plugins-observability/stat-prometheus/src/main/java/com/tencent/polaris/plugins/stat/prometheus/handler/CommonHandler.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.tencent.polaris.api.plugin.stat.CircuitBreakGauge;
2121
import com.tencent.polaris.api.plugin.stat.RateLimitGauge;
2222
import com.tencent.polaris.api.pojo.InstanceGauge;
23+
import com.tencent.polaris.api.utils.CollectionUtils;
24+
import com.tencent.polaris.api.utils.StringUtils;
2325
import com.tencent.polaris.plugins.stat.common.model.AbstractSignatureStatInfoCollector;
2426
import com.tencent.polaris.plugins.stat.common.model.StatMetric;
2527
import com.tencent.polaris.plugins.stat.common.model.StatRevisionMetric;
@@ -28,10 +30,8 @@
2830
import com.tencent.polaris.plugins.stat.common.model.SystemMetricModel.SystemMetricName;
2931
import io.prometheus.client.Gauge;
3032

31-
import java.util.Collection;
32-
import java.util.HashMap;
33-
import java.util.Map;
34-
import java.util.Objects;
33+
import java.util.*;
34+
import java.util.regex.Pattern;
3535

3636
import static com.tencent.polaris.plugins.stat.common.model.SystemMetricModel.SystemMetricValue.NULL_VALUE;
3737

@@ -87,7 +87,18 @@ public static String[] getOrderedMetricLabelValues(Map<String, String> labels, S
8787
return orderValue;
8888
}
8989

90-
public static Map<String, String> convertInsGaugeToLabels(InstanceGauge insGauge, String sdkIP) {
90+
static String convertMethod(String originalMethod, List<Pattern> pathRegexPatternList) {
91+
if (StringUtils.isNotBlank(originalMethod) && CollectionUtils.isNotEmpty(pathRegexPatternList)) {
92+
for (Pattern pattern : pathRegexPatternList) {
93+
if (pattern.matcher(originalMethod).matches()) {
94+
return pattern.pattern();
95+
}
96+
}
97+
}
98+
return originalMethod;
99+
}
100+
101+
public static Map<String, String> convertInsGaugeToLabels(InstanceGauge insGauge, String sdkIP, List<Pattern> pathRegexPatternList) {
91102
Map<String, String> labels = new HashMap<>();
92103
for (String labelName : SystemMetricLabelOrder.INSTANCE_GAUGE_LABEL_ORDER) {
93104
switch (labelName) {
@@ -98,7 +109,8 @@ public static Map<String, String> convertInsGaugeToLabels(InstanceGauge insGauge
98109
addLabel(labelName, insGauge.getService(), labels);
99110
break;
100111
case SystemMetricName.CALLEE_METHOD:
101-
addLabel(labelName, insGauge.getMethod(), labels);
112+
String method = convertMethod(insGauge.getMethod(), pathRegexPatternList);
113+
addLabel(labelName, method, labels);
102114
break;
103115
case SystemMetricModel.SystemMetricName.CALLEE_INSTANCE:
104116
addLabel(labelName, buildAddress(insGauge.getHost(), insGauge.getPort()), labels);
@@ -137,7 +149,7 @@ public static Map<String, String> convertInsGaugeToLabels(InstanceGauge insGauge
137149
return labels;
138150
}
139151

140-
public static Map<String, String> convertCircuitBreakToLabels(CircuitBreakGauge gauge, String callerIp) {
152+
public static Map<String, String> convertCircuitBreakToLabels(CircuitBreakGauge gauge, String callerIp, List<Pattern> pathRegexPatternList) {
141153
Map<String, String> labels = new HashMap<>();
142154
for (String labelName : SystemMetricModel.SystemMetricLabelOrder.CIRCUIT_BREAKER_LABEL_ORDER) {
143155
switch (labelName) {
@@ -148,7 +160,8 @@ public static Map<String, String> convertCircuitBreakToLabels(CircuitBreakGauge
148160
addLabel(labelName, gauge.getService(), labels);
149161
break;
150162
case SystemMetricName.CALLEE_METHOD:
151-
addLabel(labelName, gauge.getMethod(), labels);
163+
String method = convertMethod(gauge.getMethod(), pathRegexPatternList);
164+
addLabel(labelName, method, labels);
152165
break;
153166
case SystemMetricName.CALLEE_SUBSET:
154167
addLabel(labelName, gauge.getSubset(), labels);
@@ -182,7 +195,7 @@ public static Map<String, String> convertCircuitBreakToLabels(CircuitBreakGauge
182195
return labels;
183196
}
184197

185-
public static Map<String, String> convertRateLimitGaugeToLabels(RateLimitGauge rateLimitGauge) {
198+
public static Map<String, String> convertRateLimitGaugeToLabels(RateLimitGauge rateLimitGauge, List<Pattern> pathRegexPatternList) {
186199
Map<String, String> labels = new HashMap<>();
187200
for (String labelName : SystemMetricModel.SystemMetricLabelOrder.RATELIMIT_GAUGE_LABEL_ORDER) {
188201
switch (labelName) {
@@ -193,7 +206,8 @@ public static Map<String, String> convertRateLimitGaugeToLabels(RateLimitGauge r
193206
addLabel(labelName, rateLimitGauge.getService(), labels);
194207
break;
195208
case SystemMetricName.CALLEE_METHOD:
196-
addLabel(labelName, rateLimitGauge.getMethod(), labels);
209+
String method = convertMethod(rateLimitGauge.getMethod(), pathRegexPatternList);
210+
addLabel(labelName, method, labels);
197211
break;
198212
case SystemMetricName.CALLER_LABELS:
199213
addLabel(labelName, rateLimitGauge.getLabels(), labels);

polaris-plugins/polaris-plugins-observability/stat-prometheus/src/main/java/com/tencent/polaris/plugins/stat/prometheus/handler/PrometheusHandlerConfig.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import com.tencent.polaris.api.utils.StringUtils;
2424
import com.tencent.polaris.factory.util.TimeStrJsonDeserializer;
2525

26+
import java.util.ArrayList;
27+
import java.util.List;
28+
2629
/**
2730
* @author wallezhang
2831
*/
@@ -50,6 +53,9 @@ public class PrometheusHandlerConfig implements Verifier {
5053
@JsonProperty
5154
private Boolean openGzip = false;
5255

56+
@JsonProperty
57+
private List<String> pathRegexList = new ArrayList<>();
58+
5359
public PrometheusHandlerConfig() {
5460
}
5561

@@ -158,6 +164,14 @@ public void setService(String service) {
158164
this.service = service;
159165
}
160166

167+
public List<String> getPathRegexList() {
168+
return pathRegexList;
169+
}
170+
171+
public void setPathRegexList(List<String> pathRegexList) {
172+
this.pathRegexList = pathRegexList;
173+
}
174+
161175
@Override
162176
public String toString() {
163177
return "PrometheusHandlerConfig{" +
@@ -168,6 +182,7 @@ public String toString() {
168182
", service='" + service + '\'' +
169183
", pushInterval=" + pushInterval +
170184
", openGzip=" + openGzip +
185+
", pathRegexList=" + pathRegexList +
171186
'}';
172187
}
173188
}

polaris-plugins/polaris-plugins-observability/stat-prometheus/src/main/java/com/tencent/polaris/plugins/stat/prometheus/plugin/PrometheusReporter.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.tencent.polaris.api.plugin.stat.*;
3232
import com.tencent.polaris.api.pojo.InstanceGauge;
3333
import com.tencent.polaris.api.pojo.ServiceKey;
34+
import com.tencent.polaris.api.utils.CollectionUtils;
3435
import com.tencent.polaris.api.utils.IPAddressUtils;
3536
import com.tencent.polaris.api.utils.StringUtils;
3637
import com.tencent.polaris.client.pojo.Node;
@@ -48,15 +49,13 @@
4849
import org.slf4j.Logger;
4950

5051
import java.io.IOException;
51-
import java.util.Collections;
52-
import java.util.HashMap;
53-
import java.util.Map;
54-
import java.util.Objects;
52+
import java.util.*;
5553
import java.util.concurrent.ConcurrentHashMap;
5654
import java.util.concurrent.Executors;
5755
import java.util.concurrent.ScheduledExecutorService;
5856
import java.util.concurrent.TimeUnit;
5957
import java.util.concurrent.atomic.AtomicBoolean;
58+
import java.util.regex.Pattern;
6059

6160
/**
6261
* PrometheusReporter plugin
@@ -101,6 +100,8 @@ public class PrometheusReporter implements StatReporter, PluginConfigProvider, H
101100

102101
private final Map<String, PushGateway> pushGatewayMap = new ConcurrentHashMap<>();
103102

103+
private final List<Pattern> pathRegexPatternList = new ArrayList<>();
104+
104105
public PrometheusReporter() {
105106
this.container = new StatInfoCollectorContainer();
106107
this.sampleMapping = new HashMap<>();
@@ -131,6 +132,12 @@ public void postContextInit(Extensions extensions) throws PolarisException {
131132
this.serviceAddressRepository = new ServiceAddressRepository(Collections.singletonList(this.config.getAddress()),
132133
extensions.getValueContext().getClientId(), extensions, new ServiceKey(config.getNamespace(), config.getService()));
133134

135+
if (CollectionUtils.isNotEmpty(config.getPathRegexList())) {
136+
for (String pathRegex : config.getPathRegexList()) {
137+
pathRegexPatternList.add(Pattern.compile(pathRegex));
138+
}
139+
}
140+
134141
this.initHandle();
135142
}
136143

@@ -173,23 +180,23 @@ public void handle(StatInfo statInfo) {
173180
public void handleRouterGauge(InstanceGauge instanceGauge) {
174181
if (null != container && null != container.getInsCollector()) {
175182
container.getInsCollector().collectStatInfo(instanceGauge,
176-
CommonHandler.convertInsGaugeToLabels(instanceGauge, sdkIP),
183+
CommonHandler.convertInsGaugeToLabels(instanceGauge, sdkIP, pathRegexPatternList),
177184
MetricValueAggregationStrategyCollections.SERVICE_CALL_STRATEGY);
178185
}
179186
}
180187

181188
public void handleCircuitBreakGauge(CircuitBreakGauge circuitBreakGauge) {
182189
if (null != container && null != container.getCircuitBreakerCollector()) {
183190
container.getCircuitBreakerCollector().collectStatInfo(circuitBreakGauge,
184-
CommonHandler.convertCircuitBreakToLabels(circuitBreakGauge, sdkIP),
191+
CommonHandler.convertCircuitBreakToLabels(circuitBreakGauge, sdkIP, pathRegexPatternList),
185192
MetricValueAggregationStrategyCollections.CIRCUIT_BREAK_STRATEGY);
186193
}
187194
}
188195

189196
public void handleRateLimitGauge(RateLimitGauge rateLimitGauge) {
190197
if (null != container && null != container.getRateLimitCollector()) {
191198
container.getRateLimitCollector().collectStatInfo(rateLimitGauge,
192-
CommonHandler.convertRateLimitGaugeToLabels(rateLimitGauge),
199+
CommonHandler.convertRateLimitGaugeToLabels(rateLimitGauge, pathRegexPatternList),
193200
MetricValueAggregationStrategyCollections.RATE_LIMIT_STRATEGY);
194201
}
195202
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Tencent is pleased to support the open source community by making polaris-java available.
3+
*
4+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
5+
*
6+
* Licensed under the BSD 3-Clause License (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* https://opensource.org/licenses/BSD-3-Clause
11+
*
12+
* Unless required by applicable law or agreed to in writing, software distributed
13+
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations under the License.
16+
*/
17+
18+
package com.tencent.polaris.plugins.stat.prometheus.handler;
19+
20+
import org.junit.Test;
21+
22+
import java.util.Arrays;
23+
import java.util.Collections;
24+
import java.util.List;
25+
import java.util.regex.Pattern;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
29+
/**
30+
* Test for {@link CommonHandler}.
31+
*
32+
* @author Haotian Zhang
33+
*/
34+
public class CommonHandlerTest {
35+
36+
@Test
37+
public void testConvertMethod_WhenMethodMatchesFirstPattern() {
38+
// 准备
39+
String originalMethod = "/api/v1/users";
40+
List<Pattern> patterns = Arrays.asList(
41+
Pattern.compile("/api/v1/.*"),
42+
Pattern.compile("/api/v2/.*")
43+
);
44+
45+
// 执行
46+
String result = CommonHandler.convertMethod(originalMethod, patterns);
47+
48+
// 验证
49+
assertThat(result).isEqualTo("/api/v1/.*");
50+
}
51+
52+
@Test
53+
public void testConvertMethod_WhenMethodMatchesSecondPattern() {
54+
// 准备
55+
String originalMethod = "/api/v2/orders";
56+
List<Pattern> patterns = Arrays.asList(
57+
Pattern.compile("/api/v1/.*"),
58+
Pattern.compile("/api/v2/.*")
59+
);
60+
61+
// 执行
62+
String result = CommonHandler.convertMethod(originalMethod, patterns);
63+
64+
// 验证
65+
assertThat(result).isEqualTo("/api/v2/.*");
66+
}
67+
68+
@Test
69+
public void testConvertMethod_WhenMethodDoesNotMatchAnyPattern() {
70+
// 准备
71+
String originalMethod = "/api/v3/products";
72+
List<Pattern> patterns = Arrays.asList(
73+
Pattern.compile("/api/v1/.*"),
74+
Pattern.compile("/api/v2/.*")
75+
);
76+
77+
// 执行
78+
String result = CommonHandler.convertMethod(originalMethod, patterns);
79+
80+
// 验证
81+
assertThat(result).isEqualTo("/api/v3/products");
82+
}
83+
84+
@Test
85+
public void testConvertMethod_WithEmptyPatternList() {
86+
// 准备
87+
String originalMethod = "/api/v1/users";
88+
List<Pattern> patterns = Collections.emptyList();
89+
90+
// 执行
91+
String result = CommonHandler.convertMethod(originalMethod, patterns);
92+
93+
// 验证
94+
assertThat(result).isEqualTo("/api/v1/users");
95+
}
96+
97+
@Test
98+
public void testConvertMethod_WithNullPatternList() {
99+
// 准备
100+
String originalMethod = "/api/v1/users";
101+
List<Pattern> patterns = null;
102+
103+
// 执行
104+
String result = CommonHandler.convertMethod(originalMethod, patterns);
105+
106+
// 验证
107+
assertThat(result).isEqualTo("/api/v1/users");
108+
}
109+
110+
@Test
111+
public void testConvertMethod_WithNullOriginalMethod() {
112+
// 准备
113+
String originalMethod = null;
114+
List<Pattern> patterns = Arrays.asList(
115+
Pattern.compile("/api/v1/.*"),
116+
Pattern.compile("/api/v2/.*")
117+
);
118+
119+
// 执行
120+
String result = CommonHandler.convertMethod(originalMethod, patterns);
121+
122+
// 验证
123+
assertThat(result).isNull();
124+
}
125+
126+
@Test
127+
public void testConvertMethod_WithComplexPatterns() {
128+
// 准备
129+
String originalMethod = "/user/12345/profile";
130+
List<Pattern> patterns = Arrays.asList(
131+
Pattern.compile("/user/\\d+/profile"),
132+
Pattern.compile("/product/\\d+/detail")
133+
);
134+
135+
// 执行
136+
String result = CommonHandler.convertMethod(originalMethod, patterns);
137+
138+
// 验证
139+
assertThat(result).isEqualTo("/user/\\d+/profile");
140+
}
141+
142+
@Test
143+
public void testConvertMethod_WithExactMatchPattern() {
144+
// 准备
145+
String originalMethod = "GET";
146+
List<Pattern> patterns = Arrays.asList(
147+
Pattern.compile("GET"),
148+
Pattern.compile("POST"),
149+
Pattern.compile("PUT")
150+
);
151+
152+
// 执行
153+
String result = CommonHandler.convertMethod(originalMethod, patterns);
154+
155+
// 验证
156+
assertThat(result).isEqualTo("GET");
157+
}
158+
}

polaris-plugins/polaris-plugins-observability/stat-prometheus/src/test/java/com/tencent/polaris/plugins/stat/prometheus/plugin/PrometheusReporterTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,14 @@ private Double getCircuitBreakerResult(DefaultCircuitBreakResult example,
374374

375375
private Map<String, String> getServiceCallLabels(MetricValueAggregationStrategy<InstanceGauge> strategy,
376376
InstanceGauge gauge) {
377-
Map<String, String> labels = CommonHandler.convertInsGaugeToLabels(gauge, handler.getSdkIP());
377+
Map<String, String> labels = CommonHandler.convertInsGaugeToLabels(gauge, handler.getSdkIP(), null);
378378
labels.put(SystemMetricModel.SystemMetricName.METRIC_NAME_LABEL, strategy.getStrategyName());
379379
return labels;
380380
}
381381

382382
private Map<String, String> getCircuitBreakerLabels(MetricValueAggregationStrategy<CircuitBreakGauge> strategy,
383383
CircuitBreakGauge gauge) {
384-
Map<String, String> labels = CommonHandler.convertCircuitBreakToLabels(gauge, handler.getSdkIP());
384+
Map<String, String> labels = CommonHandler.convertCircuitBreakToLabels(gauge, handler.getSdkIP(), null);
385385
labels.put(SystemMetricModel.SystemMetricName.METRIC_NAME_LABEL, strategy.getStrategyName());
386386
return labels;
387387
}

0 commit comments

Comments
 (0)