package com.alibaba.doris.dataserver.monitor.support; import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicLong; import com.alibaba.doris.common.PrefReportUnit; public class PrefTrackerUnit { /** * 记录桶数量 */ private int _buckets = 1000; private PrefTrackerKey key; private AtomicIntegerArray histogram; private AtomicInteger histogramoverflow; private AtomicLong operations; private AtomicLong totalLatency; private AtomicLong totalBytes; private int min; private int max; private long timeStart; private int maxConcurrencyLevel; AtomicInteger currentConcurrencyLevel = new AtomicInteger(0); public PrefTrackerUnit(PrefTrackerKey key, Properties props) { this.key = key; init(); } private void init() { histogram = new AtomicIntegerArray(_buckets); histogramoverflow = new AtomicInteger(0); operations = new AtomicLong(0); totalLatency = new AtomicLong(0); totalBytes = new AtomicLong(0); min = -1; max = -1; maxConcurrencyLevel = 0; timeStart = System.currentTimeMillis(); } public void trackLatency(int latency) { if (latency >= _buckets) { histogramoverflow.incrementAndGet(); } else { histogram.incrementAndGet(latency); } operations.incrementAndGet(); totalLatency.addAndGet(latency); if ((min < 0) || (latency < min)) { min = latency; } if ((max < 0) || (latency > max)) { max = latency; } } public void incConcurrencyLevel() { int current = currentConcurrencyLevel.incrementAndGet(); if (maxConcurrencyLevel < current) { maxConcurrencyLevel = current; } } public void decConcurrencyLevel() { currentConcurrencyLevel.decrementAndGet(); } public PrefTrackerKey getKey() { return key; } public void trackBytes(int bytes) { totalBytes.addAndGet(bytes); } /** * 定时 * * @param needInit * @return */ public PrefReportUnit report(boolean needInit) { long operationCount = operations.get(); if (operationCount <= 0) { return null; } PrefReportUnit report = new PrefReportUnit(); report.setTotalOperation(operationCount); report.setMinLatency(min); report.setMaxLatency(max); report.setTotalLatency(totalLatency.get()); report.setTotalBytes(totalBytes.get()); report.setActionName(key.getActionName()); report.setNameSpace(key.getNameSpace()); report.setTimeStart(timeStart); report.setTimeUsed(System.currentTimeMillis() - timeStart); report.setMaxConcurrencyLevel(maxConcurrencyLevel); report.setCurrentConcurrencyLevel(currentConcurrencyLevel.get()); setPercentileLatency(report); if (needInit) { init(); } return report; } private void setPercentileLatency(PrefReportUnit report) { int opcounter = 0; boolean done80th = false; boolean done95th = false; int the80thLatency = -1; int the95thLatency = -1; int the99thLatency = -1; long operationCount = operations.get(); for (int i = 0; i < _buckets; i++) { opcounter += histogram.get(i); if ((!done80th) && (((double) opcounter) / operationCount >= 0.80)) { the80thLatency = i; done80th = true; } if ((!done95th) && (((double) opcounter) / operationCount >= 0.95)) { the95thLatency = i; done95th = true; } if (((double) opcounter) / ((double) operations.get()) >= 0.99) { the99thLatency = i; break; } } report.setThe80thLatency(the80thLatency); report.setThe95thLatency(the95thLatency); report.setThe99thLatency(the99thLatency); } @Override public String toString() { return String .format("OpTracker [_buckets=%s, histogram=%s, histogramoverflow=%s, operations=%s, totalLatency=%s, totalBytes=%s, min=%s, max=%s, timeStart=%s, name=%s]", _buckets, histogram, histogramoverflow, operations, totalLatency, totalBytes, min, max, timeStart, key.getActionName()); } }