Skip to content
Open
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
@@ -0,0 +1,52 @@
/*
* 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 com.alipay.sofa.boot.actuator.autoconfigure.startup;

import com.alipay.sofa.boot.actuator.startup.StartupOptimizationEndpoint;
import com.alipay.sofa.boot.startup.StartupOptimizer;
import com.alipay.sofa.boot.startup.StartupReporter;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link StartupOptimizationEndpoint}.
*
* @author OpenAI
*/
@AutoConfiguration
@ConditionalOnBean(StartupReporter.class)
@ConditionalOnAvailableEndpoint(endpoint = StartupOptimizationEndpoint.class)
public class StartupOptimizationEndpointAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public StartupOptimizer startupOptimizer(StartupReporter startupReporter) {
return new StartupOptimizer(startupReporter);
}

@Bean
@ConditionalOnMissingBean
public StartupOptimizationEndpoint startupOptimizationEndpoint(StartupOptimizer startupOptimizer,
ApplicationContext applicationContext) {
return new StartupOptimizationEndpoint(startupOptimizer, applicationContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ com.alipay.sofa.boot.actuator.autoconfigure.health.ReadinessEndpointAutoConfigur
com.alipay.sofa.boot.actuator.autoconfigure.health.ReadinessRuntimeAutoConfiguration
com.alipay.sofa.boot.actuator.autoconfigure.health.ManualReadinessCallbackEndpointAutoConfiguration
com.alipay.sofa.boot.actuator.autoconfigure.startup.StartupEndPointAutoConfiguration
com.alipay.sofa.boot.actuator.autoconfigure.startup.StartupOptimizationEndpointAutoConfiguration
com.alipay.sofa.boot.actuator.autoconfigure.rpc.RpcActuatorAutoConfiguration
com.alipay.sofa.boot.actuator.autoconfigure.isle.IsleEndpointAutoConfiguration
com.alipay.sofa.boot.actuator.autoconfigure.threadpool.ThreadPoolEndpointAutoConfiguration
com.alipay.sofa.boot.actuator.autoconfigure.threadpool.ThreadPoolEndpointAutoConfiguration
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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 com.alipay.sofa.boot.actuator.autoconfigure.startup;

import com.alipay.sofa.boot.actuator.startup.StartupOptimizationEndpoint;
import com.alipay.sofa.boot.isle.ApplicationRuntimeModel;
import com.alipay.sofa.boot.startup.StartupOptimizer;
import com.alipay.sofa.boot.startup.StartupReporter;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link StartupOptimizationEndpointAutoConfiguration}.
*
* @author OpenAI
*/
public class StartupOptimizationEndpointAutoConfigurationTests {

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations
.of(StartupOptimizationEndpointAutoConfiguration.class))
.withClassLoader(
new FilteredClassLoader(
ApplicationRuntimeModel.class));

@Test
void runShouldHaveEndpointBean() {
this.contextRunner
.withBean(StartupReporter.class)
.withPropertyValues("management.endpoints.web.exposure.include=startup-optimization")
.run((context) -> assertThat(context)
.hasSingleBean(StartupOptimizer.class)
.hasSingleBean(StartupOptimizationEndpoint.class));
}

@Test
void runWhenNotStartupReporterBeanShouldNotHaveEndpointBean() {
this.contextRunner
.withPropertyValues("management.endpoints.web.exposure.include=startup-optimization")
.run((context) -> assertThat(context)
.doesNotHaveBean(StartupOptimizer.class)
.doesNotHaveBean(StartupOptimizationEndpoint.class));
}

@Test
void runWhenNotExposedShouldNotHaveEndpointBean() {
this.contextRunner
.withBean(StartupReporter.class)
.run((context) -> assertThat(context)
.doesNotHaveBean(StartupOptimizationEndpoint.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 com.alipay.sofa.boot.actuator.startup;

import com.alipay.sofa.boot.startup.BeanInitInfo;
import com.alipay.sofa.boot.startup.StartupOptimizer;
import com.alipay.sofa.boot.startup.StartupReport;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.util.List;

/**
* {@link Endpoint @Endpoint} to expose startup optimization analysis.
*
* @author OpenAI
*/
@Endpoint(id = "startup-optimization")
public class StartupOptimizationEndpoint {

private static final String SLOW_BEANS_OPERATION = "slow-beans";

private final StartupOptimizer optimizer;

private final ApplicationContext applicationContext;

public StartupOptimizationEndpoint(StartupOptimizer optimizer,
ApplicationContext applicationContext) {
this.optimizer = optimizer;
this.applicationContext = applicationContext;
}

@ReadOperation
public StartupReport analyze() {
return optimizer.analyzeStartupBottlenecks(applicationContext);
}

@ReadOperation
public List<BeanInitInfo> slowBeans(@Selector String operation, @Nullable Integer top) {
Assert.isTrue(SLOW_BEANS_OPERATION.equals(operation),
"Only slow-beans operation is supported");
return optimizer.findSlowBeans(applicationContext, top != null ? top : 10);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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 com.alipay.sofa.boot.actuator.startup;

import com.alipay.sofa.boot.startup.BeanInitInfo;
import com.alipay.sofa.boot.startup.BeanStat;
import com.alipay.sofa.boot.startup.StartupOptimizer;
import com.alipay.sofa.boot.startup.StartupReporter;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.GenericApplicationContext;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;

/**
* Tests for {@link StartupOptimizationEndpoint}.
*
* @author OpenAI
*/
public class StartupOptimizationEndpointTests {

@Test
void analyzeAndSlowBeans() {
StartupReporter startupReporter = new StartupReporter();
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("slow", new RootBeanDefinition(Object.class));
startupReporter.addCommonStartupStat(beanStat("slow", 600));
StartupOptimizationEndpoint endpoint = new StartupOptimizationEndpoint(
new StartupOptimizer(startupReporter), context);

assertThat(endpoint.analyze().getRecommendations()).hasSize(1);
List<BeanInitInfo> slowBeans = endpoint.slowBeans("slow-beans", 1);

assertThat(slowBeans).extracting(BeanInitInfo::getBeanName).containsExactly("slow");
}

@Test
void rejectsUnsupportedSelector() {
StartupReporter startupReporter = new StartupReporter();
StartupOptimizationEndpoint endpoint = new StartupOptimizationEndpoint(
new StartupOptimizer(startupReporter), new GenericApplicationContext());

assertThatIllegalArgumentException().isThrownBy(() -> endpoint.slowBeans("unknown", 1));
}

private BeanStat beanStat(String beanName, long cost) {
BeanStat beanStat = new BeanStat();
beanStat.setType(StartupReporter.SPRING_BEANS_INSTANTIATE);
beanStat.setName(beanName);
beanStat.setCost(cost);
beanStat.setBeanClassName(Object.class.getName());
return beanStat;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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 com.alipay.sofa.boot.autoconfigure.runtime;

import com.alipay.sofa.runtime.async.AsyncInitAutoMode;

/**
* Configuration properties for async bean initialization.
*
* @author OpenAI
*/
public class AsyncInitProperties {

/**
* Whether async initialization is enabled.
*/
private boolean enabled = true;

/**
* Core async init executor size.
*/
private int corePoolSize = Runtime.getRuntime().availableProcessors();

/**
* Max async init executor size.
*/
private int maxPoolSize = corePoolSize * 2;

/**
* Async init executor queue capacity.
*/
private int queueCapacity = 100;

/**
* Timeout in milliseconds to wait for async init tasks.
*/
private long timeoutMillis = 30000;

/**
* Automatic candidate detection mode.
*/
private AsyncInitAutoMode autoMode = AsyncInitAutoMode.CONSERVATIVE;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public int getCorePoolSize() {
return corePoolSize;
}

public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
}

public int getMaxPoolSize() {
return maxPoolSize;
}

public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}

public int getQueueCapacity() {
return queueCapacity;
}

public void setQueueCapacity(int queueCapacity) {
this.queueCapacity = queueCapacity;
}

public long getTimeoutMillis() {
return timeoutMillis;
}

public void setTimeoutMillis(long timeoutMillis) {
this.timeoutMillis = timeoutMillis;
}

public AsyncInitAutoMode getAutoMode() {
return autoMode;
}

public void setAutoMode(AsyncInitAutoMode autoMode) {
this.autoMode = autoMode;
}
}
Loading
Loading