package com.github.bingoohuang.springrestclient.utils; import com.github.bingoohuang.springrestclient.provider.SignProvider; import com.google.common.base.Charsets; import com.google.common.base.Joiner; import com.google.common.io.ByteStreams; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.request.HttpRequest; import com.mashape.unirest.request.body.Body; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.InputStream; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.regex.Pattern; import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; @Slf4j public class RestLog { private final String syncOrAsync; private final String uuid = UUID.randomUUID().toString(); private final Logger logger; private final Class<?> apiClass; private long start; public RestLog(Class<?> apiClass, boolean async) { this.apiClass = apiClass; this.syncOrAsync = async ? "asyn" : "sync"; this.logger = LoggerFactory.getLogger(apiClass); } public void logAndSign(SignProvider signProvider, Map<String, Object> requestParams, HttpRequest httpRequest) { if (!logger.isInfoEnabled()) return; signReq(signProvider, requestParams, httpRequest); this.start = System.currentTimeMillis(); String methodName = httpRequest.getHttpMethod().name(); String url = UrlDecodes.decodeQuietly(httpRequest.getUrl()); String headers = buildHeaders(httpRequest.getHeaders()); List<String> contentTypes = httpRequest.getHeaders().get("Content-Type"); String contentType = contentTypes != null && contentTypes.size() > 0 ? contentTypes.get(0) : null; String body = getBodyAsString(requestParams, httpRequest); logger.info("spring rest client {} {} request: {} {} headers:{} body: {}", syncOrAsync, uuid, methodName, url, headers, singleLine(contentType, body)); } private void signReq(SignProvider signProvider, Map<String, Object> requestParams, HttpRequest httpRequest) { if (signProvider == null) return; signProvider.sign(apiClass, uuid, requestParams, httpRequest); } private String getBodyAsString(Map<String, Object> requestParams, HttpRequest httpRequest) { try { Body body = httpRequest.getBody(); if (body == null) return ""; HttpEntity entity = body.getEntity(); // MultipartFormEntity // StringEntity // UrlEncodedFormEntity; InputStream context = entity.getContent(); return new String(ByteStreams.toByteArray(context), Charsets.UTF_8); } catch (UnsupportedOperationException e) { return requestParams.toString(); } catch (Exception e) { log.warn("exception:{}", e.toString()); return requestParams.toString(); } } public void log(Throwable e) { if (!logger.isWarnEnabled()) return; long costTimeMillis = System.currentTimeMillis() - start; logger.warn("spring rest client {} {} exception: cost {} millis", syncOrAsync, uuid, costTimeMillis, e); } public void log(HttpResponse<?> response) { if (!logger.isInfoEnabled()) return; int status = response.getStatus(); String headers = buildHeaders(response.getHeaders()); String contentType = response.getHeaders().getFirst("Content-Type"); Object body = response.getBody(); long costTimeMillis = System.currentTimeMillis() - start; if (status >= 200 & status < 300) logger.info("spring rest client {} {} response: cost {} millis, {} headers:{} body: {}", syncOrAsync, uuid, costTimeMillis, status, headers, singleLine(contentType, body)); else logger.error("spring rest client {} {} response: cost {} millis, {} headers:{} body: {}", syncOrAsync, uuid, costTimeMillis, status, headers, singleLine(contentType, body)); } public void log(String status) { if (!logger.isInfoEnabled()) return; long costTimeMillis = System.currentTimeMillis() - start; logger.info("spring rest client {} {} {}: cost {} millis", syncOrAsync, uuid, status, costTimeMillis); } private String buildHeaders(Map<String, List<String>> headers) { return Joiner.on('&').withKeyValueSeparator("=").join(headers); } static Pattern lineBreakPattern = Pattern.compile("(\\r?\\n)+"); public String singleLine(String contentType, Object object) { if (containsIgnoreCase(contentType, "image")) return "<image>"; if (object instanceof InputStream) return "<inputstream>"; String str = "" + object; String s = lineBreakPattern.matcher(str).replaceAll("\\n"); if (containsIgnoreCase(contentType, "json")) return s; return UrlDecodes.decodeQuietly(s); } }