All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.lightbody.bmp.proxy.http.RequestInfo Maven / Gradle / Ivy

The newest version!
package net.lightbody.bmp.proxy.http;

import net.lightbody.bmp.core.har.HarEntry;
import net.lightbody.bmp.core.har.HarTimings;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RequestInfo {
    private static final Logger LOG = LoggerFactory.getLogger(RequestInfo.class);

    private static ThreadLocal instance = new ThreadLocal() {
        @Override
        protected RequestInfo initialValue() {
            return new RequestInfo();
        }
    };

    public static RequestInfo get() {
        return instance.get();
    }

    public static void clear(String url, HarEntry entry) {
        clear();
        RequestInfo info = get();
        info.url = url;
        info.entry = entry;
    }

    private static void clear() {
        RequestInfo info = get();
        info.blockedNanos = -1;
        info.dnsNanos = -1;
        info.connectNanos = -1;
        info.sslNanos = -1;
        info.sendNanos = 0;
        info.waitNanos = 0;
        info.receiveNanos = 0;
        info.resolvedAddress = null;
        info.startDate = null;
        info.startNanos = 0;
        info.endNanos = 0;
    }

    private long blockedNanos;
    private long dnsNanos;
    private long latencyNanos;
    private long connectNanos;
    // ssl timing can be populated from the separate ssl handshake notifier thread
    private volatile long sslNanos;
    private long sendNanos;
    private long waitNanos;
    private long receiveNanos;
    private String resolvedAddress;
    private Date startDate;
    private long startNanos;
    private long endNanos;
    private String url;
    private HarEntry entry;

    private long ping(long start, long end) {
        if (this.startDate == null || this.startNanos == 0) {
            LOG.error("Request start time was not set correctly; using current time");

            if (this.startDate == null) {
                this.startDate = new Date();
            }

            if (this.startNanos == 0) {
                this.startNanos = System.nanoTime();
            }
        }

        return end - start;
    }

    public Long getBlocked() {
        // return blocked;
        // purposely not sending back blocked timings for now until we know it's reliable
        return null;
    }

    public long getDns() {
        return dnsNanos;
    }

    public long getConnect() {
        return connectNanos;
    }

    public long getSsl() {
        return sslNanos;
    }

    public long getSend() {
        return sendNanos;
    }

    public long getWait() {
        return waitNanos;
    }

    public long getReceive() {
        return receiveNanos;
    }

    public String getResolvedAddress() {
        return resolvedAddress;
    }

    public void blocked(long start, long end) {
        // blocked is special - we don't record this start time as we don't want it to count towards receive time and
        // total time
        blockedNanos = end - start;
    }

    public void dns(long start, long end, String resolvedAddress) {
        dnsNanos = ping(start, end);
        this.resolvedAddress = resolvedAddress;
    }

    public void connect(long start, long end) {
        connectNanos = ping(start, end);
    }
    
    public void latency(long start, long end) {
    	latencyNanos = ping(start, end);
	}

    public void ssl(long start, long end) {
        sslNanos = ping(start, end);
    }

    public void send(long start, long end) {
        sendNanos = ping(start, end);
    }

    public void wait(long start, long end) {
        waitNanos = ping(start, end);
    }

    public void start() {
        this.startNanos = System.nanoTime();
        this.startDate = new Date();
    }

    public Date getStartDate() {
        return this.startDate;
    }

    public void finish() {
        if (startDate == null) {
            startDate = new Date();
        }

        if (startNanos == 0) {
            startNanos = System.nanoTime();
        }

        endNanos = System.nanoTime();

        receiveNanos = endNanos - startNanos - norm(waitNanos) - norm(sendNanos) - norm(sslNanos) - norm(connectNanos) - norm(dnsNanos);

        // as per the Har 1.2 spec (to maintain backwards compatibility with 1.1) the connect time should actually
        // include the ssl handshaking time, so doing that here after everything has been calculated
        if (norm(sslNanos) > 0L) {
            connectNanos += sslNanos;
        }

        if (receiveNanos < 0L) {
            LOG.error("Got a negative receiving time ({}) for URL {}", receiveNanos, url);
            receiveNanos = 0L;
        }
    }

    private long norm(Long val) {
        if (val == null || val == -1) {
            return 0;
        } else {
            return val;
        }
    }

    public long getTotalTime(TimeUnit timeUnit) {
        if (endNanos == 0 || startNanos == 0) {
            return -1;
        }

        return timeUnit.convert(endNanos - startNanos, TimeUnit.NANOSECONDS);
    }

    @Override
    public String toString() {
        long totalTimeNanos = getTotalTime(TimeUnit.NANOSECONDS);

        return "RequestInfo{" +
                "blocked=" + blockedNanos + "ns" +
                ", dns=" + dnsNanos + "ns" +
                ", connect=" + connectNanos + "ns" +
                ", ssl=" + sslNanos + "ns" +
                ", send=" + sendNanos + "ns" +
                ", wait=" + waitNanos + "ns" +
                ", receive=" + receiveNanos + "ns" +
                ", total=" + totalTimeNanos + "ns" +
                ", resolvedAddress='" + resolvedAddress + '\'' +
                '}';
    }

    public HarTimings getTimings() {
        HarTimings harTimings = new HarTimings();
        harTimings.setBlocked(blockedNanos, TimeUnit.NANOSECONDS);
        harTimings.setDns(dnsNanos, TimeUnit.NANOSECONDS);
        harTimings.setConnect(connectNanos, TimeUnit.NANOSECONDS);
        harTimings.setSend(sendNanos, TimeUnit.NANOSECONDS);
        harTimings.setWait(waitNanos, TimeUnit.NANOSECONDS);
        harTimings.setReceive(receiveNanos, TimeUnit.NANOSECONDS);
        harTimings.setSsl(sslNanos, TimeUnit.NANOSECONDS);

        return harTimings;
    }

    public HarEntry getEntry() {
        return entry;
    }

	public long getLatency(TimeUnit timeUnit) {
		return timeUnit.convert(latencyNanos, TimeUnit.NANOSECONDS);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy