diff --git a/eladmin-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java b/eladmin-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java index 3b6dfa6a..0d2b2917 100644 --- a/eladmin-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java +++ b/eladmin-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java @@ -19,6 +19,7 @@ import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import me.zhengjie.modules.security.security.PromethuseResponseFilter; import springfox.documentation.swagger2.annotations.EnableSwagger2; import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties; @@ -33,6 +34,7 @@ import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier; import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier; import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; @@ -96,6 +98,11 @@ public class ConfigurerAdapter implements WebMvcConfigurer { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); List supportMediaTypeList = new ArrayList<>(); supportMediaTypeList.add(MediaType.APPLICATION_JSON); + supportMediaTypeList.add(MediaType.TEXT_PLAIN); + + // Promethuse sends request with header 'Accept: application/openmetrics-text; version=1.0.0; charset=utf-8' + MediaType openMetrics = MediaType.parseMediaType("application/openmetrics-text;version=1.0.0;charset=utf-8"); + supportMediaTypeList.add(openMetrics); FastJsonConfig config = new FastJsonConfig(); config.setDateFormat("yyyy-MM-dd HH:mm:ss"); config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); @@ -120,9 +127,7 @@ public class ConfigurerAdapter implements WebMvcConfigurer { */ @Bean public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, - ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, - CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, - Environment environment) { + ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) { List> allEndpoints = new ArrayList<>(); Collection webEndpoints = webEndpointsSupplier.getEndpoints(); allEndpoints.addAll(webEndpoints); @@ -149,4 +154,22 @@ public class ConfigurerAdapter implements WebMvcConfigurer { return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT)); } + + + /** + * 配置过滤器 + * + * @return + */ + @Bean + public FilterRegistrationBean someFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new PromethuseResponseFilter());// 配置一个返回值过滤器 + registration.addUrlPatterns("/actuator/prometheus"); + registration.addInitParameter("paramName", "paramValue"); + registration.setName("responseFilter"); + return registration; + } + } diff --git a/eladmin-system/src/main/java/me/zhengjie/config/ResponseWrapper.java b/eladmin-system/src/main/java/me/zhengjie/config/ResponseWrapper.java new file mode 100644 index 00000000..8b996e72 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/ResponseWrapper.java @@ -0,0 +1,93 @@ +package me.zhengjie.config; + + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + + +/** + * 返回值输出代理类 + * + * @Title: ResponseWrapper + * @Description: + * @author fei + * @date 2023-07-26 + */ +public class ResponseWrapper extends HttpServletResponseWrapper +{ + + private ByteArrayOutputStream buffer; + + private ServletOutputStream out; + + public ResponseWrapper(HttpServletResponse httpServletResponse) + { + super(httpServletResponse); + buffer = new ByteArrayOutputStream(); + out = new WrapperOutputStream(buffer); + } + + @Override + public ServletOutputStream getOutputStream() + throws IOException + { + return out; + } + + @Override + public void flushBuffer() + throws IOException + { + if (out != null) + { + out.flush(); + } + } + + public byte[] getContent() + throws IOException + { + flushBuffer(); + return buffer.toByteArray(); + } + + class WrapperOutputStream extends ServletOutputStream + { + private ByteArrayOutputStream bos; + + public WrapperOutputStream(ByteArrayOutputStream bos) + { + this.bos = bos; + } + + @Override + public void write(int b) + throws IOException + { + bos.write(b); + } + + @Override + public boolean isReady() + { + + // TODO Auto-generated method stub + return false; + + } + + @Override + public void setWriteListener(WriteListener arg0) + { + + // TODO Auto-generated method stub + + } + } + +} \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/PromethuseResponseFilter.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/PromethuseResponseFilter.java new file mode 100644 index 00000000..8636d2c5 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/PromethuseResponseFilter.java @@ -0,0 +1,40 @@ +package me.zhengjie.modules.security.security; + +import java.io.IOException; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.filter.OncePerRequestFilter; + +import com.alibaba.fastjson.JSON; + +import me.zhengjie.config.ResponseWrapper; + +public class PromethuseResponseFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + + ResponseWrapper wrapperResponse = new ResponseWrapper((HttpServletResponse)response);//转换成代理类 + filterChain.doFilter(request, wrapperResponse); + + byte[] content = wrapperResponse.getContent();//获取返回值 + if (content.length > 0) { + String jsonString = new String(content); + Object plaObject = JSON.parse(jsonString); + //把返回值输出到客户端 + ServletOutputStream out = response.getOutputStream(); + // Prometheus actuator endpoint should produce a text/plain response + // https://github.com/spring-projects/spring-boot/issues/28446 + response.setContentType("text/plain"); + out.write(plaObject.toString().getBytes()); + out.flush(); + out.close(); + } + + } +} diff --git a/eladmin-system/src/main/resources/config/application-dev.yml b/eladmin-system/src/main/resources/config/application-dev.yml index c9deb7a2..e992f102 100644 --- a/eladmin-system/src/main/resources/config/application-dev.yml +++ b/eladmin-system/src/main/resources/config/application-dev.yml @@ -120,7 +120,7 @@ management: endpoints: web: exposure: - include: health,info, metrics, shutdown + include: health,info, metrics, shutdown, prometheus # include: '*' # all # default: http://localhost:8000/actuator/* # base-path: http://localhost:8000/${base-path}/* diff --git a/pom.xml b/pom.xml index 7c58ad30..b1226455 100644 --- a/pom.xml +++ b/pom.xml @@ -95,6 +95,11 @@ spring-boot-starter-actuator + + io.micrometer + micrometer-registry-prometheus + + org.bgee.log4jdbc-log4j2