blob: b078551ad2ca006d2b2c5f84589bbb3e059d068f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.common.stats;
import java.util.LinkedList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.logging.InternalLogger;
public class StatsItem {
private final AtomicLong value = new AtomicLong(0);
private final AtomicLong times = new AtomicLong(0);
private final LinkedList<CallSnapshot> csListMinute = new LinkedList<CallSnapshot>();
private final LinkedList<CallSnapshot> csListHour = new LinkedList<CallSnapshot>();
private final LinkedList<CallSnapshot> csListDay = new LinkedList<CallSnapshot>();
private final String statsName;
private final String statsKey;
private final ScheduledExecutorService scheduledExecutorService;
private final InternalLogger log;
public StatsItem(String statsName, String statsKey, ScheduledExecutorService scheduledExecutorService,
InternalLogger log) {
this.statsName = statsName;
this.statsKey = statsKey;
this.scheduledExecutorService = scheduledExecutorService;
this.log = log;
}
private static StatsSnapshot computeStatsData(final LinkedList<CallSnapshot> csList) {
StatsSnapshot statsSnapshot = new StatsSnapshot();
synchronized (csList) {
double tps = 0;
double avgpt = 0;
long sum = 0;
long timesDiff = 0;
if (!csList.isEmpty()) {
CallSnapshot first = csList.getFirst();
CallSnapshot last = csList.getLast();
sum = last.getValue() - first.getValue();
tps = (sum * 1000.0d) / (last.getTimestamp() - first.getTimestamp());
timesDiff = last.getTimes() - first.getTimes();
if (timesDiff > 0) {
avgpt = (sum * 1.0d) / timesDiff;
}
}
statsSnapshot.setSum(sum);
statsSnapshot.setTps(tps);
statsSnapshot.setAvgpt(avgpt);
statsSnapshot.setTimes(timesDiff);
}
return statsSnapshot;
}
public StatsSnapshot getStatsDataInMinute() {
return computeStatsData(this.csListMinute);
}
public StatsSnapshot getStatsDataInHour() {
return computeStatsData(this.csListHour);
}
public StatsSnapshot getStatsDataInDay() {
return computeStatsData(this.csListDay);
}
public void init() {
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
samplingInSeconds();
} catch (Throwable ignored) {
}
}
}, 0, 10, TimeUnit.SECONDS);
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
samplingInMinutes();
} catch (Throwable ignored) {
}
}
}, 0, 10, TimeUnit.MINUTES);
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
samplingInHour();
} catch (Throwable ignored) {
}
}
}, 0, 1, TimeUnit.HOURS);
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
printAtMinutes();
} catch (Throwable ignored) {
}
}
}, Math.abs(UtilAll.computeNextMinutesTimeMillis() - System.currentTimeMillis()), 1000 * 60, TimeUnit.MILLISECONDS);
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
printAtHour();
} catch (Throwable ignored) {
}
}
}, Math.abs(UtilAll.computeNextHourTimeMillis() - System.currentTimeMillis()), 1000 * 60 * 60, TimeUnit.MILLISECONDS);
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
printAtDay();
} catch (Throwable ignored) {
}
}
}, Math.abs(UtilAll.computeNextMorningTimeMillis() - System.currentTimeMillis()) - 2000, 1000 * 60 * 60 * 24, TimeUnit.MILLISECONDS);
}
public void samplingInSeconds() {
synchronized (this.csListMinute) {
if (this.csListMinute.size() == 0) {
this.csListMinute.add(new CallSnapshot(System.currentTimeMillis() - 10 * 1000, 0, 0));
}
this.csListMinute.add(new CallSnapshot(System.currentTimeMillis(), this.times.get(), this.value
.get()));
if (this.csListMinute.size() > 7) {
this.csListMinute.removeFirst();
}
}
}
public void samplingInMinutes() {
synchronized (this.csListHour) {
if (this.csListHour.size() == 0) {
this.csListHour.add(new CallSnapshot(System.currentTimeMillis() - 10 * 60 * 1000, 0, 0));
}
this.csListHour.add(new CallSnapshot(System.currentTimeMillis(), this.times.get(), this.value
.get()));
if (this.csListHour.size() > 7) {
this.csListHour.removeFirst();
}
}
}
public void samplingInHour() {
synchronized (this.csListDay) {
if (this.csListDay.size() == 0) {
this.csListDay.add(new CallSnapshot(System.currentTimeMillis() - 1 * 60 * 60 * 1000, 0, 0));
}
this.csListDay.add(new CallSnapshot(System.currentTimeMillis(), this.times.get(), this.value
.get()));
if (this.csListDay.size() > 25) {
this.csListDay.removeFirst();
}
}
}
public void printAtMinutes() {
StatsSnapshot ss = computeStatsData(this.csListMinute);
log.info(String.format("[%s] [%s] Stats In One Minute, ", this.statsName, this.statsKey) + statPrintDetail(ss));
}
public void printAtHour() {
StatsSnapshot ss = computeStatsData(this.csListHour);
log.info(String.format("[%s] [%s] Stats In One Hour, ", this.statsName, this.statsKey) + statPrintDetail(ss));
}
public void printAtDay() {
StatsSnapshot ss = computeStatsData(this.csListDay);
log.info(String.format("[%s] [%s] Stats In One Day, ", this.statsName, this.statsKey) + statPrintDetail(ss));
}
protected String statPrintDetail(StatsSnapshot ss) {
return String.format("SUM: %d TPS: %.2f AVGPT: %.2f",
ss.getSum(),
ss.getTps(),
ss.getAvgpt());
}
public AtomicLong getValue() {
return value;
}
public String getStatsKey() {
return statsKey;
}
public String getStatsName() {
return statsName;
}
public AtomicLong getTimes() {
return times;
}
}
class CallSnapshot {
private final long timestamp;
private final long times;
private final long value;
public CallSnapshot(long timestamp, long times, long value) {
super();
this.timestamp = timestamp;
this.times = times;
this.value = value;
}
public long getTimestamp() {
return timestamp;
}
public long getTimes() {
return times;
}
public long getValue() {
return value;
}
}