我想使用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来自另一个Blog;希望对别人有帮助。
答案 0 :(得分:0)
最终使用从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();
}
}
}