001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.utils; 014 015import java.lang.reflect.*; 016import java.util.*; 017import java.util.concurrent.atomic.*; 018 019import org.apache.juneau.annotation.*; 020import org.apache.juneau.marshall.*; 021 022/** 023 * Basic timing information. 024 * 025 * Keeps track of number of starts/finishes on tasks and keeps an average run time. 026 */ 027@Bean(bpi="method,runs,running,errors,minTime,maxTime,avgTime,totalTime,exceptions") 028public class MethodExecStats implements Comparable<MethodExecStats> { 029 030 private String method; 031 private WeightedAverage avgTime = new WeightedAverage(); 032 private volatile int minTime = -1, maxTime; 033 034 private AtomicInteger 035 starts = new AtomicInteger(), 036 finishes = new AtomicInteger(), 037 errors = new AtomicInteger(); 038 039 private AtomicLong 040 totalTime = new AtomicLong(); 041 042 private StackTraceDatabase stackTraceDb; 043 044 /** 045 * Constructor. 046 * 047 * @param method Arbitrary label. Should be kept to less than 50 characters. 048 * @param stackTraceStopClass Don't calculate stack traces when this class is encountered. 049 */ 050 public MethodExecStats(Method method, Class<?> stackTraceStopClass) { 051 this.method = method.getDeclaringClass().getSimpleName() + "." + method.getName(); 052 this.stackTraceDb = new StackTraceDatabase(-1, stackTraceStopClass); 053 } 054 055 /** 056 * Constructor. 057 * 058 * @param method Arbitrary label. Should be kept to less than 50 characters. 059 */ 060 public MethodExecStats(Method method) { 061 this(method, MethodInvoker.class); 062 } 063 064 /** 065 * Call when task is started. 066 */ 067 public void started() { 068 starts.incrementAndGet(); 069 } 070 071 /** 072 * Call when task is finished. 073 * @param nanoTime The execution time of the task in nanoseconds. 074 */ 075 public void finished(long nanoTime) { 076 finishes.incrementAndGet(); 077 int milliTime = (int)(nanoTime/1_000_000); 078 totalTime.addAndGet(nanoTime); 079 avgTime.add(1, nanoTime); 080 minTime = minTime == -1 ? milliTime : Math.min(minTime, milliTime); 081 maxTime = Math.max(maxTime, milliTime); 082 } 083 084 /** 085 * Call when an error occurs. 086 * @param e The exception thrown. Can be <jk>null</jk>. 087 */ 088 public void error(Throwable e) { 089 errors.incrementAndGet(); 090 stackTraceDb.add(e); 091 } 092 093 /** 094 * Returns the method name of these stats. 095 * 096 * @return The method name of these stats. 097 */ 098 public String getMethod() { 099 return method; 100 } 101 102 /** 103 * Returns the number of times the {@link #started()} method was called. 104 * 105 * @return The number of times the {@link #started()} method was called. 106 */ 107 public int getRuns() { 108 return starts.get(); 109 } 110 111 /** 112 * Returns the number currently running method invocations. 113 * 114 * @return The number of currently running method invocations. 115 */ 116 public int getRunning() { 117 return starts.get() - finishes.get(); 118 } 119 120 /** 121 * Returns the number of times the {@link #error(Throwable)} method was called. 122 * 123 * @return The number of times the {@link #error(Throwable)} method was called. 124 */ 125 public int getErrors() { 126 return errors.get(); 127 } 128 129 /** 130 * Returns the max execution time. 131 * 132 * @return The average execution time in milliseconds. 133 */ 134 public int getMinTime() { 135 return minTime == -1 ? 0 : minTime; 136 } 137 138 /** 139 * Returns the max execution time. 140 * 141 * @return The average execution time in milliseconds. 142 */ 143 public int getMaxTime() { 144 return maxTime; 145 } 146 147 /** 148 * Returns the average execution time. 149 * 150 * @return The average execution time in milliseconds. 151 */ 152 public int getAvgTime() { 153 return (int)avgTime.getValue() / 1_000_000; 154 } 155 156 /** 157 * Returns the total execution time. 158 * 159 * @return The total execution time in milliseconds. 160 */ 161 public long getTotalTime() { 162 return totalTime.get() / 1_000_000; 163 } 164 165 /** 166 * Returns information on all stack traces of all exceptions encountered. 167 * 168 * @return Information on all stack traces of all exceptions encountered. 169 */ 170 public List<StackTraceInfo> getExceptions() { 171 return stackTraceDb.getClonedStackTraceInfos(); 172 } 173 174 @Override /* Object */ 175 public String toString() { 176 return SimpleJson.DEFAULT.toString(this); 177 } 178 179 @Override /* Comparable */ 180 public int compareTo(MethodExecStats o) { 181 return Long.compare(o.getTotalTime(), getTotalTime()); 182 } 183}