1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package tools.gsf.time;
17
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21
22
23
24
25
26
27
28
29
30 public final class LoggerStopwatch implements Stopwatch {
31
32
33
34
35 public static final String DEFAULT_LOGGER_NAME = "tools.gsf.time";
36
37
38
39
40
41
42 public static final String MESSAGE_FORMAT_SPLIT = "Split timer measurement: {}us ({}) for: ";
43
44
45
46
47
48
49 public static final String MESSAGE_FORMAT_ELAPSED = "Elapsed timer measurement: {}us ({}) for: ";
50
51 private final Logger logger;
52 private long startTimeNanos;
53 private long lastIntervalTimeNanos;
54
55
56
57
58
59
60
61 public static Stopwatch getInstance(Logger logger) {
62 return logger.isDebugEnabled() ? new LoggerStopwatch(logger) : NoopStopwatch.INSTANCE;
63 }
64
65
66
67
68
69
70
71 public static Stopwatch getInstance(String logger) {
72 return getInstance(LoggerFactory.getLogger(logger));
73 }
74
75
76
77
78
79
80
81
82 public static Stopwatch getInstance() {
83 return getInstance(DEFAULT_LOGGER_NAME);
84 }
85
86 private LoggerStopwatch(Logger logger) {
87 this.logger = logger;
88 this.startTimeNanos = 0L;
89 this.lastIntervalTimeNanos = 0L;
90 }
91
92 @Override
93 public void start() {
94 startTimeNanos = System.nanoTime();
95 lastIntervalTimeNanos = startTimeNanos;
96 }
97
98 public void split(String msg) {
99 if (startTimeNanos == 0L) throw new IllegalStateException("Not yet started. Call start() first.");
100 long now = System.nanoTime();
101 _log(lastIntervalTimeNanos, now, true, msg);
102 lastIntervalTimeNanos = now;
103 }
104
105 public void split(String msg, Object... args) {
106 if (startTimeNanos == 0L) throw new IllegalStateException("Not yet started. Call start() first.");
107 long now = System.nanoTime();
108 _log(lastIntervalTimeNanos, now, true, msg, args);
109 lastIntervalTimeNanos = now;
110 }
111
112 public void elapsed(String msg) {
113 if (startTimeNanos == 0L) throw new IllegalStateException("Not yet started. Call start() first.");
114 long now = System.nanoTime();
115 _log(startTimeNanos, now, false, msg);
116 }
117
118 public void elapsed(String msg, Object... args) {
119 if (startTimeNanos == 0L) throw new IllegalStateException("Not yet started. Call start() first.");
120 long now = System.nanoTime();
121 _log(startTimeNanos, now, false, msg, args);
122 }
123
124 private void _log(long startNanos, long endNanos, boolean split, String msg, Object... args) {
125
126 long micros = (endNanos - startNanos) / 1000;
127 String sMicros = Long.toString(micros);
128 String human = _humanFormat(micros);
129
130 String logmsg = split ? MESSAGE_FORMAT_SPLIT : MESSAGE_FORMAT_ELAPSED;
131 logmsg += msg;
132
133 if (args == null || args.length == 0) {
134 logger.debug(logmsg, sMicros, human);
135 } else {
136 Object[] arguments = new Object[args.length + 2];
137 arguments[0] = sMicros;
138 arguments[1] = human;
139 System.arraycopy(args, 0, arguments, 2, args.length);
140 logger.debug(logmsg, arguments);
141 }
142 }
143
144 private String _humanFormat(long micros) {
145 String human;
146 if (micros > 1000000) {
147 final long millis = micros / 1000;
148 human = Long.toString(millis / 1000) + "." + String.format("%03d", (millis % 1000)) + "s";
149 } else if (micros > 1000) {
150 human = Long.toString(micros / 1000) + "." + String.format("%03d", (micros % 1000)) + "ms";
151 } else {
152 human = Long.toString(micros) + "us";
153 }
154 return human;
155 }
156 }