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

org.devocative.artemis.StatisticsContext Maven / Gradle / Ivy

There is a newer version: 2.0
Show newest version
package org.devocative.artemis;

import lombok.RequiredArgsConstructor;

import java.util.*;

import static java.lang.Math.max;

public class StatisticsContext {
	private static final List ALL_LISTS = Collections.synchronizedList(new ArrayList<>());
	private static final ThreadLocal CTX = new ThreadLocal<>();

	// ------------------------------

	public static void add(String id, String method, String uri, int status, long duration) {
		if (CTX.get() == null) {
			CTX.set(createList());
		}
		CTX.get()
			.add(new Record(id, method, uri, status, duration, Thread.currentThread().getName()));
	}

	public static void print() {
		if (ALL_LISTS.size() > 1) {
			printAll();
		}
		ALL_LISTS.clear();
	}

	public static void printThis() {
		printOne(CTX.get());
		CTX.remove();
	}

	// ------------------------------

	private synchronized static RecordList createList() {
		final RecordList list = new RecordList();
		ALL_LISTS.add(list);
		return list;
	}

	private static void printOne(RecordList list) {
		final Tabular t = new Tabular("ID", "URI", "Method", "Status", "Duration");
		list.forEach(r -> t.addRow(r.id, r.uri, r.method, String.valueOf(r.status), String.valueOf(r.duration)));
		t.print();
	}

	private static void printAll() {
		final Map map = new LinkedHashMap<>();
		for (int i = 0; i < ALL_LISTS.size(); i++) {
			for (final Record r : ALL_LISTS.get(i)) {
				final String key = r.id + r.status;
				if (i == 0) {
					map.put(key, new StatRecord(r));
				} else {
					if (map.containsKey(key)) {
						final StatRecord sr = map.get(key);
						sr.count++;
						sr.durSum += r.duration;
						if (sr.min > r.duration) {
							sr.min = r.duration;
							sr.minName = r.threadName;
						}
						if (sr.max < r.duration) {
							sr.max = r.duration;
							sr.maxName = r.threadName;
						}
					} else {
						map.put(key, new StatRecord(r));
					}
				}
			}
		}

		final Tabular t = new Tabular("ID", "Status", "Avg", "Count", "Min", "Min(th)", "Max", "Max(th)");
		map.values().forEach(sr ->
			t.addRow(
				sr.id,
				String.valueOf(sr.status),
				String.format("%.2f", sr.durSum / sr.count),
				String.valueOf(sr.count),
				String.valueOf(sr.min),
				String.format("[%s]", sr.minName),
				String.valueOf(sr.max),
				String.format("[%s]", sr.maxName)
			));
		t.print();
	}

	// ------------------------------

	@RequiredArgsConstructor
	private static class Record {
		private final String id;
		private final String method;
		private final String uri;
		private final int status;
		private final long duration;
		private final String threadName;
	}

	private static class StatRecord {
		private final String id;
		private final int status;
		private double durSum;
		private int count = 1;
		private long max;
		private String maxName;
		private long min;
		private String minName;

		public StatRecord(Record r) {
			id = r.id;
			status = r.status;
			durSum = r.duration;
			max = r.duration;
			min = r.duration;
			maxName = r.threadName;
			minName = r.threadName;
		}
	}

	private static class RecordList extends ArrayList {
	}

	private static class Tabular {
		private final String[] header;
		private final Integer[] width;
		private final List rows = new ArrayList<>();

		// ------------------------------

		public Tabular(String... header) {
			this.header = header;

			width = new Integer[header.length];
			for (int i = 0; i < header.length; i++) {
				width[i] = header[i].length();
			}
		}

		// ------------------------------

		public void addRow(String... cells) {
			final String[] row = new String[header.length];

			if (cells.length == header.length) {
				for (int i = 0; i < cells.length; i++) {
					final String cell = cells[i] != null ? cells[i] : "";
					width[i] = max(width[i], cell.length());
					row[i] = cell;
				}
			} else {
				throw new RuntimeException("Invalid row size: " + Arrays.toString(cells));
			}

			rows.add(row);
		}

		public void print() {
			final StringBuilder builder = new StringBuilder();

			for (int i = 0; i < width.length - 1; i++) {
				builder.append("%-").append(width[i]).append("s  ");
			}
			builder.append("%s");

			final String format = builder.toString();
			ALog.info(String.format(format, (Object[]) header));

			for (String[] row : rows) {
				ALog.info(String.format(format, (Object[]) row));
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy