All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vrap.rmf.base.client.http.InternalLoggerMiddlewareImpl Maven / Gradle / Ivy

There is a newer version: 17.17.0
Show newest version

package io.vrap.rmf.base.client.http;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.function.Function;

import io.vrap.rmf.base.client.*;
import io.vrap.rmf.base.client.error.ConcurrentModificationException;
import io.vrap.rmf.base.client.utils.json.JsonException;
import io.vrap.rmf.base.client.utils.json.JsonUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.slf4j.event.Level;

/**
 * 

Default implementation for the {@link InternalLoggerMiddleware}

*/ class InternalLoggerMiddlewareImpl implements InternalLoggerMiddleware { private static final Logger classLogger = LoggerFactory.getLogger(InternalLoggerMiddlewareImpl.class); private final InternalLoggerFactory factory; private final Level deprecationLogEvent; private final Level responseLogEvent; private final Level defaultExceptionLogEvent; private final Map, Level> exceptionLogEvents; public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory) { this(factory, Level.INFO, Level.INFO); } public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory, final Level responseLogEvent, Level deprecationLogEvent) { this(factory, responseLogEvent, deprecationLogEvent, Level.ERROR, Collections.singletonMap(ConcurrentModificationException.class, Level.INFO)); } public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory, final Level responseLogEvent, final Level deprecationLogEvent, final Level defaultExceptionLogEvent, final Map, Level> exceptionLogEvents) { this.factory = factory; this.responseLogEvent = responseLogEvent; this.deprecationLogEvent = deprecationLogEvent; this.defaultExceptionLogEvent = defaultExceptionLogEvent; this.exceptionLogEvents = exceptionLogEvents; } @Override public CompletableFuture> invoke(final ApiHttpRequest request, final Function>> next) { final InternalLogger logger = factory.createFor(request, InternalLogger.TOPIC_REQUEST); final Optional requestContext = Optional.ofNullable(request.getContext(MDCContext.class)); requestContext.ifPresent(c -> MDC.setContextMap(c.getValue())); logger.debug(() -> request); logger.trace(() -> { final String output; final String httpMethodAndUrl = request.getMethod().name() + " " + request.getUrl().toString(); if (request.getBody() != null) { final String unformattedBody = request.getSecuredBody(); final boolean isJsonRequest = request.getHeaders() .getHeaders(ApiHttpHeaders.CONTENT_TYPE) .stream() .findFirst() .map(ct -> ct.getValue().toLowerCase().contains("json")) .orElse(true); if (isJsonRequest) { String prettyPrint; try { prettyPrint = JsonUtils.prettyPrint(unformattedBody); } catch (final JsonException e) { classLogger.warn("pretty print failed", e); prettyPrint = unformattedBody; } output = "send: " + httpMethodAndUrl + "\nformatted: " + prettyPrint; } else { output = "send: " + request.getMethod().name() + " " + request.getUrl() + " " + unformattedBody; } } else { output = httpMethodAndUrl + " "; } return output; }); requestContext.ifPresent(c -> MDC.clear()); final long startTime = System.currentTimeMillis(); return next.apply(request).whenComplete((response, throwable) -> { final long executionTime = System.currentTimeMillis() - startTime; final InternalLogger responseLogger = factory.createFor(request, InternalLogger.TOPIC_RESPONSE); if (throwable != null) { requestContext.ifPresent(c -> MDC.setContextMap(c.getValue())); Throwable cause = throwable instanceof CompletionException ? throwable.getCause() : throwable; if (cause instanceof ApiHttpException) { final ApiHttpResponse errorResponse = ((ApiHttpException) throwable.getCause()) .getResponse(); final Level level = exceptionLogEvents.entrySet() .stream() .filter(classLevelEntry -> classLevelEntry.getKey() .isAssignableFrom(throwable.getCause().getClass())) .findFirst() .map(Map.Entry::getValue) .orElse(defaultExceptionLogEvent); responseLogger.log(level, () -> String .format("%s %s %s %s %s %s", request.getMethod().name(), request.getUrl(), errorResponse.getStatusCode(), executionTime, Optional.ofNullable(errorResponse.getHeaders().getFirst(ApiHttpHeaders.SERVER_TIMING)) .orElse("-"), Optional.ofNullable( errorResponse.getHeaders().getFirst(ApiHttpHeaders.X_CORRELATION_ID)).orElse("-")) .trim()); final List> notices = errorResponse.getHeaders() .getHeaders(ApiHttpHeaders.X_DEPRECATION_NOTICE); if (notices != null) { notices.forEach( message -> logger.log(deprecationLogEvent, () -> "Deprecation notice: " + message)); } responseLogger.debug(() -> errorResponse, throwable); responseLogger.trace(() -> errorResponse.getStatusCode() + "\n" + Optional.ofNullable(errorResponse.getBody()) .map(body -> JsonUtils.prettyPrint(errorResponse.getBodyAsString().orElse(""))) .orElse("")); } else { final Level level = exceptionLogEvents.entrySet() .stream() .filter(classLevelEntry -> classLevelEntry.getKey() .isAssignableFrom(throwable.getCause().getClass())) .findFirst() .map(Map.Entry::getValue) .orElse(defaultExceptionLogEvent); responseLogger.log(level, throwable::getCause, throwable); } requestContext.ifPresent(c -> MDC.clear()); } else { final Optional responseContext = Optional.ofNullable(response.getContext(MDCContext.class)); responseContext.ifPresent(c -> MDC.setContextMap(c.getValue())); responseLogger.log(responseLogEvent, () -> String.format("%s %s %s %s %s %s", request.getMethod().name(), request.getUrl(), response.getStatusCode(), executionTime, Optional.ofNullable(response.getHeaders().getFirst(ApiHttpHeaders.SERVER_TIMING)).orElse("-"), Optional.ofNullable(response.getHeaders().getFirst(ApiHttpHeaders.X_CORRELATION_ID)).orElse("-")) .trim()); final List> notices = response.getHeaders() .getHeaders(ApiHttpHeaders.X_DEPRECATION_NOTICE); if (notices != null) { notices.forEach(message -> logger.log(deprecationLogEvent, () -> "Deprecation notice: " + message)); } responseLogger.debug(() -> response); responseLogger.trace(() -> response.getStatusCode() + "\n" + Optional.ofNullable(response.getBody()) .map(body -> JsonUtils.prettyPrint(response.getBodyAsString().orElse(""))) .orElse("")); responseContext.ifPresent(c -> MDC.clear()); } }); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy