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.rest.stats; 014 015import java.lang.reflect.*; 016import java.util.*; 017import java.util.concurrent.atomic.*; 018 019import org.apache.juneau.*; 020import org.apache.juneau.cp.*; 021import org.apache.juneau.internal.*; 022import org.apache.juneau.marshaller.*; 023 024/** 025 * Method execution statistics. 026 * 027 * Keeps track of number of starts/finishes on tasks and keeps an average run time. 028 * 029 * <h5 class='section'>See Also:</h5><ul> 030 * <li class='link'><a class="doclink" href="../../../../../index.html#jrs.ExecutionStatistics">REST method execution statistics</a> 031 * </ul> 032 */ 033public class MethodExecStats { 034 035 //----------------------------------------------------------------------------------------------------------------- 036 // Static 037 //----------------------------------------------------------------------------------------------------------------- 038 039 /** 040 * Static creator. 041 * 042 * @param beanStore The bean store to use for creating beans. 043 * @return A new builder for this object. 044 */ 045 public static Builder create(BeanStore beanStore) { 046 return new Builder(beanStore); 047 } 048 049 //----------------------------------------------------------------------------------------------------------------- 050 // Builder 051 //----------------------------------------------------------------------------------------------------------------- 052 053 /** 054 * Builder class. 055 */ 056 @FluentSetters 057 public static class Builder extends BeanBuilder<MethodExecStats> { 058 059 Method method; 060 ThrownStore thrownStore; 061 062 /** 063 * Constructor. 064 * 065 * @param beanStore The bean store to use for creating beans. 066 */ 067 protected Builder(BeanStore beanStore) { 068 super(MethodExecStats.class, beanStore); 069 } 070 071 @Override /* BeanBuilder */ 072 protected MethodExecStats buildDefault() { 073 return new MethodExecStats(this); 074 } 075 076 //------------------------------------------------------------------------------------------------------------- 077 // Properties 078 //------------------------------------------------------------------------------------------------------------- 079 080 /** 081 * Specifies the Java method. 082 * 083 * @param value The new value for this setting. 084 * @return This object. 085 */ 086 @FluentSetter 087 public Builder method(Method value) { 088 method = value; 089 return this; 090 } 091 092 /** 093 * Specifies the thrown store for tracking exceptions. 094 * 095 * @param value The new value for this setting. 096 * @return This object. 097 */ 098 @FluentSetter 099 public Builder thrownStore(ThrownStore value) { 100 thrownStore = value; 101 return this; 102 } 103 104 // <FluentSetters> 105 106 @Override /* GENERATED - org.apache.juneau.BeanBuilder */ 107 public Builder impl(Object value) { 108 super.impl(value); 109 return this; 110 } 111 112 @Override /* GENERATED - org.apache.juneau.BeanBuilder */ 113 public Builder type(Class<?> value) { 114 super.type(value); 115 return this; 116 } 117 118 // </FluentSetters> 119 } 120 121 //----------------------------------------------------------------------------------------------------------------- 122 // Instance 123 //----------------------------------------------------------------------------------------------------------------- 124 125 private final long guid; 126 private final Method method; 127 private final ThrownStore thrownStore; 128 129 private volatile int minTime = -1, maxTime; 130 131 private AtomicInteger 132 starts = new AtomicInteger(), 133 finishes = new AtomicInteger(), 134 errors = new AtomicInteger(); 135 136 private AtomicLong 137 totalTime = new AtomicLong(); 138 139 /** 140 * Constructor. 141 * 142 * @param builder The builder for this object. 143 */ 144 protected MethodExecStats(Builder builder) { 145 this.guid = new Random().nextLong(); 146 this.method = builder.method; 147 this.thrownStore = builder.thrownStore != null ? builder.thrownStore : new ThrownStore(); 148 } 149 150 151 /** 152 * Call when task is started. 153 * 154 * @return This object. 155 */ 156 public MethodExecStats started() { 157 starts.incrementAndGet(); 158 return this; 159 } 160 161 /** 162 * Call when task is finished. 163 * 164 * @param nanoTime The execution time of the task in nanoseconds. 165 * @return This object. 166 */ 167 public MethodExecStats finished(long nanoTime) { 168 finishes.incrementAndGet(); 169 int milliTime = (int)(nanoTime/1_000_000); 170 totalTime.addAndGet(nanoTime); 171 minTime = minTime == -1 ? milliTime : Math.min(minTime, milliTime); 172 maxTime = Math.max(maxTime, milliTime); 173 return this; 174 } 175 176 /** 177 * Call when an error occurs. 178 * 179 * @param e The exception thrown. Can be <jk>null</jk>. 180 * @return This object. 181 */ 182 public MethodExecStats error(Throwable e) { 183 errors.incrementAndGet(); 184 thrownStore.add(e); 185 return this; 186 } 187 188 /** 189 * Returns a globally unique ID for this object. 190 * 191 * <p> 192 * A random long generated during the creation of this object. 193 * Allows this object to be differentiated from other similar objects in multi-node environments so that 194 * statistics can be reliably stored in a centralized location. 195 * 196 * @return The globally unique ID for this object. 197 */ 198 public long getGuid() { 199 return guid; 200 } 201 202 /** 203 * Returns the method name of these stats. 204 * 205 * @return The method name of these stats. 206 */ 207 public Method getMethod() { 208 return method; 209 } 210 211 /** 212 * Returns the number of times the {@link #started()} method was called. 213 * 214 * @return The number of times the {@link #started()} method was called. 215 */ 216 public int getRuns() { 217 return starts.get(); 218 } 219 220 /** 221 * Returns the number currently running method invocations. 222 * 223 * @return The number of currently running method invocations. 224 */ 225 public int getRunning() { 226 return starts.get() - finishes.get(); 227 } 228 229 /** 230 * Returns the number of times the {@link #error(Throwable)} method was called. 231 * 232 * @return The number of times the {@link #error(Throwable)} method was called. 233 */ 234 public int getErrors() { 235 return errors.get(); 236 } 237 238 /** 239 * Returns the max execution time. 240 * 241 * @return The average execution time in milliseconds. 242 */ 243 public int getMinTime() { 244 return minTime == -1 ? 0 : minTime; 245 } 246 247 /** 248 * Returns the max execution time. 249 * 250 * @return The average execution time in milliseconds. 251 */ 252 public int getMaxTime() { 253 return maxTime; 254 } 255 256 /** 257 * Returns the average execution time. 258 * 259 * @return The average execution time in milliseconds. 260 */ 261 public int getAvgTime() { 262 int runs = finishes.get(); 263 return runs == 0 ? 0 : (int)(getTotalTime() / runs); 264 } 265 266 /** 267 * Returns the total execution time. 268 * 269 * @return The total execution time in milliseconds. 270 */ 271 public long getTotalTime() { 272 return totalTime.get() / 1_000_000; 273 } 274 275 /** 276 * Returns information on all stack traces of all exceptions encountered. 277 * 278 * @return Information on all stack traces of all exceptions encountered. 279 */ 280 public ThrownStore getThrownStore() { 281 return thrownStore; 282 } 283 284 @Override /* Object */ 285 public String toString() { 286 return Json5.of(this); 287 } 288}