受某些大厂的影响,很多开发人员只使用Http 200状态码,而在响应体的内部定义自身的响应码来表示错误信息,这样导致了现有的监控库并不能有效的监控到API的错误响应。考虑到大量API的改造工作量,所以最简单快速的方法还是改造监控的库,添加上自定义错误码的采集。

集成 Actuator

项目添加如下maven依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

NOTE:Actuator 1.x和2.x是不兼容的,建议使用2.x版本。

配置 Actuator Metrics

Actuator 2.x的端口默认是关闭的,需要通过配置打开,特别是生产环境更需要小心公开的API。

management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus
  metrics:
    tags:
      application: actuator-demo #应用名称
      version: 1.0.0 #应用版本

获取自定义响应码

实现ResponseBodyAdvice接口,获取自定义响应码

public class CustomizedErrorCodeControllerAdvice implements ResponseBodyAdvice<Object> {
    private final Map<Class<?>, Function<Object, String>> classFunctionMap = new ConcurrentHashMap<>();

    public CustomizedErrorCodeControllerAdvice(Map<Class<?>, Function<Object, String>> maps) {
        classFunctionMap.putAll(maps);
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // 非空判断,如果为空xxx.isAssignableFrom总是真
        if (null != o && serverHttpRequest instanceof ServletServerHttpRequest) {
            HttpServletRequest httpServletRequest = ((ServletServerHttpRequest) serverHttpRequest).getServletRequest();
            for (Map.Entry<Class<?>, Function<Object, String>> entry : classFunctionMap.entrySet()) {
                if (entry.getKey().isAssignableFrom(o.getClass())) {
                    String errorCode = entry.getValue().apply(o);
                    httpServletRequest.setAttribute(CustomizedErrorCodeContributor.REQUEST_ATTRIBUTE, errorCode);

                    break;
                }
            }
        }
        return o;
    }

为指标添加自定义响应码

实现WebMvcTagsContributor接口,为指标添加自定义响应码。

@Component
public class CustomizedErrorCodeContributor implements WebMvcTagsContributor {
    public static final String REQUEST_ATTRIBUTE = "__actuator_demo_customized_error_code.Request.Attribute";
    private static final String ERROR_CODE_TAG = "business_code";

    @Override
    public Iterable<Tag> getTags(HttpServletRequest request HttpServletResponse response, Object handler, Throwable exception) {
        Object attr = request.getAttribute(REQUEST_ATTRIBUTE);
        if (attr instanceof String) {
            return Tags.of(ERROR_CODE_TAG, (String) attr);
        }

        return Tags.empty();
    }

    @Override
    public Iterable<Tag> getLongRequestTags(HttpServletRequest request, Object handler) {
        return Tags.empty();
    }
}