Fix javadoc warnings in DurationStatisticsTracker
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / DurationStatisticsTracker.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.util;
9
10 import static java.util.concurrent.TimeUnit.MICROSECONDS;
11 import static java.util.concurrent.TimeUnit.MILLISECONDS;
12 import static java.util.concurrent.TimeUnit.NANOSECONDS;
13 import static java.util.concurrent.TimeUnit.SECONDS;
14
15 import com.google.common.annotations.Beta;
16 import java.text.DecimalFormat;
17 import java.text.DecimalFormatSymbols;
18 import java.util.Date;
19 import java.util.concurrent.TimeUnit;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 /**
24  * Abstract class that calculates and tracks time duration statistics.
25  *
26  * @author Thomas Pantelis
27  * @author Robert Varga
28  */
29 @Beta
30 public abstract class DurationStatisticsTracker {
31     private static final Logger LOG = LoggerFactory.getLogger(DurationStatisticsTracker.class);
32     private static final DecimalFormat DECIMAL_FORMAT;
33
34     static {
35         final DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
36         symbols.setDecimalSeparator('.');
37         DECIMAL_FORMAT = new DecimalFormat("0.00", symbols);
38     }
39
40     /**
41      * Create a concurrent {@link DurationStatisticsTracker}, which performs well in very contended environments.
42      *
43      * @return A new instance.
44      */
45     public static DurationStatisticsTracker createConcurrent() {
46         return new ConcurrentDurationStatisticsTracker();
47     }
48
49     /**
50      * Create a synchronized {@link DurationStatisticsTracker}, which performs well in non-contended environments.
51      *
52      * @return A new instance.
53      */
54     public static DurationStatisticsTracker createSynchronized() {
55         return new SynchronizedDurationStatsTracker();
56     }
57
58     /**
59      * Add a duration to track.
60      *
61      * @param duration non-negative duration in nanoseconds.
62      */
63     public abstract void addDuration(long duration);
64
65     /**
66      * Returns the average duration in nanoseconds.
67      *
68      * @return average duration in nanoseconds.
69      */
70     public abstract double getAverageDuration();
71
72     /**
73      * Returns the total number of tracked durations.
74      *
75      * @return Total number of measurements accumulated since last {@link #reset()}.
76      */
77     public abstract long getTotalDurations();
78
79     /**
80      * Resets all statistics back to their defaults.
81      */
82     public abstract void reset();
83
84     /**
85      * Returns the longest duration in nanoseconds.
86      *
87      * @return the longest duration in nanoseconds.
88      */
89     public final long getLongestDuration() {
90         return getDuration(getLongest());
91     }
92
93     /**
94      * Returns the shortest duration in nanoseconds.
95      *
96      * @return the shortest duration in nanoseconds.
97      */
98     public final long getShortestDuration() {
99         return getDuration(getShortest());
100     }
101
102     /**
103      * Returns the average duration as a displayable String with units, e.g. {@code 12.34 ms}.
104      *
105      * @return the average duration in human-readable form.
106      */
107     public final String getDisplayableAverageDuration() {
108         return formatDuration(getAverageDuration(), null);
109     }
110
111     /**
112      * Returns the longest duration as a displayable String with units and the date/time at which it occurred, e.g.
113      * {@code 12.34 ms at 08/02/2014 12:30:24}.
114      *
115      * @return The longest duration and when it has occurred in human-readable form.
116      */
117     public final String getDisplayableLongestDuration() {
118         return formatDuration(getLongest());
119     }
120
121     /**
122      * Returns the shortest duration as a displayable String with units and the date/time at which it occurred, e.g.
123      * {@code 12.34 ms at 08/02/2014 12:30:24}.
124      *
125      * @return The shortest duration and when it has occurred in human-readable form.
126      */
127     public final String getDisplayableShortestDuration() {
128         return formatDuration(getShortest());
129     }
130
131     /**
132      * Returns the time stamp of the longest duration.
133      *
134      * @return the time stamp of the longest duration.
135      */
136     public final long getTimeOfLongestDuration() {
137         return getTimeMillis(getLongest());
138     }
139
140     /**
141      * Returns the time stamp of the shortest duration.
142      *
143      * @return the time stamp of the shortest duration.
144      */
145     public final long getTimeOfShortestDuration() {
146         return getTimeMillis(getShortest());
147     }
148
149     /**
150      * Get the shortest recorded duration and the time when it was recorded.
151      *
152      * @return Duration and timestamp.
153      */
154     abstract DurationWithTime getShortest();
155
156     /**
157      * Get the longest recorded duration and the time when it was recorded.
158      *
159      * @return Duration and timestamp.
160      */
161     abstract DurationWithTime getLongest();
162
163     /**
164      * Returns formatted value of number, e.g. "12.34". Always is used dot as decimal separator.
165      */
166     private static synchronized String formatDecimalValue(final double value) {
167         return DECIMAL_FORMAT.format(value);
168     }
169
170     private static long getDuration(final DurationWithTime current) {
171         return current == null ? 0L : current.getDuration();
172     }
173
174     private static long getTimeMillis(final DurationWithTime current) {
175         return current == null ? 0L : current.getTimeMillis();
176     }
177
178     private static String formatDuration(final double duration, final Long timeStamp) {
179         final TimeUnit unit = chooseUnit((long) duration);
180         final double value = duration / NANOSECONDS.convert(1, unit);
181
182         final StringBuilder sb = new StringBuilder();
183         sb.append(formatDecimalValue(value)).append(' ').append(abbreviate(unit));
184
185         if (timeStamp != null) {
186             sb.append(String.format(" at %1$tD %1$tT", new Date(timeStamp)));
187         }
188
189         return sb.toString();
190     }
191
192     private static String formatDuration(final DurationWithTime current) {
193         if (current == null) {
194             return formatDuration(0, null);
195         }
196         return formatDuration(current.getDuration(), current.getTimeMillis());
197     }
198
199     private static TimeUnit chooseUnit(final long nanos) {
200         // TODO: this could be inlined, as we are doing needless divisions
201         if (NANOSECONDS.toSeconds(nanos) > 0) {
202             return SECONDS;
203         }
204         if (NANOSECONDS.toMillis(nanos) > 0) {
205             return MILLISECONDS;
206         }
207         if (NANOSECONDS.toMicros(nanos) > 0) {
208             return MICROSECONDS;
209         }
210         return NANOSECONDS;
211     }
212
213     private static String abbreviate(final TimeUnit unit) {
214         switch (unit) {
215             case NANOSECONDS:
216                 return "ns";
217             case MICROSECONDS:
218                 return "μs";
219             case MILLISECONDS:
220                 return "ms";
221             case SECONDS:
222                 return "s";
223             case MINUTES:
224                 return "m";
225             case HOURS:
226                 return "h";
227             case DAYS:
228                 return "d";
229             default:
230                 LOG.warn("Unhandled time unit {}", unit);
231                 return "";
232         }
233     }
234 }