1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.io;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.atomic.AtomicLong;
26 import java.util.concurrent.atomic.LongAdder;
27
28 import org.eclipse.jetty.util.annotation.ManagedAttribute;
29 import org.eclipse.jetty.util.annotation.ManagedObject;
30 import org.eclipse.jetty.util.annotation.ManagedOperation;
31 import org.eclipse.jetty.util.component.AbstractLifeCycle;
32 import org.eclipse.jetty.util.component.ContainerLifeCycle;
33 import org.eclipse.jetty.util.component.Dumpable;
34 import org.eclipse.jetty.util.statistic.CounterStatistic;
35 import org.eclipse.jetty.util.statistic.SampleStatistic;
36
37
38
39
40
41
42
43
44 @ManagedObject("Tracks statistics on connections")
45 public class ConnectionStatistics extends AbstractLifeCycle implements Connection.Listener, Dumpable
46 {
47 private final CounterStatistic _connections = new CounterStatistic();
48 private final SampleStatistic _connectionsDuration = new SampleStatistic();
49 private final LongAdder _rcvdBytes = new LongAdder();
50 private final AtomicLong _bytesInStamp = new AtomicLong();
51 private final LongAdder _sentBytes = new LongAdder();
52 private final AtomicLong _bytesOutStamp = new AtomicLong();
53 private final LongAdder _messagesIn = new LongAdder();
54 private final AtomicLong _messagesInStamp = new AtomicLong();
55 private final LongAdder _messagesOut = new LongAdder();
56 private final AtomicLong _messagesOutStamp = new AtomicLong();
57
58 @ManagedOperation(value = "Resets the statistics", impact = "ACTION")
59 public void reset()
60 {
61 _connections.reset();
62 _connectionsDuration.reset();
63 _rcvdBytes.reset();
64 _bytesInStamp.set(System.nanoTime());
65 _sentBytes.reset();
66 _bytesOutStamp.set(System.nanoTime());
67 _messagesIn.reset();
68 _messagesInStamp.set(System.nanoTime());
69 _messagesOut.reset();
70 _messagesOutStamp.set(System.nanoTime());
71 }
72
73 @Override
74 protected void doStart() throws Exception
75 {
76 reset();
77 }
78
79 @Override
80 public void onOpened(Connection connection)
81 {
82 if (!isStarted())
83 return;
84
85 _connections.increment();
86 }
87
88 @Override
89 public void onClosed(Connection connection)
90 {
91 if (!isStarted())
92 return;
93
94 _connections.decrement();
95
96 long elapsed = System.currentTimeMillis() - connection.getCreatedTimeStamp();
97 _connectionsDuration.set(elapsed);
98
99 long bytesIn = connection.getBytesIn();
100 if (bytesIn > 0)
101 _rcvdBytes.add(bytesIn);
102 long bytesOut = connection.getBytesOut();
103 if (bytesOut > 0)
104 _sentBytes.add(bytesOut);
105
106 long messagesIn = connection.getMessagesIn();
107 if (messagesIn > 0)
108 _messagesIn.add(messagesIn);
109 long messagesOut = connection.getMessagesOut();
110 if (messagesOut > 0)
111 _messagesOut.add(messagesOut);
112 }
113
114 @ManagedAttribute("Total number of bytes received by tracked connections")
115 public long getReceivedBytes()
116 {
117 return _rcvdBytes.sum();
118 }
119
120 @ManagedAttribute("Total number of bytes received per second since the last invocation of this method")
121 public long getReceivedBytesRate()
122 {
123 long now = System.nanoTime();
124 long then = _bytesInStamp.getAndSet(now);
125 long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then);
126 return elapsed == 0 ? 0 : getReceivedBytes() * 1000 / elapsed;
127 }
128
129 @ManagedAttribute("Total number of bytes sent by tracked connections")
130 public long getSentBytes()
131 {
132 return _sentBytes.sum();
133 }
134
135 @ManagedAttribute("Total number of bytes sent per second since the last invocation of this method")
136 public long getSentBytesRate()
137 {
138 long now = System.nanoTime();
139 long then = _bytesOutStamp.getAndSet(now);
140 long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then);
141 return elapsed == 0 ? 0 : getSentBytes() * 1000 / elapsed;
142 }
143
144 @ManagedAttribute("The max duration of a connection in ms")
145 public long getConnectionDurationMax()
146 {
147 return _connectionsDuration.getMax();
148 }
149
150 @ManagedAttribute("The mean duration of a connection in ms")
151 public double getConnectionDurationMean()
152 {
153 return _connectionsDuration.getMean();
154 }
155
156 @ManagedAttribute("The standard deviation of the duration of a connection")
157 public double getConnectionDurationStdDev()
158 {
159 return _connectionsDuration.getStdDev();
160 }
161
162 @ManagedAttribute("The total number of connections opened")
163 public long getConnectionsTotal()
164 {
165 return _connections.getTotal();
166 }
167
168 @ManagedAttribute("The current number of open connections")
169 public long getConnections()
170 {
171 return _connections.getCurrent();
172 }
173
174 @ManagedAttribute("The max number of open connections")
175 public long getConnectionsMax()
176 {
177 return _connections.getMax();
178 }
179
180 @ManagedAttribute("The total number of messages received")
181 public long getReceivedMessages()
182 {
183 return _messagesIn.sum();
184 }
185
186 @ManagedAttribute("Total number of messages received per second since the last invocation of this method")
187 public long getReceivedMessagesRate()
188 {
189 long now = System.nanoTime();
190 long then = _messagesInStamp.getAndSet(now);
191 long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then);
192 return elapsed == 0 ? 0 : getReceivedMessages() * 1000 / elapsed;
193 }
194
195 @ManagedAttribute("The total number of messages sent")
196 public long getSentMessages()
197 {
198 return _messagesOut.sum();
199 }
200
201 @ManagedAttribute("Total number of messages sent per second since the last invocation of this method")
202 public long getSentMessagesRate()
203 {
204 long now = System.nanoTime();
205 long then = _messagesOutStamp.getAndSet(now);
206 long elapsed = TimeUnit.NANOSECONDS.toMillis(now - then);
207 return elapsed == 0 ? 0 : getSentMessages() * 1000 / elapsed;
208 }
209
210 @Override
211 public String dump()
212 {
213 return ContainerLifeCycle.dump(this);
214 }
215
216 @Override
217 public void dump(Appendable out, String indent) throws IOException
218 {
219 ContainerLifeCycle.dumpObject(out, this);
220 List<String> children = new ArrayList<>();
221 children.add(String.format("connections=%s", _connections));
222 children.add(String.format("durations=%s", _connectionsDuration));
223 children.add(String.format("bytes in/out=%s/%s", getReceivedBytes(), getSentBytes()));
224 children.add(String.format("messages in/out=%s/%s", getReceivedMessages(), getSentMessages()));
225 ContainerLifeCycle.dump(out, indent, children);
226 }
227
228 @Override
229 public String toString()
230 {
231 return String.format("%s@%x", getClass().getSimpleName(), hashCode());
232 }
233 }