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

kg.apc.jmeter.reporters.LoadosophiaAggregator Maven / Gradle / Ivy

There is a newer version: 3.0
Show newest version
package kg.apc.jmeter.reporters;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.jmeter.samplers.SampleEvent;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

import java.text.SimpleDateFormat;
import java.util.*;

public class LoadosophiaAggregator {

    private static final Logger log = LoggingManager.getLoggerForClass();
    private SortedMap> buffer = new TreeMap<>();
    private static final long SEND_SECONDS = 5;
    private long lastAggregatedTime = 0;
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    private int numSources = 0;

    public void addSample(SampleEvent res) {
        Long time = res.getResult().getEndTime() / 1000;
        if (!buffer.containsKey(time)) {
            // we need to create new sec list
            if (time <= lastAggregatedTime) {
                // a problem with times sequence - taking last available
                log.debug("Got time " + time + " <= " + lastAggregatedTime);
                for (Long aLong : buffer.keySet()) {
                    time = aLong;
                }
            }
            buffer.put(time, new LinkedList());
        }
        buffer.get(time).add(res);
    }

    public boolean haveDataToSend() {
        return buffer.size() > getBufLen() + 1;
    }

    private long getBufLen() {
        return SEND_SECONDS * numSources;
    }

    public JSONArray getDataToSend() {
        JSONArray data = new JSONArray();
        Iterator it = buffer.keySet().iterator();
        int cnt = 0;
        while (cnt < getBufLen() && it.hasNext()) {
            Long sec = it.next();
            List raw = buffer.get(sec);
            data.add(getAggregateSecond(sec, raw));
            it.remove();
            cnt++;
        }
        return data;
    }

    private JSONObject getAggregateSecond(Long sec, List raw) {
        /*
         "rc": item.http_codes,
         "net": item.net_codes
         */
        JSONObject result = new JSONObject();
        this.lastAggregatedTime = sec;
        Date ts = new Date(sec * 1000);
        log.debug("Aggregating " + sec);
        result.put("ts", format.format(ts));

        Map threads = new HashMap<>();
        int avg_rt = 0;
        Long[] rtimes = new Long[raw.size()];
        String[] rcodes = new String[raw.size()];
        int cnt = 0;
        int failedCount = 0;
        for (SampleEvent evt : raw) {
            SampleResult res = evt.getResult();

            if (!threads.containsKey(evt.getHostname())) {
                threads.put(evt.getHostname(), 0);
            }
            threads.put(evt.getHostname(), res.getAllThreads());

            avg_rt += res.getTime();
            rtimes[cnt] = res.getTime();
            rcodes[cnt] = res.getResponseCode();
            if (!res.isSuccessful()) {
                failedCount++;
            }
            cnt++;
        }

        long tsum = 0;
        for (Integer tcount : threads.values()) {
            tsum += tcount;
        }
        result.put("rps", cnt);
        result.put("threads", tsum);
        result.put("avg_rt", avg_rt / cnt);
        result.put("quantiles", getQuantilesJSON(rtimes));
        result.put("net", getNetJSON(failedCount, cnt - failedCount));
        result.put("rc", getRCJSON(rcodes));
        result.put("planned_rps", 0); // JMeter has no such feature like Yandex.Tank
        return result;
    }

    public static JSONObject getQuantilesJSON(Long[] rtimes) {
        JSONObject result = new JSONObject();
        Arrays.sort(rtimes);

        double[] quantiles = {0.25, 0.50, 0.75, 0.80, 0.90, 0.95, 0.98, 0.99, 1.00};

        Stack timings = new Stack<>();
        timings.addAll(Arrays.asList(rtimes));
        double level = 1.0;
        Object timing = 0;
        for (int qn = quantiles.length - 1; qn >= 0; qn--) {
            double quan = quantiles[qn];
            while (level >= quan && !timings.empty()) {
                timing = timings.pop();
                level -= 1.0 / rtimes.length;
            }
            result.element(String.valueOf(quan * 100), timing);
        }

        return result;
    }

    private JSONObject getNetJSON(int failedCount, int succCount) {
        JSONObject result = new JSONObject();
        result.put("0", succCount);
        result.put("1", failedCount);
        return result;
    }

    private JSONObject getRCJSON(String[] rcodes) {
        JSONObject result = new JSONObject();
        for (String rcode : rcodes) {
            int oldval = 0;
            if (result.containsKey(rcode)) {
                oldval = (Integer) result.get(rcode);
            }
            result.put(rcode, oldval + 1);

        }
        return result;
    }

    public void setNumSources(int numSources) {
        this.numSources = numSources;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy