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.mstat; 014 015import java.lang.reflect.*; 016import java.util.*; 017import java.util.concurrent.atomic.*; 018 019import org.apache.juneau.annotation.*; 020import org.apache.juneau.marshall.*; 021import org.apache.juneau.utils.*; 022 023/** 024 * Basic timing information. 025 * 026 * Keeps track of number of starts/finishes on tasks and keeps an average run time. 027 */ 028@Bean(bpi="method,runs,running,errors,minTime,maxTime,avgTime,totalTime,exceptions") 029public class MethodExecStats implements Comparable<MethodExecStats> { 030 031 private String method; 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 ExceptionStore 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 ExceptionStore(-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 minTime = minTime == -1 ? milliTime : Math.min(minTime, milliTime); 080 maxTime = Math.max(maxTime, milliTime); 081 } 082 083 /** 084 * Call when an error occurs. 085 * @param e The exception thrown. Can be <jk>null</jk>. 086 */ 087 public void error(Throwable e) { 088 errors.incrementAndGet(); 089 stackTraceDb.add(e); 090 } 091 092 /** 093 * Returns the method name of these stats. 094 * 095 * @return The method name of these stats. 096 */ 097 public String getMethod() { 098 return method; 099 } 100 101 /** 102 * Returns the number of times the {@link #started()} method was called. 103 * 104 * @return The number of times the {@link #started()} method was called. 105 */ 106 public int getRuns() { 107 return starts.get(); 108 } 109 110 /** 111 * Returns the number currently running method invocations. 112 * 113 * @return The number of currently running method invocations. 114 */ 115 public int getRunning() { 116 return starts.get() - finishes.get(); 117 } 118 119 /** 120 * Returns the number of times the {@link #error(Throwable)} method was called. 121 * 122 * @return The number of times the {@link #error(Throwable)} method was called. 123 */ 124 public int getErrors() { 125 return errors.get(); 126 } 127 128 /** 129 * Returns the max execution time. 130 * 131 * @return The average execution time in milliseconds. 132 */ 133 public int getMinTime() { 134 return minTime == -1 ? 0 : minTime; 135 } 136 137 /** 138 * Returns the max execution time. 139 * 140 * @return The average execution time in milliseconds. 141 */ 142 public int getMaxTime() { 143 return maxTime; 144 } 145 146 /** 147 * Returns the average execution time. 148 * 149 * @return The average execution time in milliseconds. 150 */ 151 public int getAvgTime() { 152 int runs = getRuns(); 153 return runs == 0 ? 0 : (int)(getTotalTime() / runs); 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<ExceptionStats> getExceptions() { 171 return stackTraceDb.getClonedStats(); 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}