Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add metric collection function to router plugin #1656

Merged
merged 1 commit into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ private Iterable<Tag> getMeterTags(Tags tags) {
for (Map.Entry<String, String> entry : tags.getTags().entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
if (StringUtils.isEmpty(key) || value == null) {
continue;
}
result.add(Tag.of(entry.getKey(), value));
Expand Down
2 changes: 2 additions & 0 deletions sermant-plugins/sermant-router/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ router.plugin:
enabled-spring-zone-router: false
# compatibility router config 1.0, default is false not support
enabled-previous-rule: false
# Whether to Enable Metrics Collection
enable-metric: false
transmit.plugin:
# Whether to transmit the label on the direct new thread
enabled-thread: true
Expand Down
2 changes: 1 addition & 1 deletion sermant-plugins/sermant-router/dubbo-router-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-config-api</artifactId>
<version>${dubbo.version}</version>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
*
* 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 io.sermant.router.dubbo.declarer;

import io.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer;
import io.sermant.core.plugin.agent.declarer.InterceptDeclarer;
import io.sermant.core.plugin.agent.matcher.ClassMatcher;
import io.sermant.core.plugin.agent.matcher.MethodMatcher;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.router.common.config.RouterConfig;
import io.sermant.router.dubbo.interceptor.AlibabaDubboMonitorFilterInterceptor;

/**
* Enhanced Declarer of the MonitorFilter
*
* @author zhp
* @since 2024-10-23
*/
public class AlibabaDubboMonitorFilterDeclarer extends AbstractPluginDeclarer {
private static final String ENHANCE_CLASS = "com.alibaba.dubbo.monitor.support.MonitorFilter";

private static final String METHOD_NAME = "invoke";

private static final RouterConfig ROUTER_CONFIG = PluginConfigManager.getPluginConfig(RouterConfig.class);

@Override
public ClassMatcher getClassMatcher() {
return ClassMatcher.nameEquals(ENHANCE_CLASS);
}

@Override
public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) {
return new InterceptDeclarer[]{
InterceptDeclarer.build(MethodMatcher.nameEquals(METHOD_NAME),
new AlibabaDubboMonitorFilterInterceptor())
};
}
daizhenyu marked this conversation as resolved.
Show resolved Hide resolved

@Override
public boolean isEnabled() {
return ROUTER_CONFIG.isEnableMetric();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
*
* 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 io.sermant.router.dubbo.declarer;

import io.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer;
import io.sermant.core.plugin.agent.declarer.InterceptDeclarer;
import io.sermant.core.plugin.agent.matcher.ClassMatcher;
import io.sermant.core.plugin.agent.matcher.MethodMatcher;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.router.common.config.RouterConfig;
import io.sermant.router.dubbo.interceptor.ApacheDubboMonitorFilterInterceptor;

/**
* Enhanced Declarer of the MonitorFilter
*
* @author zhp
* @since 2024-10-23
*/
public class ApacheDubboMonitorFilterDeclarer extends AbstractPluginDeclarer {
private static final String ENHANCE_CLASS = "org.apache.dubbo.monitor.support.MonitorFilter";

private static final String METHOD_NAME = "invoke";

private static final RouterConfig ROUTER_CONFIG = PluginConfigManager.getPluginConfig(RouterConfig.class);

@Override
public ClassMatcher getClassMatcher() {
return ClassMatcher.nameEquals(ENHANCE_CLASS);
}

@Override
public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) {
return new InterceptDeclarer[]{
InterceptDeclarer.build(MethodMatcher.nameEquals(METHOD_NAME),
new ApacheDubboMonitorFilterInterceptor())
};
}

@Override
public boolean isEnabled() {
return ROUTER_CONFIG.isEnableMetric();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@
package io.sermant.router.dubbo.handler;

import io.sermant.core.common.LoggerFactory;
import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.core.plugin.service.PluginServiceManager;
import io.sermant.router.common.cache.DubboCache;
import io.sermant.router.common.config.RouterConfig;
import io.sermant.router.common.constants.RouterConstant;
import io.sermant.router.common.metric.MetricsManager;
import io.sermant.router.common.utils.CollectionUtils;
import io.sermant.router.common.utils.DubboReflectUtils;
import io.sermant.router.dubbo.service.LaneContextFilterService;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand All @@ -39,6 +44,8 @@
public class LaneContextFilterHandler extends AbstractContextFilterHandler {
private static final Logger LOGGER = LoggerFactory.getLogger();

private final RouterConfig routerConfig = PluginConfigManager.getPluginConfig(RouterConfig.class);

private final LaneContextFilterService laneContextFilterService;

/**
Expand Down Expand Up @@ -77,6 +84,19 @@ public Map<String, List<String>> getRequestTag(Object invoker, Object invocation
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Lane is " + requestTag);
}
if (!routerConfig.isEnableMetric()) {
return requestTag;
}
laneTag.forEach((key, values) -> {
if (CollectionUtils.isEmpty(values)) {
return;
}
Map<String, String> tagsMap = new HashMap<>();
tagsMap.put(RouterConstant.CLIENT_SERVICE_NAME, DubboCache.INSTANCE.getAppName());
tagsMap.put(key, values.get(0));
tagsMap.put(RouterConstant.PROTOCOL, RouterConstant.DUBBO_PROTOCOL);
MetricsManager.addOrUpdateCounterMetricValue(RouterConstant.LANE_TAG_COUNT, tagsMap, 1);
});
return requestTag;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
*
* 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 io.sermant.router.dubbo.interceptor;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invoker;

import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.plugin.agent.interceptor.AbstractInterceptor;
import io.sermant.router.common.cache.DubboCache;
import io.sermant.router.common.constants.RouterConstant;
import io.sermant.router.common.metric.MetricsManager;

import java.util.HashMap;
import java.util.Map;

/**
* Interceptor of the MonitorFilter, Collecting Metric Information
*
* @author zhp
* @since 2024-10-23
*/
public class AlibabaDubboMonitorFilterInterceptor extends AbstractInterceptor {
@Override
public ExecuteContext before(ExecuteContext context) throws Exception {
return context;
}

@Override
public ExecuteContext after(ExecuteContext context) throws Exception {
Object[] arguments = context.getArguments();
if (arguments == null || arguments.length == 0) {
return context;
}
if (!(arguments[0] instanceof Invoker)) {
return context;
}
Invoker<?> invoker = (Invoker<?>) arguments[0];
URL url = invoker.getUrl();
if (isConsumer(url)) {
String address = url.getHost() + RouterConstant.URL_CONNECTOR + url.getPort();
Map<String, String> tagsMap = new HashMap<>();
tagsMap.put(RouterConstant.SERVER_ADDRESS, address);
tagsMap.put(RouterConstant.CLIENT_SERVICE_NAME, DubboCache.INSTANCE.getAppName());
tagsMap.put(RouterConstant.PROTOCOL, RouterConstant.DUBBO_PROTOCOL);
MetricsManager.addOrUpdateCounterMetricValue(RouterConstant.ROUTER_REQUEST_COUNT, tagsMap, 1);
}
return context;
}

private boolean isConsumer(URL url) {
return RouterConstant.DUBBO_CONSUMER.equals(url.getParameter(RouterConstant.DUBBO_SIDE,
RouterConstant.DUBBO_PROVIDER));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2024-2024 Sermant Authors. All rights reserved.
*
* 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 io.sermant.router.dubbo.interceptor;

import io.sermant.core.plugin.agent.entity.ExecuteContext;
import io.sermant.core.plugin.agent.interceptor.AbstractInterceptor;
import io.sermant.router.common.cache.DubboCache;
import io.sermant.router.common.constants.RouterConstant;
import io.sermant.router.common.metric.MetricsManager;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invoker;

import java.util.HashMap;
import java.util.Map;

/**
* Interceptor of the MonitorFilter, Collecting Metric Information
*
* @author zhp
* @since 2024-10-23
*/
public class ApacheDubboMonitorFilterInterceptor extends AbstractInterceptor {
@Override
public ExecuteContext before(ExecuteContext context) throws Exception {
return context;
}

@Override
public ExecuteContext after(ExecuteContext context) throws Exception {
daizhenyu marked this conversation as resolved.
Show resolved Hide resolved
Object[] arguments = context.getArguments();
if (arguments == null || arguments.length == 0) {
return context;
}
if (!(arguments[0] instanceof Invoker)) {
return context;
}
Invoker<?> invoker = (Invoker<?>) arguments[0];
URL url = invoker.getUrl();
if (isConsumer(url)) {
String address = url.getHost() + RouterConstant.URL_CONNECTOR + url.getPort();
Map<String, String> tagsMap = new HashMap<>();
tagsMap.put(RouterConstant.SERVER_ADDRESS, address);
tagsMap.put(RouterConstant.CLIENT_SERVICE_NAME, DubboCache.INSTANCE.getAppName());
tagsMap.put(RouterConstant.PROTOCOL, RouterConstant.DUBBO_PROTOCOL);
MetricsManager.addOrUpdateCounterMetricValue(RouterConstant.ROUTER_REQUEST_COUNT, tagsMap, 1);
}
return context;
}

private boolean isConsumer(URL url) {
return RouterConstant.DUBBO_CONSUMER.equals(url.getParameter(RouterConstant.DUBBO_SIDE,
RouterConstant.DUBBO_PROVIDER));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ io.sermant.router.dubbo.declarer.ClusterUtilsDeclarer
io.sermant.router.dubbo.declarer.ContextFilterDeclarer
io.sermant.router.dubbo.declarer.SpringApplicationDeclarer
io.sermant.router.dubbo.declarer.AbstractConfigDeclarer
io.sermant.router.dubbo.declarer.ApacheDubboMonitorFilterDeclarer
io.sermant.router.dubbo.declarer.AlibabaDubboMonitorFilterDeclarer
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package io.sermant.router.dubbo.handler;

import io.sermant.core.plugin.config.PluginConfigManager;
import io.sermant.core.service.ServiceManager;
import io.sermant.router.common.config.RouterConfig;
import io.sermant.router.dubbo.TestDubboConfigService;
import io.sermant.router.dubbo.service.LaneContextFilterService;

Expand Down Expand Up @@ -44,6 +46,8 @@ public class LaneContextFilterHandlerTest {

private static MockedStatic<ServiceManager> mockServiceManager;

private static MockedStatic<PluginConfigManager> mockPluginConfigManager;

private final LaneContextFilterHandler laneContextFilterHandler;

private final TestDubboConfigService configService;
Expand All @@ -63,6 +67,9 @@ public static void before() {
mockServiceManager = Mockito.mockStatic(ServiceManager.class);
mockServiceManager.when(() -> ServiceManager.getService(LaneContextFilterService.class))
.thenReturn(LANE_CONTEXT_FILTER_SERVICE);
mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class);
mockPluginConfigManager.when(()-> PluginConfigManager.getPluginConfig(RouterConfig.class))
.thenReturn(new RouterConfig());
}

/**
Expand All @@ -71,6 +78,7 @@ public static void before() {
@AfterClass
public static void after() {
mockServiceManager.close();
mockPluginConfigManager.close();
}

public LaneContextFilterHandlerTest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package io.sermant.router.spring.cache;
package io.sermant.router.common.cache;

import java.util.Map;

Expand Down
Loading
Loading