mirror of https://github.com/longtai-cn/hippo4j
Bruceyan/issue monitor 20230624 (#1382)
parent
d3e76ff668
commit
f773440783
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 cn.hippo4j.agent.plugin.spring.common.define;
|
||||
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import cn.hippo4j.agent.core.plugin.match.ClassMatch;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
import static cn.hippo4j.agent.core.plugin.match.NameMatch.byName;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
public class SpringApplicationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
private static final String ENHANCE_CLASS = "org.springframework.boot.SpringApplication";
|
||||
|
||||
private static final String RUN_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.common.interceptor.SpringApplicationRunInterceptor";
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName(ENHANCE_CLASS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[]{
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named("run");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return RUN_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] witnessClasses() {
|
||||
return new String[]{"org.springframework.boot.SpringApplication"};
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 cn.hippo4j.common.handler;
|
||||
|
||||
import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
|
||||
import cn.hippo4j.common.extension.spi.ServiceLoaderRegistry;
|
||||
import cn.hippo4j.common.toolkit.CollectionUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* Dynamic thread pool adapter choose.
|
||||
*/
|
||||
public class DynamicThreadPoolAdapterChoose {
|
||||
|
||||
private static final List<DynamicThreadPoolAdapter> DYNAMIC_THREAD_POOL_ADAPTERS = new ArrayList<>();
|
||||
|
||||
static {
|
||||
DYNAMIC_THREAD_POOL_ADAPTERS.add(new TransmittableThreadLocalExecutorAdapter());
|
||||
DYNAMIC_THREAD_POOL_ADAPTERS.add(new TransmittableThreadLocalExecutorServiceAdapter());
|
||||
DYNAMIC_THREAD_POOL_ADAPTERS.add(new ZipkinExecutorAdapter());
|
||||
loadCustomerAdapter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the object contains thread pool information.
|
||||
*
|
||||
* @param executor objects where there may be instances
|
||||
* of dynamic thread pools
|
||||
* @return matching results
|
||||
*/
|
||||
public static boolean match(Object executor) {
|
||||
return DYNAMIC_THREAD_POOL_ADAPTERS.stream().anyMatch(each -> each.match(executor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dynamic thread pool reference in the object.
|
||||
*
|
||||
* @param executor objects where there may be instances
|
||||
* of dynamic thread pools
|
||||
* @return get the real dynamic thread pool instance
|
||||
*/
|
||||
public static ThreadPoolExecutor unwrap(Object executor) {
|
||||
Optional<DynamicThreadPoolAdapter> dynamicThreadPoolAdapterOptional = DYNAMIC_THREAD_POOL_ADAPTERS.stream().filter(each -> each.match(executor)).findFirst();
|
||||
return dynamicThreadPoolAdapterOptional.map(each -> each.unwrap(executor)).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@link DynamicThreadPoolAdapter#match(Object)} conditions are met,
|
||||
* the thread pool is replaced with a dynamic thread pool.
|
||||
*
|
||||
* @param executor objects where there may be instances
|
||||
* of dynamic thread pools
|
||||
* @param dynamicThreadPoolExecutor dynamic thread-pool executor
|
||||
*/
|
||||
public static void replace(Object executor, Executor dynamicThreadPoolExecutor) {
|
||||
Optional<DynamicThreadPoolAdapter> dynamicThreadPoolAdapterOptional = DYNAMIC_THREAD_POOL_ADAPTERS.stream().filter(each -> each.match(executor)).findFirst();
|
||||
dynamicThreadPoolAdapterOptional.ifPresent(dynamicThreadPoolAdapter -> dynamicThreadPoolAdapter.replace(executor, dynamicThreadPoolExecutor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load SPI customer adapter.
|
||||
*/
|
||||
private static void loadCustomerAdapter() {
|
||||
ServiceLoaderRegistry.register(DynamicThreadPoolAdapter.class);
|
||||
Collection<DynamicThreadPoolAdapter> instances = ServiceLoaderRegistry.getSingletonServiceInstances(DynamicThreadPoolAdapter.class);
|
||||
if (CollectionUtil.isEmpty(instances)) {
|
||||
return;
|
||||
}
|
||||
for (DynamicThreadPoolAdapter instance : instances) {
|
||||
if (instance != null) {
|
||||
DYNAMIC_THREAD_POOL_ADAPTERS.add(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 cn.hippo4j.common.handler;
|
||||
|
||||
import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
|
||||
import cn.hippo4j.common.toolkit.ReflectUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* Transmittable thread local executor adapter.
|
||||
*/
|
||||
public class TransmittableThreadLocalExecutorAdapter implements DynamicThreadPoolAdapter {
|
||||
|
||||
private static final String MATCH_CLASS_NAME = "ExecutorTtlWrapper";
|
||||
|
||||
private static final String FIELD_NAME = "executor";
|
||||
|
||||
@Override
|
||||
public boolean match(Object executor) {
|
||||
return Objects.equals(MATCH_CLASS_NAME, executor.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadPoolExecutor unwrap(Object executor) {
|
||||
return (ThreadPoolExecutor) ReflectUtil.getFieldValue(executor, FIELD_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(Object executor, Executor dynamicThreadPoolExecutor) {
|
||||
ReflectUtil.setFieldValue(executor, FIELD_NAME, dynamicThreadPoolExecutor);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 cn.hippo4j.common.handler;
|
||||
|
||||
import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
|
||||
import cn.hippo4j.common.toolkit.ReflectUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* Transmittable thread local executor service adapter.
|
||||
*/
|
||||
public class TransmittableThreadLocalExecutorServiceAdapter implements DynamicThreadPoolAdapter {
|
||||
|
||||
private static final String MATCH_CLASS_NAME = "ExecutorServiceTtlWrapper";
|
||||
|
||||
private static final String FIELD_NAME = "executorService";
|
||||
|
||||
@Override
|
||||
public boolean match(Object executor) {
|
||||
return Objects.equals(MATCH_CLASS_NAME, executor.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadPoolExecutor unwrap(Object executor) {
|
||||
return (ThreadPoolExecutor) ReflectUtil.getFieldValue(executor, FIELD_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(Object executor, Executor dynamicThreadPoolExecutor) {
|
||||
ReflectUtil.setFieldValue(executor, FIELD_NAME, dynamicThreadPoolExecutor);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 cn.hippo4j.common.handler;
|
||||
|
||||
import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
|
||||
import cn.hippo4j.common.toolkit.ReflectUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* Zipkin thread local executor adapter.
|
||||
*/
|
||||
public class ZipkinExecutorAdapter implements DynamicThreadPoolAdapter {
|
||||
|
||||
private static final String MATCH_CLASS_NAME = "brave.internal.WrappingExecutorService";
|
||||
private static final String FIELD_NAME = "delegate";
|
||||
private static final String TYPE_NAME = "java.util.concurrent.ExecutorService";
|
||||
|
||||
@Override
|
||||
public boolean match(Object executor) {
|
||||
return matchSuper(executor);
|
||||
}
|
||||
|
||||
public boolean matchSuper(Object executor) {
|
||||
if (Objects.equals(MATCH_CLASS_NAME, Optional.ofNullable(executor).map(Object::getClass).map(Class::getName).orElse(null))) {
|
||||
return true;
|
||||
} else {
|
||||
return Objects.equals(MATCH_CLASS_NAME, Optional.ofNullable(executor).map(Object::getClass).map(Class::getSuperclass).map(Class::getName).orElse(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadPoolExecutor unwrap(Object executor) {
|
||||
Object unwrap = doUnwrap(executor);
|
||||
if (unwrap == null) {
|
||||
return null;
|
||||
}
|
||||
return (ThreadPoolExecutor) unwrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(Object executor, Executor dynamicThreadPoolExecutor) {
|
||||
Field field = ReflectUtil.findField(executor, FIELD_NAME, TYPE_NAME);
|
||||
ReflectUtil.setFieldValue(executor, field, dynamicThreadPoolExecutor);
|
||||
}
|
||||
|
||||
private Object doUnwrap(Object executor) {
|
||||
Object unwrap = ReflectUtil.getFieldValue(executor, FIELD_NAME);
|
||||
if (unwrap == null) {
|
||||
Field field = ReflectUtil.findField(executor, FIELD_NAME, TYPE_NAME);
|
||||
if (field != null) {
|
||||
return ReflectUtil.getFieldValue(executor, field);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-kernel</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hippo4j-threadpool-kernel-monitor</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hippo4j</groupId>
|
||||
<artifactId>hippo4j-threadpool-infra-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.springboot.starter.adapter.web.WebAdapterConfiguration
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 cn.hippo4j.config.springboot.starter.config;
|
||||
|
||||
import cn.hippo4j.config.springboot.starter.monitor.ThreadPoolMonitorExecutor;
|
||||
import cn.hippo4j.core.enable.MarkerConfiguration;
|
||||
import cn.hippo4j.threadpool.dynamic.mode.config.properties.BootstrapConfigProperties;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
@EnableConfigurationProperties(SpringBootstrapConfigProperties.class)
|
||||
public class MonitorConfiguration {
|
||||
|
||||
private final BootstrapConfigProperties bootstrapConfigProperties;
|
||||
|
||||
@Bean
|
||||
public ThreadPoolMonitorExecutor hippo4jDynamicThreadPoolMonitorExecutor() {
|
||||
return new ThreadPoolMonitorExecutor(bootstrapConfigProperties);
|
||||
}
|
||||
}
|
@ -1 +1,5 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.config.springboot.starter.config.DynamicThreadPoolAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.config.springboot.starter.config.DynamicThreadPoolAutoConfiguration,\
|
||||
cn.hippo4j.core.config.UtilAutoConfiguration,\
|
||||
cn.hippo4j.message.config.MessageConfiguration,\
|
||||
cn.hippo4j.springboot.starter.adapter.web.WebAdapterConfiguration,\
|
||||
cn.hippo4j.config.springboot.starter.config.MonitorConfiguration
|
Loading…
Reference in new issue