FragmentLogging.java
/*
* Licensed 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.esigate.extension;
import java.util.Properties;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpStatus;
import org.apache.http.client.cache.CacheResponseStatus;
import org.apache.http.client.cache.HttpCacheContext;
import org.esigate.Driver;
import org.esigate.Parameters;
import org.esigate.events.Event;
import org.esigate.events.EventDefinition;
import org.esigate.events.EventManager;
import org.esigate.events.IEventListener;
import org.esigate.events.impl.FragmentEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This extension logs fragments usage.
* <p>
* Be sure to put this extension as the first extension in order to log the whole fragment processing time, including
* all other extension processing.
*
* <p>
* Log level is :
* <ul>
* <li>WARN for status codes >= 400</li>
* <li>INFO for other codes</li>
* </ul>
* <p>
* Logged data are :
*
* <ul>
* <li>Provider name</li>
* <li>Request status line</li>
* <li>Request headers</li>
* <li>Response status line</li>
* <li>Response headers</li>
* <li>Cache status (HIT, MISS, ...)</li>
* <li>Request time</li>
*
* </ul>
*
*
* @author Nicolas Richeton
*
*/
public class FragmentLogging implements Extension, IEventListener {
private static final String TIME = "org.esigate.time";
private static final Logger LOG = LoggerFactory.getLogger(FragmentLogging.class);
private Driver driver;
@Override
public void init(Driver pDriver, Properties properties) {
this.driver = pDriver;
this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_POST, this);
this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_PRE, this);
}
@Override
public boolean event(EventDefinition id, Event event) {
FragmentEvent e = (FragmentEvent) event;
if (EventManager.EVENT_FRAGMENT_PRE.equals(id)) {
// Keep track of the start time.
e.getHttpContext().setAttribute(TIME, System.currentTimeMillis(), true);
} else {
int statusCode = e.getHttpResponse().getStatusLine().getStatusCode();
// Log only if info or issue
if (LOG.isInfoEnabled() || statusCode >= HttpStatus.SC_BAD_REQUEST) {
// Log last result only
HttpRequest httpRequest = e.getHttpContext().getSentRequest();
// Create log message
HttpHost targetHost = e.getHttpContext().getTargetHost();
String requestLine = httpRequest.getRequestLine().toString();
String statusLine = e.getHttpResponse().getStatusLine().toString();
String reqHeaders = ArrayUtils.toString(httpRequest.getAllHeaders());
String respHeaders = ArrayUtils.toString(e.getHttpResponse().getAllHeaders());
String cache = "";
CacheResponseStatus cacheResponseStatus =
(CacheResponseStatus) e.getHttpContext().getAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS);
if (cacheResponseStatus != null) {
cache = cacheResponseStatus.toString();
}
long time = System.currentTimeMillis() - (Long) e.getHttpContext().removeAttribute(TIME, true);
StringBuilder logMessage = new StringBuilder(Parameters.SMALL_BUFFER_SIZE);
logMessage.append(driver.getConfiguration().getInstanceName());
logMessage.append(" ");
// Display target host, protocol and port
if (targetHost != null) {
logMessage.append(targetHost.getSchemeName());
logMessage.append("://");
logMessage.append(targetHost.getHostName());
if (targetHost.getPort() != -1) {
logMessage.append(":");
logMessage.append(targetHost.getPort());
}
logMessage.append(" - ");
}
logMessage.append(requestLine).append(" ").append(reqHeaders).append(" -> ").append(statusLine)
.append(" (").append(time).append(" ms) ").append(cache).append(" ").append(respHeaders);
// Log level according to status code.
if (statusCode >= HttpStatus.SC_BAD_REQUEST) {
LOG.warn(logMessage.toString());
} else {
LOG.info(logMessage.toString());
}
}
}
// Continue processing
return true;
}
}