Add new logging starter and refactor logging autoconfiguration

See 'spring-cloud-starter-app-broker-logging'
This commit is contained in:
Roy Clarkson
2020-05-18 14:38:15 -04:00
committed by Roy Clarkson
parent 2ef46ced10
commit 59f6b0ea52
15 changed files with 259 additions and 28 deletions

View File

@@ -11,3 +11,4 @@ include "spring-cloud-app-broker-security-credhub"
include "spring-cloud-app-broker-logging"
include "spring-cloud-starter-app-broker"
include "spring-cloud-starter-app-broker-cloudfoundry"
include "spring-cloud-starter-app-broker-logging"

View File

@@ -26,6 +26,7 @@ dependencies {
compile project(":spring-cloud-app-broker-core")
compile project(":spring-cloud-app-broker-deployer")
compile project(":spring-cloud-app-broker-deployer-cloudfoundry")
optional project(":spring-cloud-app-broker-logging")
compile project(":spring-cloud-app-broker-security-credhub")
compile("org.springframework.boot:spring-boot-starter")
compile("org.cloudfoundry:cloudfoundry-client-reactor:${cfJavaClientVersion}")

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2016-2020 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* https://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,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cloud.appbroker.logging.streaming;
package org.springframework.cloud.appbroker.autoconfigure;
import java.util.HashMap;
import java.util.Map;
@@ -24,8 +24,12 @@ import org.cloudfoundry.doppler.DopplerClient;
import org.cloudfoundry.doppler.Envelope;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.appbroker.logging.streaming.ApplicationLogStreamPublisher;
import org.springframework.cloud.appbroker.logging.streaming.DopplerLogStreamPublisher;
import org.springframework.cloud.appbroker.logging.streaming.LogStreamPublisher;
import org.springframework.cloud.appbroker.logging.streaming.endpoint.StreamingLogWebSocketHandler;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
@@ -36,8 +40,9 @@ import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
@Configuration
@ConditionalOnClass(ApplicationLogStreamPublisher.class)
@ConditionalOnBean(ApplicationIdsProvider.class)
public class ServiceInstanceLogStreamingAutoConfiguration {
public class ServiceInstanceLogStreamAutoConfiguration {
@Bean
public StreamingLogWebSocketHandler streamingLogWebSocketHandler(
@@ -64,11 +69,8 @@ public class ServiceInstanceLogStreamingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public LogStreamPublisher<Envelope> streamLogsPublisher(
CloudFoundryClient cloudFoundryClient,
DopplerClient dopplerClient,
ApplicationIdsProvider applicationIdsProvider
) {
public LogStreamPublisher<Envelope> streamLogsPublisher(CloudFoundryClient cloudFoundryClient,
DopplerClient dopplerClient, ApplicationIdsProvider applicationIdsProvider) {
return new DopplerLogStreamPublisher(cloudFoundryClient, dopplerClient, applicationIdsProvider);
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2016-2020 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* https://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,
@@ -14,26 +14,28 @@
* limitations under the License.
*/
package org.springframework.cloud.appbroker.logging.recent;
package org.springframework.cloud.appbroker.autoconfigure;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.doppler.DopplerClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.appbroker.logging.recent.ApplicationRecentLogsProvider;
import org.springframework.cloud.appbroker.logging.recent.RecentLogsProvider;
import org.springframework.cloud.appbroker.logging.recent.endpoint.RecentLogsController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass(ApplicationRecentLogsProvider.class)
@ConditionalOnBean(ApplicationIdsProvider.class)
public class ServiceInstanceRecentLogsAutoConfiguration {
@Bean
public RecentLogsProvider recentLogsProvider(
CloudFoundryClient cloudFoundryClient,
DopplerClient dopplerClient,
public RecentLogsProvider recentLogsProvider(CloudFoundryClient cloudFoundryClient, DopplerClient dopplerClient,
ApplicationIdsProvider applicationIdsProvider) {
return new ApplicationRecentLogsProvider(cloudFoundryClient, dopplerClient, applicationIdsProvider);
}

View File

@@ -1,4 +1,6 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.appbroker.autoconfigure.AppBrokerAutoConfiguration,\
org.springframework.cloud.appbroker.autoconfigure.CloudFoundryAppDeployerAutoConfiguration,\
org.springframework.cloud.appbroker.autoconfigure.CredHubAutoConfiguration,\
org.springframework.cloud.appbroker.autoconfigure.AppBrokerAutoConfiguration
org.springframework.cloud.appbroker.autoconfigure.ServiceInstanceRecentLogsAutoConfiguration,\
org.springframework.cloud.appbroker.autoconfigure.ServiceInstanceLogStreamAutoConfiguration

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2002-2020 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
*
* https://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 org.springframework.cloud.appbroker.autoconfigure;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.appbroker.logging.streaming.ApplicationLogStreamPublisher;
import org.springframework.cloud.appbroker.logging.streaming.LogStreamPublisher;
import org.springframework.cloud.appbroker.logging.streaming.endpoint.StreamingLogWebSocketHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
import static org.assertj.core.api.Assertions.assertThat;
class ServiceInstanceLogStreamAutoConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
AppBrokerAutoConfiguration.class,
CloudFoundryAppDeployerAutoConfiguration.class,
ServiceInstanceLogStreamAutoConfiguration.class
))
.withPropertyValues(
"spring.cloud.appbroker.deployer.cloudfoundry.api-host=https://api.example.local",
"spring.cloud.appbroker.deployer.cloudfoundry.username=user",
"spring.cloud.appbroker.deployer.cloudfoundry.password=secret"
);
@Test
void servicesAreNotCreatedWithoutLoggingOnClasspath() {
contextRunner
.withClassLoader(new FilteredClassLoader(ApplicationLogStreamPublisher.class))
.withUserConfiguration(LoggingConfiguration.class)
.run(context -> assertThat(context)
.doesNotHaveBean(StreamingLogWebSocketHandler.class)
.doesNotHaveBean(WebSocketHandlerAdapter.class)
.doesNotHaveBean(HandlerMapping.class)
.doesNotHaveBean(LogStreamPublisher.class)
.doesNotHaveBean(ApplicationLogStreamPublisher.class));
}
@Test
void servicesAreNotCreatedWithoutRequiredBeansOnClasspath() {
contextRunner
.run(context -> assertThat(context)
.doesNotHaveBean(StreamingLogWebSocketHandler.class)
.doesNotHaveBean(WebSocketHandlerAdapter.class)
.doesNotHaveBean(HandlerMapping.class)
.doesNotHaveBean(LogStreamPublisher.class)
.doesNotHaveBean(ApplicationLogStreamPublisher.class));
}
@Test
void servicesAreCreatedWithLoggingConfigured() {
contextRunner
.withUserConfiguration(LoggingConfiguration.class)
.run(context -> assertThat(context)
.hasSingleBean(StreamingLogWebSocketHandler.class)
.hasSingleBean(WebSocketHandlerAdapter.class)
.hasSingleBean(HandlerMapping.class)
.hasSingleBean(LogStreamPublisher.class)
.hasSingleBean(ApplicationLogStreamPublisher.class));
}
@TestConfiguration
public static class LoggingConfiguration {
@Bean
public ApplicationIdsProvider applicationIdsProvider() {
return serviceInstanceId -> Flux.just("app1");
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2002-2020 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
*
* https://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 org.springframework.cloud.appbroker.autoconfigure;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.appbroker.logging.recent.ApplicationRecentLogsProvider;
import org.springframework.cloud.appbroker.logging.recent.RecentLogsProvider;
import org.springframework.cloud.appbroker.logging.recent.endpoint.RecentLogsController;
import org.springframework.context.annotation.Bean;
import static org.assertj.core.api.Assertions.assertThat;
class ServiceInstanceRecentLogsAutoConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
AppBrokerAutoConfiguration.class,
CloudFoundryAppDeployerAutoConfiguration.class,
ServiceInstanceRecentLogsAutoConfiguration.class
))
.withPropertyValues(
"spring.cloud.appbroker.deployer.cloudfoundry.api-host=https://api.example.local",
"spring.cloud.appbroker.deployer.cloudfoundry.username=user",
"spring.cloud.appbroker.deployer.cloudfoundry.password=secret"
);
@Test
void servicesAreNotCreatedWithoutLoggingOnClasspath() {
contextRunner
.withClassLoader(new FilteredClassLoader(ApplicationRecentLogsProvider.class))
.withUserConfiguration(LoggingConfiguration.class)
.run(context -> assertThat(context)
.doesNotHaveBean(RecentLogsProvider.class)
.doesNotHaveBean(RecentLogsController.class));
}
@Test
void servicesAreNotCreatedWithoutRequiredBeansOnClasspath() {
contextRunner
.run(context -> assertThat(context)
.doesNotHaveBean(RecentLogsProvider.class)
.doesNotHaveBean(RecentLogsController.class));
}
@Test
void servicesAreCreatedWithLoggingConfigured() {
contextRunner
.withUserConfiguration(LoggingConfiguration.class)
.run(context -> assertThat(context)
.hasSingleBean(RecentLogsProvider.class)
.hasSingleBean(RecentLogsController.class));
}
@TestConfiguration
public static class LoggingConfiguration {
@Bean
public ApplicationIdsProvider applicationIdsProvider() {
return serviceInstanceId -> Flux.just("app1");
}
}
}

View File

@@ -10,10 +10,7 @@ ext {
}
dependencies {
compile "org.springframework:spring-webflux"
compile "org.springframework:spring-context"
compile "org.springframework.boot:spring-boot-autoconfigure"
compile "org.springframework.boot:spring-boot-starter-webflux"
compile "org.cloudfoundry:cloudfoundry-client-reactor:${cfJavaClientVersion}"
compile "org.cloudfoundry:cloudfoundry-operations:${cfJavaClientVersion}"
compile "org.immutables:value:${immutablesVersion}"
@@ -22,6 +19,7 @@ dependencies {
exclude group: 'junit', module: 'junit'
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation(project(":spring-cloud-starter-app-broker-logging"))
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.awaitility:awaitility:${awaitilityVersion}"
}

View File

@@ -26,7 +26,7 @@ import reactor.core.publisher.Flux;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.appbroker.logging.LoggingUtils;
class ApplicationRecentLogsProvider implements RecentLogsProvider {
public class ApplicationRecentLogsProvider implements RecentLogsProvider {
private final CloudFoundryClient client;

View File

@@ -31,7 +31,7 @@ import org.springframework.cloud.appbroker.logging.streaming.events.ServiceInsta
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
class ApplicationLogStreamPublisher implements ApplicationListener<ServiceInstanceLoggingEvent> {
public class ApplicationLogStreamPublisher implements ApplicationListener<ServiceInstanceLoggingEvent> {
private static final Logger LOG = LoggerFactory.getLogger(ApplicationLogStreamPublisher.class);
@@ -41,7 +41,7 @@ class ApplicationLogStreamPublisher implements ApplicationListener<ServiceInstan
private final ApplicationEventPublisher publisher;
protected ApplicationLogStreamPublisher(LogStreamPublisher<Envelope> logStreamPublisher,
public ApplicationLogStreamPublisher(LogStreamPublisher<Envelope> logStreamPublisher,
ApplicationEventPublisher publisher) {
this.logStreamPublisher = logStreamPublisher;
this.publisher = publisher;

View File

@@ -28,7 +28,7 @@ import reactor.core.publisher.Flux;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.appbroker.logging.LoggingUtils;
class DopplerLogStreamPublisher implements LogStreamPublisher<Envelope> {
public class DopplerLogStreamPublisher implements LogStreamPublisher<Envelope> {
private static final Logger LOG = LoggerFactory.getLogger(DopplerLogStreamPublisher.class);

View File

@@ -1,2 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.cloud.appbroker.logging.recent.ServiceInstanceRecentLogsAutoConfiguration,\
org.springframework.cloud.appbroker.logging.streaming.ServiceInstanceLogStreamingAutoConfiguration

View File

@@ -22,9 +22,14 @@ import reactor.core.publisher.Flux;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.servicebroker.autoconfigure.web.ServiceBrokerAutoConfiguration;
import org.springframework.cloud.servicebroker.autoconfigure.web.reactive.ServiceBrokerWebFluxAutoConfiguration;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@SpringBootApplication(exclude = {
ServiceBrokerAutoConfiguration.class,
ServiceBrokerWebFluxAutoConfiguration.class
})
public class RecentLogsTestApp {
static final String APP_ID = UUID.randomUUID().toString();

View File

@@ -23,10 +23,15 @@ import reactor.core.publisher.Flux;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.appbroker.logging.ApplicationIdsProvider;
import org.springframework.cloud.appbroker.logging.streaming.events.StopServiceInstanceLoggingEvent;
import org.springframework.cloud.servicebroker.autoconfigure.web.ServiceBrokerAutoConfiguration;
import org.springframework.cloud.servicebroker.autoconfigure.web.reactive.ServiceBrokerWebFluxAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
@SpringBootApplication
@SpringBootApplication(exclude = {
ServiceBrokerAutoConfiguration.class,
ServiceBrokerWebFluxAutoConfiguration.class
})
public class LogStreamingTestApp {
static final String APP_ID = UUID.randomUUID().toString();

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2002-2020 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
*
* https://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.
*/
description = "Spring Cloud App Broker Starter for Logging"
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
}
}
dependencies {
compile project(":spring-cloud-starter-app-broker")
compile project(":spring-cloud-app-broker-logging")
}
install {
repositories.mavenInstaller {
pom.whenConfigured { generatedPom ->
generatedPom.packaging = "pom"
}
}
}