// *************************************************************************************************************************** | |
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * | |
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * | |
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * | |
// * with the License. You may obtain a copy of the License at * | |
// * * | |
// * http://www.apache.org/licenses/LICENSE-2.0 * | |
// * * | |
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * | |
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * | |
// * specific language governing permissions and limitations under the License. * | |
// *************************************************************************************************************************** | |
package org.apache.juneau.rest.client; | |
import static org.apache.juneau.internal.StringUtils.*; | |
import java.io.*; | |
import java.util.logging.*; | |
import org.apache.http.*; | |
import org.apache.http.client.methods.*; | |
import org.apache.http.util.*; | |
/** | |
* Specialized interceptor for logging calls to a log file. | |
* | |
* <p> | |
* Causes a log entry to be created that shows all the request and response headers and content at the end of the | |
* request. | |
* | |
* <p> | |
* Use the {@link RestClientBuilder#logTo(Level, Logger)} and {@link RestCall#logTo(Level, Logger)} methods to create | |
* instances of this class. | |
*/ | |
public class RestCallLogger extends RestCallInterceptor { | |
/** | |
* Default HTTP request logger. | |
* <p> | |
* Logs outgoing HTTP requests to the <c>org.apache.juneau.rest.client</c> logger at <jsf>WARNING</jsf> level. | |
*/ | |
public static final RestCallLogger DEFAULT = new RestCallLogger(Level.WARNING, Logger.getLogger("org.apache.juneau.rest.client")); | |
private Level level; | |
private Logger log; | |
/** | |
* Constructor. | |
* | |
* @param level The log level to log messages at. | |
* @param log The logger to log to. | |
*/ | |
protected RestCallLogger(Level level, Logger log) { | |
this.level = level; | |
this.log = log; | |
} | |
@Override /* RestCallInterceptor */ | |
public void onInit(RestCall restCall) { | |
if (log.isLoggable(level)) | |
restCall.captureResponse(); | |
} | |
@Override /* RestCallInterceptor */ | |
public void onConnect(RestCall restCall, int statusCode, HttpRequest req, HttpResponse res) { | |
// Do nothing. | |
} | |
@Override /* RestCallInterceptor */ | |
public void onRetry(RestCall restCall, int statusCode, HttpRequest req, HttpResponse res, Exception ex) { | |
if (log.isLoggable(level)) { | |
if (ex == null) | |
log.log(level, format("Call to {0} returned {1}. Will retry.", req.getRequestLine().getUri(), statusCode)); | |
else | |
log.log(level, format("Call to {0} caused exception {1}. Will retry.", req.getRequestLine().getUri(), ex.getLocalizedMessage()), ex); | |
} | |
} | |
@Override /* RestCallInterceptor */ | |
public void onClose(RestCall restCall) throws RestCallException { | |
try { | |
if (log.isLoggable(level)) { | |
String output = restCall.getCapturedResponse(); | |
StringBuilder sb = new StringBuilder(); | |
HttpUriRequest req = restCall.getRequest(); | |
HttpResponse res = restCall.getResponse(); | |
if (req != null) { | |
sb.append("\n=== HTTP Call (outgoing) ======================================================="); | |
sb.append("\n=== REQUEST ===\n").append(req); | |
sb.append("\n---request headers---"); | |
for (Header h : req.getAllHeaders()) | |
sb.append("\n\t").append(h); | |
if (req instanceof HttpEntityEnclosingRequestBase) { | |
sb.append("\n---request entity---"); | |
HttpEntityEnclosingRequestBase req2 = (HttpEntityEnclosingRequestBase)req; | |
HttpEntity e = req2.getEntity(); | |
if (e == null) | |
sb.append("\nEntity is null"); | |
else { | |
if (e.getContentType() != null) | |
sb.append("\n").append(e.getContentType()); | |
if (e.getContentEncoding() != null) | |
sb.append("\n").append(e.getContentEncoding()); | |
if (e.isRepeatable()) { | |
try { | |
sb.append("\n---request content---\n").append(EntityUtils.toString(e)); | |
} catch (Exception ex) { | |
throw new RuntimeException(ex); | |
} | |
} | |
} | |
} | |
} | |
if (res != null) { | |
sb.append("\n=== RESPONSE ===\n").append(res.getStatusLine()); | |
sb.append("\n---response headers---"); | |
for (Header h : res.getAllHeaders()) | |
sb.append("\n\t").append(h); | |
sb.append("\n---response content---\n").append(output); | |
sb.append("\n=== END ========================================================================"); | |
} | |
log.log(level, sb.toString()); | |
} | |
} catch (IOException e) { | |
log.log(Level.SEVERE, e.getLocalizedMessage(), e); | |
} | |
} | |
} |