/* * 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.monitoring; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.ScheduledReporter; import com.codahale.metrics.Slf4jReporter; 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.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.esigate.events.impl.ProxyEvent; import org.esigate.extension.Extension; import org.esigate.util.Parameter; import org.esigate.util.ParameterInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Properties; import java.util.concurrent.TimeUnit; /** * This extension will record proxy request, and backend request to generate statistics. * <p/> * Result will be logged using SLF4J in INFO level every 60 seconds. Period can be configured in driver properties : * <p/> * <code>metricPeriod=60</code> * <p/> * <p/> * Created by alexis on 20/03/14. */ public class Metric implements Extension, IEventListener { private static final Logger LOG = LoggerFactory.getLogger(Metric.class); private static final Parameter<Integer> PARAM_METRIC_PERIOD = new ParameterInteger("metricPeriod", 60); private MetricRegistry metric = new MetricRegistry(); private Driver driver; @Override public void init(Driver d, Properties properties) { this.driver = d; LOG.debug("Initialize Metric"); driver.getEventManager().register(EventManager.EVENT_PROXY_POST, this); driver.getEventManager().register(EventManager.EVENT_FETCH_POST, this); ScheduledReporter reporter = Slf4jReporter.forRegistry(this.metric).outputTo(LOG).convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS).build(); reporter.start(PARAM_METRIC_PERIOD.getValue(properties), TimeUnit.SECONDS); } @Override public boolean event(EventDefinition id, Event event) { String timerName = MetricRegistry.name(this.getClass().getSimpleName(), driver.getConfiguration().getInstanceName(), id.getId()); if (EventManager.EVENT_PROXY_POST.equals(id)) { if (((ProxyEvent) event).getErrorPage() != null) { String statusCode = String.valueOf(((ProxyEvent) event).getErrorPage().getHttpResponse().getStatusLine() .getStatusCode()); timerName = MetricRegistry.name(timerName, "error", statusCode); } } else if (EventManager.EVENT_FETCH_POST.equals(id)) { // Retrieve HTTP response status code and cache status FetchEvent e = (FetchEvent) event; int statusCode = e.getHttpResponse().getStatusLine().getStatusCode(); CacheResponseStatus cacheResponseStatus = (CacheResponseStatus) e.getHttpContext().getAttribute(HttpCacheContext.CACHE_RESPONSE_STATUS); // Adding status code when error if (statusCode >= HttpStatus.SC_BAD_REQUEST) { timerName = MetricRegistry.name(timerName, "error", String.valueOf(statusCode)); } // Adding cache if not MISS if (cacheResponseStatus != null && !cacheResponseStatus.equals(CacheResponseStatus.CACHE_MISS)) { timerName = MetricRegistry.name(timerName, cacheResponseStatus.name().toLowerCase()); } } metric.meter(timerName).mark(); return true; } }