GH-766 Initial support to expose FunctionCatalog as actuator endpoint
This commit is contained in:
@@ -43,9 +43,9 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.module</groupId>
|
<groupId>com.fasterxml.jackson.module</groupId>
|
||||||
<artifactId>jackson-module-kotlin</artifactId>
|
<artifactId>jackson-module-kotlin</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>com.vaadin.external.google</groupId>
|
<groupId>com.vaadin.external.google</groupId>
|
||||||
<artifactId>android-json</artifactId>
|
<artifactId>android-json</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- KOTLIN -->
|
<!-- KOTLIN -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
@@ -109,10 +109,17 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.cloudevents</groupId>
|
<groupId>io.cloudevents</groupId>
|
||||||
<artifactId>cloudevents-spring</artifactId>
|
<artifactId>cloudevents-spring</artifactId>
|
||||||
<version>2.2.0</version>
|
<version>2.2.0</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Actuator -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ public class SimpleFunctionRegistry implements FunctionRegistry, FunctionInspect
|
|||||||
|
|
||||||
|
|
||||||
public boolean isPrototype() {
|
public boolean isPrototype() {
|
||||||
return this.isPrototype();
|
return !this.isSingleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSkipInputConversion(boolean skipInputConversion) {
|
public void setSkipInputConversion(boolean skipInputConversion) {
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021-2021 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.function.context.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.cloud.function.context.FunctionCatalog;
|
||||||
|
import org.springframework.cloud.function.endpoint.FunctionsEndpoint;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Oleg Zhurakousky
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(name = {
|
||||||
|
"org.springframework.boot.actuate.endpoint.annotation.Endpoint" })
|
||||||
|
@ConditionalOnBean(FunctionCatalog.class)
|
||||||
|
@AutoConfigureAfter(EndpointAutoConfiguration.class)
|
||||||
|
public class FunctionsEndpointAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnAvailableEndpoint
|
||||||
|
public FunctionsEndpoint bindingsEndpoint(FunctionCatalog functionCatalog) {
|
||||||
|
return new FunctionsEndpoint(functionCatalog);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021-2021 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.function.endpoint;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||||
|
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||||
|
import org.springframework.cloud.function.context.FunctionCatalog;
|
||||||
|
import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper;
|
||||||
|
import org.springframework.cloud.function.json.JsonMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Actuator endpoint to access {@link FunctionCatalog}
|
||||||
|
*
|
||||||
|
* @author Oleg Zhurakousky
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@Endpoint(id = "functions")
|
||||||
|
public class FunctionsEndpoint {
|
||||||
|
|
||||||
|
private final FunctionCatalog functionCatalog;
|
||||||
|
|
||||||
|
public FunctionsEndpoint(FunctionCatalog functionCatalog) {
|
||||||
|
this.functionCatalog = functionCatalog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadOperation
|
||||||
|
public Map<String, Map<String, Object>> listAll() {
|
||||||
|
Map<String, Map<String, Object>> allFunctions = new TreeMap<>();
|
||||||
|
Set<String> names = functionCatalog.getNames(null);
|
||||||
|
for (String name : names) {
|
||||||
|
FunctionInvocationWrapper function = functionCatalog.lookup(name);
|
||||||
|
Map<String, Object> functionMap = new LinkedHashMap<>();
|
||||||
|
if (function.isFunction()) {
|
||||||
|
functionMap.put("type", "FUNCTION");
|
||||||
|
functionMap.put("input-type", function.getInputType().toString());
|
||||||
|
functionMap.put("output-type", function.getOutputType().toString());
|
||||||
|
}
|
||||||
|
else if (function.isConsumer()) {
|
||||||
|
functionMap.put("type", "CONSUMER");
|
||||||
|
functionMap.put("input-type", function.getInputType().toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
functionMap.put("type", "SUPPLIER");
|
||||||
|
functionMap.put("output-type", function.getOutputType().toString());
|
||||||
|
}
|
||||||
|
allFunctions.put(name, functionMap);
|
||||||
|
}
|
||||||
|
return allFunctions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration,\
|
org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration,\
|
||||||
org.springframework.cloud.function.cloudevent.CloudEventsFunctionExtensionConfiguration,\
|
org.springframework.cloud.function.cloudevent.CloudEventsFunctionExtensionConfiguration,\
|
||||||
org.springframework.cloud.function.context.config.KotlinLambdaToFunctionAutoConfiguration
|
org.springframework.cloud.function.context.config.KotlinLambdaToFunctionAutoConfiguration,\
|
||||||
|
org.springframework.cloud.function.context.config.FunctionsEndpointAutoConfiguration
|
||||||
org.springframework.cloud.function.context.WrapperDetector=\
|
org.springframework.cloud.function.context.WrapperDetector=\
|
||||||
org.springframework.cloud.function.context.config.FluxWrapperDetector
|
org.springframework.cloud.function.context.config.FluxWrapperDetector
|
||||||
org.springframework.context.ApplicationContextInitializer=\
|
org.springframework.context.ApplicationContextInitializer=\
|
||||||
|
|||||||
@@ -26,6 +26,10 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-function-webflux</artifactId>
|
<artifactId>spring-cloud-starter-function-webflux</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ import reactor.core.publisher.Flux;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
|
||||||
// @checkstyle:off
|
// @checkstyle:off
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class SampleApplication {
|
public class SampleApplication {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
SpringApplication.run(SampleApplication.class, args);
|
SpringApplication.run(SampleApplication.class, "--management.endpoints.web.exposure.include=functions");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -38,6 +39,11 @@ public class SampleApplication {
|
|||||||
return value -> value.toUpperCase();
|
return value -> value.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Function<Message<String>, String> uppercaseMessage() {
|
||||||
|
return value -> value.getPayload().toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Function<Flux<String>, Flux<String>> lowercase() {
|
public Function<Flux<String>, Flux<String>> lowercase() {
|
||||||
return flux -> flux.map(value -> value.toLowerCase());
|
return flux -> flux.map(value -> value.toLowerCase());
|
||||||
|
|||||||
Reference in New Issue
Block a user