blob: 515d6940113dfd16e0e7748066c140faf8977bc1 [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.ofbiz.base.util;
import java.util.concurrent.ConcurrentHashMap;
/**
* Timer handling utility
* Utility class for simple reporting of the progress of a process.
* Steps are labelled, and the time between each label (or message)
* and the time since the start are reported in each call to timerString.
*
*/
public class UtilTimer {
public static final String module = UtilTimer.class.getName();
protected static ConcurrentHashMap<String, UtilTimer> staticTimers = new ConcurrentHashMap<String, UtilTimer>();
protected String timerName = null;
protected String lastMessage = null;
protected long realStartTime;
protected long startTime;
protected long lastMessageTime;
protected boolean running = false;
protected boolean log = false;
public static UtilTimer makeTimer() {
return new UtilTimer();
}
/** Default constructor. Starts the timer. */
public UtilTimer() {
this("", true);
}
public UtilTimer(String timerName, boolean start) {
this(timerName, start, false);
}
public UtilTimer(String timerName, boolean start, boolean log) {
this.timerName = timerName;
this.setLog(log);
if (start) {
this.startTimer();
}
}
public void startTimer() {
this.lastMessageTime = realStartTime = startTime = System.currentTimeMillis();
this.lastMessage = "Begin";
this.running = true;
}
public String getName() {
return this.timerName;
}
public boolean isRunning() {
return this.running;
}
/** Creates a string with information including the passed message, the last passed message and the time since the last call, and the time since the beginning
* @param message A message to put into the timer String
* @return A String with the timing information, the timer String
*/
public String timerString(String message) {
return timerString(message, this.getClass().getName());
}
/** Creates a string with information including the passed message, the last passed message and the time since the last call, and the time since the beginning
* @param message A message to put into the timer String
* @param module The debug/log module/thread to use, can be null for root module
* @return A String with the timing information, the timer String
*/
public String timerString(String message, String module) {
// time this call to avoid it interfering with the main timer
long tsStart = System.currentTimeMillis();
StringBuilder retBuf = new StringBuilder();
retBuf.append("[[").append(message).append("- total:").append(secondsSinceStart());
if (lastMessage != null) {
retBuf.append(",since last(").append(((lastMessage.length() > 20) ? (lastMessage.substring(0, 17) + "...") : lastMessage)).append("):").append(secondsSinceLast());
}
retBuf.append("]]");
// append the timer name
if (UtilValidate.isNotEmpty(timerName)) {
retBuf.append(" - '").append(timerName).append("'");
}
lastMessage = message;
String retString = retBuf.toString();
if (log) Debug.log(Debug.TIMING, null, retString, module, "org.ofbiz.base.util.UtilTimer");
// have lastMessageTime come as late as possible to just time what happens between calls
lastMessageTime = System.currentTimeMillis();
// update startTime to disclude the time this call took
startTime += (lastMessageTime - tsStart);
return retString;
}
/** Returns the number of seconds since the timer started
* @return The number of seconds since the timer started
*/
public double secondsSinceStart() {
return (timeSinceStart()) / 1000.0;
}
/** Returns the number of seconds since the last time timerString was called
* @return The number of seconds since the last time timerString was called
*/
public double secondsSinceLast() {
return (timeSinceLast()) / 1000.0;
}
/** Returns the number of milliseconds since the timer started
* @return The number of milliseconds since the timer started
*/
public long timeSinceStart() {
long currentTime = System.currentTimeMillis();
return currentTime - startTime;
}
/** Returns the number of milliseconds since the last time timerString was called
* @return The number of milliseconds since the last time timerString was called
*/
public long timeSinceLast() {
long currentTime = System.currentTimeMillis();
return currentTime - lastMessageTime;
}
/** Sets the value of the log member, denoting whether log output is off or not
* @param log The new value of log
*/
public void setLog(boolean log) {
this.log = log;
}
/** Gets the value of the log member, denoting whether log output is off or not
* @return The value of log
*/
public boolean getLog() {
return log;
}
/** Creates a string with information including the passed message, the time since the last call,
* and the time since the beginning. This version allows an integer level to be specified to
* improve readability of the output.
* @param level Integer specifying how many levels to indent the timer string so the output can be more easily read through nested method calls.
* @param message A message to put into the timer String
* @return A String with the timing information, the timer String
*/
public String timerString(int level, String message) {
// String retString = "[[" + message + ": seconds since start: " + secondsSinceStart() + ",since last(" + lastMessage + "):" + secondsSinceLast() + "]]";
StringBuilder retStringBuf = new StringBuilder();
for (int i = 0; i < level; i++) {
retStringBuf.append("| ");
}
retStringBuf.append("(");
String timeSinceStartStr = String.valueOf(timeSinceStart());
// int spacecount = 5 - timeSinceStartStr.length();
// for (int i=0; i < spacecount; i++) { retStringBuf.append(' '); }
retStringBuf.append(timeSinceStartStr + ",");
String timeSinceLastStr = String.valueOf(timeSinceLast());
// spacecount = 4 - timeSinceLastStr.length();
// for (int i=0; i < spacecount; i++) { retStringBuf.append(' '); }
retStringBuf.append(timeSinceLastStr);
retStringBuf.append(")");
int spacecount = 12 + (2 * level) - retStringBuf.length();
for (int i = 0; i < spacecount; i++) {
retStringBuf.append(' ');
}
retStringBuf.append(message);
// lastMessageTime = (new Date()).getTime();
lastMessageTime = System.currentTimeMillis();
// lastMessage = message;
String retString = retStringBuf.toString();
// if (!quiet) Debug.logInfo(retString, module);
if (log && Debug.timingOn()) Debug.logTiming(retString, module);
return retString;
}
// static logging timer - be sure to close the timer when finished!
public static UtilTimer getTimer(String timerName) {
return getTimer(timerName, true);
}
public static UtilTimer getTimer(String timerName, boolean log) {
UtilTimer timer = staticTimers.get(timerName);
if (timer == null) {
timer = new UtilTimer(timerName, false);
timer.setLog(log);
staticTimers.putIfAbsent(timerName, timer);
timer = staticTimers.get(timerName);
}
return timer;
}
public static void timerLog(String timerName, String message, String module) {
UtilTimer timer = UtilTimer.getTimer(timerName);
if (!timer.isRunning()) {
timer.startTimer();
}
if (timer.getLog()) {
if (module == null) {
module = timer.getClass().getName();
}
timer.timerString(message, module);
}
}
public static void closeTimer(String timerName) {
UtilTimer.closeTimer(timerName, null, null);
}
public static void closeTimer(String timerName, String message) {
UtilTimer.closeTimer(timerName, message, null);
}
public static void closeTimer(String timerName, String message, String module) {
if (message != null) {
UtilTimer.timerLog(timerName, message, module);
}
staticTimers.remove(timerName);
}
}