/**
* This file Copyright (c) 2013 Magnolia International
* Ltd. (http://www.magnolia-cms.com). All rights reserved.
*
*
* This file is dual-licensed under both the Magnolia
* Network Agreement and the GNU General Public License.
* You may elect to use one or the other of these licenses.
*
* This file is distributed in the hope that it will be
* useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
* Redistribution, except as permitted by whichever of the GPL
* or MNA you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or
* modify this file under the terms of the GNU General
* Public License, Version 3, as published by the Free Software
* Foundation. You should have received a copy of the GNU
* General Public License, Version 3 along with this program;
* if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 2. For the Magnolia Network Agreement (MNA), this file
* and the accompanying materials are made available under the
* terms of the MNA which accompanies this distribution, and
* is available at http://www.magnolia-cms.com/mna.html
*
* Any modifications to this file must keep this entire header
* intact.
*
*/
package info.magnolia.debug;
import info.magnolia.context.MgnlContext;
import java.util.HashMap;
import java.util.Map;
/**
* Invocation aggregator.
*/
public class TrackingStatus {
private static final String ATTRIBUTE_NAME = TrackingStatus.class.getName();
private final Map<String, Long>[] traces = new Map[10];
private final boolean trace;
private final Object testString;
/**
* Gets instance of the status configured for current request or new one if none is configured
* yet.
*/
public static TrackingStatus getInstance() {
return getInstance(true);
}
/**
* Gets instance of the status configured for current request or new one if none is configured
* yet.
*
* @param trace used only for the very first invocation to enable/disable this status instance.
*/
public static TrackingStatus getInstance(boolean trace) {
return getInstance(true, null);
}
/**
* Gets instance of the status configured for current request or new one if none is configured
* yet.
*
* @param trace used only for the very first invocation to enable/disable this status instance.
* @param testString used to further filter the calls to trace. Only calls to
* {@link #track(String)} matching the {@link #testString} will be logged.
*/
public static TrackingStatus getInstance(boolean trace, String testString) {
if(!MgnlContext.hasAttribute(ATTRIBUTE_NAME)) {
MgnlContext.setAttribute(ATTRIBUTE_NAME, new TrackingStatus(trace, testString));
}
return (TrackingStatus) MgnlContext.getAttribute(ATTRIBUTE_NAME);
}
public TrackingStatus(boolean trace, String testString) {
for (int i = 0; i < traces.length; i++) {
traces[i] = new HashMap<String, Long>();
}
this.trace = trace;
this.testString = testString;
}
/**
* Track all the callers and update aggregated stacktrace.
*/
public void track() {
if (!trace) {
return;
}
StackTraceElement[] trace = new Exception().getStackTrace();
int count = 0;
for (StackTraceElement el : trace) {
String strTrace = el.toString();
Map<String, Long> traceMap = traces[count];
Long sum = traceMap.get(strTrace);
if (sum != null) {
sum += 1;
} else {
sum = 1L;
}
traceMap.put(strTrace, sum);
count++;
if (count >= traces.length) {
break;
}
}
}
@Override
/**
* Generates aggregated tracktrace from all captured calls including count of invocations.
*/
public String toString() {
StringBuilder sb = new StringBuilder();
if (totalInits > 0) {
sb.append("inits: ").append(totalInits).append(",");
}
if (totalCalls > 0) {
sb.append(", total calls: ").append(totalCalls).append(",");
}
if (totalTime > 0) {
sb.append("total time: ").append(totalTime);
}
sb.append("\n");
String ind = " ";
for (Map<String, Long> trace : traces) {
for (Map.Entry<String, Long> entry : trace.entrySet()) {
sb.append(ind).append(entry.getValue()).append(";").append(entry.getKey()).append("\n");
}
ind += " ";
}
return sb.toString();
}
public long totalCalls;
public long totalInits;
public long totalTime;
/**
* Track only calls where {@link #testString} matches the argument.
*/
public void track(String str) {
if (testString == null || testString.equals(str)) {
track();
}
}
}