RequestLoggerImpl.java 5.94 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.servlet.Filter
 *  javax.servlet.FilterChain
 *  javax.servlet.FilterConfig
 *  javax.servlet.ServletException
 *  javax.servlet.ServletRequest
 *  javax.servlet.ServletResponse
 *  javax.servlet.http.HttpServletRequest
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Deactivate
 *  org.apache.felix.scr.annotations.Modified
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.commons.metrics.MetricsService
 *  org.apache.sling.commons.metrics.Timer
 *  org.apache.sling.commons.metrics.Timer$Context
 *  org.apache.sling.commons.osgi.PropertiesUtil
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.requests.logging.impl;

import com.adobe.granite.requests.logging.api.RequestLogger;
import com.adobe.granite.requests.logging.api.TimedRequest;
import com.adobe.granite.requests.logging.impl.TimedRequestImpl;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableSet;
import java.util.concurrent.ConcurrentSkipListSet;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.commons.metrics.MetricsService;
import org.apache.sling.commons.metrics.Timer;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(immediate=1, metatype=1, label="Adobe Granite Timed Requests Logger")
@Service(value={Runnable.class, RequestLogger.class, Filter.class})
@Properties(value={@Property(name="scheduler.expression", value={"*/10 * * * * ?"}), @Property(name="scheduler.concurrent", boolValue={0}, propertyPrivate=1), @Property(name="sling.filter.scope", value={"REQUEST"}), @Property(name="service.ranking", intValue={Integer.MIN_VALUE})})
public final class RequestLoggerImpl
implements Runnable,
RequestLogger,
Filter {
    private static final Logger logger = LoggerFactory.getLogger(RequestLoggerImpl.class);
    @Property(label="Longest requests history size", description="The number of longest requests stored for analysis.", intValue={20})
    public static final String LONG_REQUEST_HISTORY_SIZE = "long.requests.history.size";
    @Reference
    private MetricsService metricsService;
    private static Timer timer;
    private NavigableSet<TimedRequest> longestRequests;
    private static int historySize;

    @Activate
    protected void activate(Map<String, Object> props) throws Exception {
        this.setProperties(props);
        this.longestRequests = new ConcurrentSkipListSet<TimedRequest>();
        timer = this.metricsService.timer("granite.request.metrics.timer");
    }

    @Modified
    protected void update(Map<String, Object> props) throws Exception {
        this.setProperties(props);
    }

    private void setProperties(Map<String, Object> props) throws Exception {
        historySize = PropertiesUtil.toInteger((Object)props.get("long.requests.history.size"), (int)20);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req;
        if (request instanceof HttpServletRequest) {
            req = (HttpServletRequest)request;
            String path = req.getPathInfo().toLowerCase();
            if (!(path.startsWith("/content/") || path.contains(".html") || path.startsWith("/etc/design"))) {
                chain.doFilter(request, response);
                return;
            }
        } else {
            chain.doFilter(request, response);
            return;
        }
        long reqTime = System.currentTimeMillis();
        Timer.Context context = timer.time();
        try {
            chain.doFilter(request, response);
        }
        finally {
            long respTime = System.currentTimeMillis();
            long duration = respTime - reqTime;
            this.longestRequests.add(new TimedRequestImpl(req, duration, reqTime));
            context.stop();
        }
    }

    @Override
    public void run() {
        this.cleanShortRequests();
    }

    @Override
    public TimedRequest[] getLongestRequests() {
        this.cleanShortRequests();
        return this.longestRequests.descendingSet().toArray(new TimedRequest[0]);
    }

    public void destroy() {
    }

    @Deactivate
    protected void deactivate() {
        this.longestRequests.clear();
        this.longestRequests = null;
    }

    private void cleanShortRequests() {
        Iterator<TimedRequest> longReqIt = this.longestRequests.iterator();
        for (int size = this.longestRequests.size(); longReqIt.hasNext() && size > historySize; --size) {
            TimedRequest tr = longReqIt.next();
            longReqIt.remove();
        }
    }

    protected void bindMetricsService(MetricsService metricsService) {
        this.metricsService = metricsService;
    }

    protected void unbindMetricsService(MetricsService metricsService) {
        if (this.metricsService == metricsService) {
            this.metricsService = null;
        }
    }
}