diff --git a/README.md b/README.md index 378e985..c62e597 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,15 @@ Buildin appender: * console format - * stackdriver format (with support for error reporting) + * Stackdriver format (with support for error reporting) ### Set log level based on MDC values -Confguration: +Configuration: * *enabled*: enable MDC filter (`true` is default) * *key*: MDC key, is optional (will use name instead, see example `user` below) * *level*: log level to use (`TRACE` is default) - * *loggers*: whitelist of logger names, matches all loggers if empty + * *loggers*: passlist of logger names, matches all loggers if empty * *values*: values for matching MDC key, matches all values if empty Example for setting different values for different values/logger: @@ -66,21 +66,32 @@ logger: ### Set log level based on HTTP request header -Confguration: - * *enabled*: enable HTTP request filter (`true` is default) +Configuration for server filter (prefixed with *logger.request.filter*): + * *enabled*: enable HTTP server filter (`true` is default) * *order*: order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/master/core/src/main/java/io/micronaut/core/order/Ordered.java) (highest is default) - * *pattern*: filter pattern (`/**` is default) + * *path*: filter path (`/**` is default) * *header*: name of HTTP header (`x-log-level` is default) + +Configuration for client filter for propagation (prefixed with *logger.request.propagation*): + * *enabled*: enable HTTP client filter (`true` is default) + * *order*: order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/master/core/src/main/java/io/micronaut/core/order/Ordered.java) (tracing is default) + * *path*: filter path (`/**` is default) + * *header*: name of HTTP header (server header is default) Example with default configuration: ``` logger: request: - header: + filter: enabled: true order: -2147483648 - pattern: /** + path: /** header: x-log-level + propagation: + enabled: true + order: 19000 + path: /** + header: ${logger.request.header.header-name} ``` ### Add princial for request to MDC @@ -88,7 +99,7 @@ logger: Confguration: * *enabled*: enable HTTP principal filter (`true` is default) * *order*: order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/master/core/src/main/java/io/micronaut/core/order/Ordered.java) ([ServerFilterPhase.SECURITY.after()](https://github.com/micronaut-projects/micronaut-core/blob/v2.0.1/http/src/main/java/io/micronaut/http/filter/ServerFilterPhase.java#L54) is default) - * *pattern*: filter pattern (`/**` is default) + * *path*: filter path (`/**` is default) * *key*: name of MDC header (`principal` is default) Example with default configuration: @@ -98,7 +109,7 @@ logger: principal: enabled: true order: 39250 - pattern: /** + path: /** key: principal ``` diff --git a/pom.xml b/pom.xml index 1b82a89..2337d50 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ 0.1.5 - 2.0.1 + 2.0.2 diff --git a/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java index 300b57e..e83217c 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java +++ b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java @@ -10,6 +10,7 @@ import io.micronaut.context.annotation.Requires; import io.micronaut.context.env.Environment; import io.micronaut.core.annotation.Internal; import io.micronaut.core.type.Argument; +import io.micronaut.core.util.StringUtils; import lombok.extern.slf4j.Slf4j; /** @@ -19,7 +20,7 @@ import lombok.extern.slf4j.Slf4j; */ @Requires(beans = LogbackUtil.class) @Requires(property = MDCTurboFilterConfigurer.PREFIX) -@Requires(property = MDCTurboFilterConfigurer.ENABLED, notEquals = "false") +@Requires(property = MDCTurboFilterConfigurer.PREFIX + ".enabled", notEquals = StringUtils.FALSE) @BootstrapContextCompatible @Context @Internal @@ -27,7 +28,6 @@ import lombok.extern.slf4j.Slf4j; public class MDCTurboFilterConfigurer { public static final String PREFIX = "logger.mdc"; - public static final String ENABLED = PREFIX + ".enabled"; private final LogbackUtil logback; private final Environment environment; diff --git a/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingClientHttpFilter.java b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingClientHttpFilter.java new file mode 100644 index 0000000..463a070 --- /dev/null +++ b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingClientHttpFilter.java @@ -0,0 +1,56 @@ +package io.kokuwa.micronaut.logging.request; + +import java.util.Optional; + +import org.reactivestreams.Publisher; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.context.annotation.Value; +import io.micronaut.core.util.StringUtils; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MutableHttpRequest; +import io.micronaut.http.annotation.Filter; +import io.micronaut.http.context.ServerRequestContext; +import io.micronaut.http.filter.ClientFilterChain; +import io.micronaut.http.filter.HttpClientFilter; +import io.micronaut.http.filter.ServerFilterPhase; + +/** + * Http request logging filter. + * + * @author Stephan Schnabel + */ +@Requires(beans = HeaderLoggingServerHttpFilter.class) +@Requires(property = HeaderLoggingClientHttpFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE) +@Filter("${" + HeaderLoggingClientHttpFilter.PREFIX + ".path:/**}") +public class HeaderLoggingClientHttpFilter implements HttpClientFilter { + + public static final String PREFIX = "logger.request.propagation"; + public static final int DEFAULT_ORDER = ServerFilterPhase.TRACING.order(); + + private final String serverHeader; + private final String propagationHeader; + private final int order; + + public HeaderLoggingClientHttpFilter( + @Value("${" + HeaderLoggingServerHttpFilter.PREFIX + ".header}") Optional serverHeader, + @Value("${" + PREFIX + ".header}") Optional propagationHeader, + @Value("${" + PREFIX + ".order}") Optional order) { + this.serverHeader = serverHeader.orElse(HeaderLoggingServerHttpFilter.DEFAULT_HEADER); + this.propagationHeader = propagationHeader.orElse(this.serverHeader); + this.order = order.orElse(DEFAULT_ORDER); + } + + @Override + public int getOrder() { + return order; + } + + @Override + public Publisher> doFilter(MutableHttpRequest targetRequest, ClientFilterChain chain) { + ServerRequestContext.currentRequest() + .flatMap(currentRequest -> currentRequest.getHeaders().getFirst(serverHeader)) + .ifPresent(level -> targetRequest.getHeaders().add(propagationHeader, level)); + return chain.proceed(targetRequest); + } +} diff --git a/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingHttpFilter.java b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingServerHttpFilter.java similarity index 66% rename from src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingHttpFilter.java rename to src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingServerHttpFilter.java index bed5fae..f0afce3 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingHttpFilter.java +++ b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingServerHttpFilter.java @@ -12,6 +12,8 @@ import ch.qos.logback.classic.turbo.TurboFilter; import io.kokuwa.micronaut.logging.LogbackUtil; import io.micronaut.context.annotation.Requires; import io.micronaut.context.annotation.Value; +import io.micronaut.core.async.publisher.Publishers; +import io.micronaut.core.util.StringUtils; import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; import io.micronaut.http.annotation.Filter; @@ -26,29 +28,27 @@ import io.micronaut.runtime.server.EmbeddedServer; * @author Stephan Schnabel */ @Requires(beans = EmbeddedServer.class) -@Requires(property = HeaderLoggingHttpFilter.ENABLED, notEquals = "false") -@Filter("${" + HeaderLoggingHttpFilter.PREFIX + ".pattern:" + HeaderLoggingHttpFilter.DEFAULT_PATTERN + ":/**}") -public class HeaderLoggingHttpFilter implements HttpServerFilter { +@Requires(property = HeaderLoggingServerHttpFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE) +@Filter("${" + HeaderLoggingServerHttpFilter.PREFIX + ".path:/**}") +public class HeaderLoggingServerHttpFilter implements HttpServerFilter { - public static final String PREFIX = "logger.request.header"; - public static final String ENABLED = PREFIX + ".enabled"; - public static final String MDC_FILTER = PREFIX + ".filter"; + public static final String PREFIX = "logger.request.filter"; + public static final String MDC_FILTER = PREFIX; public static final String MDC_KEY = "level"; public static final String DEFAULT_HEADER = "x-log-level"; - public static final String DEFAULT_PATTERN = "/**"; public static final int DEFAULT_ORDER = ServerFilterPhase.FIRST.before(); private final LogbackUtil logback; private final String header; private final int order; - public HeaderLoggingHttpFilter( + public HeaderLoggingServerHttpFilter( LogbackUtil logback, - @Value("${" + PREFIX + ".header:" + DEFAULT_HEADER + "}") String header, + @Value("${" + PREFIX + ".header}") Optional header, @Value("${" + PREFIX + ".order}") Optional order) { this.logback = logback; - this.header = header; + this.header = header.orElse(DEFAULT_HEADER); this.order = order.orElse(DEFAULT_ORDER); } @@ -69,7 +69,15 @@ public class HeaderLoggingHttpFilter implements HttpServerFilter { @Override public Publisher> doFilter(HttpRequest request, ServerFilterChain chain) { - request.getHeaders().getFirst(header).ifPresent(level -> MDC.put(MDC_KEY, level)); - return chain.proceed(request); + var level = request.getHeaders().getFirst(header); + if (level.isPresent()) { + MDC.put(MDC_KEY, level.get()); + return Publishers.map(chain.proceed(request), response -> { + MDC.remove(MDC_KEY); + return response; + }); + } else { + return chain.proceed(request); + } } } diff --git a/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingTurboFilter.java b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingTurboFilter.java index 17e42ea..c1a8dc3 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingTurboFilter.java +++ b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingTurboFilter.java @@ -22,7 +22,7 @@ public class HeaderLoggingTurboFilter extends TurboFilter { return FilterReply.NEUTRAL; } - var value = MDC.get(HeaderLoggingHttpFilter.MDC_KEY); + var value = MDC.get(HeaderLoggingServerHttpFilter.MDC_KEY); if (value == null) { return FilterReply.NEUTRAL; } diff --git a/src/main/java/io/kokuwa/micronaut/logging/request/PrincipalHttpFilter.java b/src/main/java/io/kokuwa/micronaut/logging/request/PrincipalHttpFilter.java index 80848e2..0e7a14d 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/request/PrincipalHttpFilter.java +++ b/src/main/java/io/kokuwa/micronaut/logging/request/PrincipalHttpFilter.java @@ -7,6 +7,8 @@ import org.slf4j.MDC; import io.micronaut.context.annotation.Requires; import io.micronaut.context.annotation.Value; +import io.micronaut.core.async.publisher.Publishers; +import io.micronaut.core.util.StringUtils; import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; import io.micronaut.http.annotation.Filter; @@ -21,15 +23,13 @@ import io.micronaut.runtime.server.EmbeddedServer; * @author Stephan Schnabel */ @Requires(beans = EmbeddedServer.class) -@Requires(property = PrincipalHttpFilter.ENABLED, notEquals = "false") -@Filter("${" + PrincipalHttpFilter.PREFIX + ".pattern:" + PrincipalHttpFilter.DEFAULT_PATTERN + ":/**}") +@Requires(property = PrincipalHttpFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE) +@Filter("${" + PrincipalHttpFilter.PREFIX + ".path:/**}") public class PrincipalHttpFilter implements HttpServerFilter { public static final String PREFIX = "logger.request.principal"; - public static final String ENABLED = PREFIX + ".enabled"; public static final String DEFAULT_KEY = "principal"; - public static final String DEFAULT_PATTERN = "/**"; public static final int DEFAULT_ORDER = ServerFilterPhase.SECURITY.after(); private final String key; @@ -49,7 +49,15 @@ public class PrincipalHttpFilter implements HttpServerFilter { @Override public Publisher> doFilter(HttpRequest request, ServerFilterChain chain) { - request.getUserPrincipal().ifPresent(princial -> MDC.put(key, princial.getName())); - return chain.proceed(request); + var princial = request.getUserPrincipal(); + if (princial.isPresent()) { + MDC.put(key, princial.get().getName()); + return Publishers.map(chain.proceed(request), response -> { + MDC.remove(key); + return response; + }); + } else { + return chain.proceed(request); + } } } diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/RequestHeaderTest.java b/src/test/java/io/kokuwa/micronaut/logging/request/RequestHeaderTest.java index b939b95..2b7ee19 100644 --- a/src/test/java/io/kokuwa/micronaut/logging/request/RequestHeaderTest.java +++ b/src/test/java/io/kokuwa/micronaut/logging/request/RequestHeaderTest.java @@ -9,7 +9,7 @@ import ch.qos.logback.classic.Level; import io.kokuwa.micronaut.logging.AbstractTest; /** - * Test for {@link HeaderLoggingHttpFilter}. + * Test for {@link HeaderLoggingServerHttpFilter}. * * @author Stephan Schnabel */ diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/TestClient.java b/src/test/java/io/kokuwa/micronaut/logging/request/TestClient.java index b44495a..669e907 100644 --- a/src/test/java/io/kokuwa/micronaut/logging/request/TestClient.java +++ b/src/test/java/io/kokuwa/micronaut/logging/request/TestClient.java @@ -19,7 +19,7 @@ import io.micronaut.http.client.annotation.Client; import io.micronaut.security.token.jwt.signature.SignatureGeneratorConfiguration; /** - * Contoller for testing {@link HeaderLoggingHttpFilter} and {@link PrincipalHttpFilter}. + * Contoller for testing {@link HeaderLoggingServerHttpFilter} and {@link PrincipalHttpFilter}. * * @author Stephan Schnabel */ @@ -48,7 +48,7 @@ public class TestClient { request.bearerAuth(token); } if (header != null) { - request.getHeaders().add(HeaderLoggingHttpFilter.DEFAULT_HEADER, header); + request.getHeaders().add(HeaderLoggingServerHttpFilter.DEFAULT_HEADER, header); } var response = client.toBlocking().exchange(request, TestResponse.class); diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/TestController.java b/src/test/java/io/kokuwa/micronaut/logging/request/TestController.java index 3d3d6c9..58bdf5b 100644 --- a/src/test/java/io/kokuwa/micronaut/logging/request/TestController.java +++ b/src/test/java/io/kokuwa/micronaut/logging/request/TestController.java @@ -13,7 +13,7 @@ import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; /** - * Controller for testing {@link HeaderLoggingHttpFilter} and {@link PrincipalHttpFilter}. + * Controller for testing {@link HeaderLoggingServerHttpFilter} and {@link PrincipalHttpFilter}. * * @author Stephan Schnabel */