【问题标题】:Using tag() for logging使用 tag() 进行日志记录
【发布时间】:2018-09-21 13:13:23
【问题描述】:

我想使用 tag(key, value) 运算符进行日志记录,将所有 tags() 放入 MDC 并记录它们。

但我似乎无法找到如何做这样的事情?我该如何检索标签???

@Test
public void testTags() {
  List<String> strings = Mono.just("asdf")
      .tag("bla", "blubb")
      .toProcessor()
      .tags()
      .map(Tuple2::toString)
      .collect(Collectors.toList());
  assertEquals("[bla, blubb]", strings); // strings is empty
}

我还不想先使用 toProcessor,因为它会使流变热,我想登录订阅。

--

这一切都在 spring-boot/Webflux 上下文中,我可以在其中使用 WebFilter(忘了提)。下面的答案是从 Webflux 的 MetricsFilter 和另一个博客的 MDC.putCloseable 东西拼凑而成的;希望它可以帮助某人。

【问题讨论】:

    标签: spring-webflux


    【解决方案1】:

    最终使用派生自 MetricsFilter 的 WebFilter 进行此操作

    @Named
    @Order(Ordered.LOWEST_PRECEDENCE)
    public class AuditAccessLogFilter implements WebFilter {
    
      private final Logger log = LoggerFactory.getLogger(getClass());
    
      @Inject
      private Logger AUDIT;
    
      private Authentication anonymousUser = new AnonymousAuthenticationToken("key", "anonymous", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
    
      private static final String hostname;
    
      static {
        try {
          hostname = InetAddress.getLocalHost()
              .getHostName();
        } catch (UnknownHostException e) {
          throw new RuntimeException("Could not find local hostname");
        }
      }
    
      @Value("${spring.application.name}")
      private String appName;
    
      @Value("${server.port}")
      private String serverPort;
    
      public AuditAccessLogFilter() {
        if (StringUtils.isEmpty(appName)) {
          log.warn("Application name is not set, using run directory");
          appName = "-";
        }
    
      }
    
      @Override
      public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return chain.filter(exchange)
            .compose(call -> filter(exchange, call));
      }
    
      private Publisher<Void> filter(ServerWebExchange exchange, Mono<Void> call) {
        long start = System.currentTimeMillis();
        ServerHttpResponse response = exchange.getResponse();
        return Mono.subscriberContext()
            .flatMap(context -> exchange.getPrincipal()
                .switchIfEmpty(Mono.just(anonymousUser))
                .flatMap(principal -> call.doOnSuccess(done -> success(exchange, principal, context, start))
                    .doOnError(cause -> {
                      if (response.isCommitted()) {
                        error(exchange, principal, start, context, cause);
                      }
                      else {
                        response.beforeCommit(() -> {
                          error(exchange, principal, start, context, cause);
                          return Mono.empty();
                        });
                      }
                    })));
      }
    
      private void success(ServerWebExchange exchange, Principal principal, Context context, long start) {
        long timeTaken = System.currentTimeMillis() - start;
        auditLog(() -> AUDIT.info("accesslog"), timeTaken, exchange, principal, context);
      }
    
      private void error(ServerWebExchange exchange, Principal principal, long start, Context context, Throwable cause) {
        long timeTaken = System.nanoTime() - start;
        auditLog(() -> AUDIT.error("accesslog", cause.getMessage()), timeTaken, exchange, principal, context);
      }
    
      private void auditLog(Runnable fun, long timeTaken, ServerWebExchange exchange, Principal principal, Context context) {
        HttpStatus tmpStatusCode = exchange.getResponse()
            .getStatusCode();
        int statusCode = (tmpStatusCode == null ? 0 : tmpStatusCode.value());
    
        String uri = exchange.getRequest()
            .getURI()
            .toString();
        String queryParams = exchange.getRequest()
            .getQueryParams()
            .toString();
        String reasonPhrase = exchange.getResponse()
            .getStatusCode()
            .getReasonPhrase();
        try (MDC.MDCCloseable ignored = MDC.putCloseable("id", context.getOrDefault(GeneralConfig.REQUEST_HASH, "-"));
             MDC.MDCCloseable ignored2 = MDC.putCloseable("responsetimeMs", Long.toString(timeTaken));
             MDC.MDCCloseable ignored3 = MDC.putCloseable("uri", uri);
             MDC.MDCCloseable ignored4 = MDC.putCloseable("user", principal.getName());
             MDC.MDCCloseable ignored5 = MDC.putCloseable("params", queryParams);
             MDC.MDCCloseable ignored6 = MDC.putCloseable("httpCode", Integer.toString(statusCode));
             MDC.MDCCloseable ignored7 = MDC.putCloseable("httpReason", reasonPhrase);
             MDC.MDCCloseable ignored8 = MDC.putCloseable("hostname", hostname + ":" + serverPort);
             MDC.MDCCloseable ignored9 = MDC.putCloseable("appname", appName)) {
          fun.run();
        }
    
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-11
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-04
      相关资源
      最近更新 更多