/* * 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 org.apache.commons.lang3.ArrayUtils; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpStatus; 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.FetchEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Properties; /** * This extension logs requests to remote systems. * <p> * Be sure to put this extension as the first extension in order to log the whole request time, including all 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>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 FetchLogging implements Extension, IEventListener { private static final String TIME = "org.esigate.time.external"; private static final Logger LOG = LoggerFactory.getLogger(FetchLogging.class); @Override public void init(Driver driver, Properties properties) { driver.getEventManager().register(EventManager.EVENT_FETCH_POST, this); driver.getEventManager().register(EventManager.EVENT_FETCH_PRE, this); } @Override public boolean event(EventDefinition id, Event event) { FetchEvent e = (FetchEvent) event; if (EventManager.EVENT_FETCH_POST.equals(id)) { int statusCode = e.getHttpResponse().getStatusLine().getStatusCode(); // Log only if info or issue if (LOG.isInfoEnabled() || statusCode >= HttpStatus.SC_BAD_REQUEST) { HttpRequest lastRequest = e.getHttpRequest(); String url = lastRequest.getRequestLine().toString(); String status = e.getHttpResponse().getStatusLine().toString(); String reqHeaders = ArrayUtils.toString(lastRequest.getAllHeaders()); String respHeaders = ArrayUtils.toString(e.getHttpResponse().getAllHeaders()); HttpHost targetHost = e.getHttpContext().getTargetHost(); long time = System.currentTimeMillis() - (Long) e.getHttpContext().removeAttribute(TIME, true); StringBuilder logMessage = new StringBuilder(Parameters.SMALL_BUFFER_SIZE); // 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(" - "); } // Url logMessage.append(url); logMessage.append(" "); // request headers logMessage.append(reqHeaders); // Response status logMessage.append(" -> "); logMessage.append(status); // Time logMessage.append(" ("); logMessage.append(time); logMessage.append(" ms) "); // Response headers logMessage.append(respHeaders); if (statusCode >= HttpStatus.SC_BAD_REQUEST) { LOG.warn(logMessage.toString()); } else { LOG.info(logMessage.toString()); } } } else { e.getHttpContext().setAttribute(TIME, System.currentTimeMillis(), true); } // Continue processing return true; } }