1
18
19 package io.undertow.server;
20
21 import io.undertow.conduits.ByteActivityCallback;
22 import io.undertow.util.StatusCodes;
23
24 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
25
26
29 public class ConnectorStatisticsImpl implements ConnectorStatistics {
30
31 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> requestCountUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "requestCount");
32 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> bytesSentUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "bytesSent");
33 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> bytesReceivedUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "bytesReceived");
34 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> errorCountUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "errorCount");
35 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> processingTimeUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "processingTime");
36 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> maxProcessingTimeUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "maxProcessingTime");
37 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> activeConnectionsUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "activeConnections");
38 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> maxActiveConnectionsUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "maxActiveConnections");
39 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> activeRequestsUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "activeRequests");
40 private static final AtomicLongFieldUpdater<ConnectorStatisticsImpl> maxActiveRequestsUpdater = AtomicLongFieldUpdater.newUpdater(ConnectorStatisticsImpl.class, "maxActiveRequests");
41
42 private volatile long requestCount;
43 private volatile long bytesSent;
44 private volatile long bytesReceived;
45 private volatile long errorCount;
46 private volatile long processingTime;
47 private volatile long maxProcessingTime;
48 private volatile long activeConnections;
49 private volatile long maxActiveConnections;
50 private volatile long activeRequests;
51 private volatile long maxActiveRequests;
52
53 private final ExchangeCompletionListener completionListener = new ExchangeCompletionListener() {
54 @Override
55 public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) {
56 try {
57 activeRequestsUpdater.decrementAndGet(ConnectorStatisticsImpl.this);
58 if (exchange.getStatusCode() == StatusCodes.INTERNAL_SERVER_ERROR) {
59 errorCountUpdater.incrementAndGet(ConnectorStatisticsImpl.this);
60 }
61 long start = exchange.getRequestStartTime();
62 if (start > 0) {
63 long elapsed = System.nanoTime() - start;
64 processingTimeUpdater.addAndGet(ConnectorStatisticsImpl.this, elapsed);
65 long oldMax;
66 do {
67 oldMax = maxProcessingTimeUpdater.get(ConnectorStatisticsImpl.this);
68 if (oldMax >= elapsed) {
69 break;
70 }
71 } while (!maxProcessingTimeUpdater.compareAndSet(ConnectorStatisticsImpl.this, oldMax, elapsed));
72 }
73
74 } finally {
75 nextListener.proceed();
76 }
77 }
78 };
79
80 private final ByteActivityCallback bytesSentAccumulator = new BytesSentAccumulator();
81 private final ByteActivityCallback bytesReceivedAccumulator = new BytesReceivedAccumulator();
82
83 @Override
84 public long getRequestCount() {
85 return requestCountUpdater.get(this);
86 }
87
88 @Override
89 public long getBytesSent() {
90 return bytesSentUpdater.get(this);
91 }
92
93 @Override
94 public long getBytesReceived() {
95 return bytesReceivedUpdater.get(this);
96 }
97
98 @Override
99 public long getErrorCount() {
100 return errorCountUpdater.get(this);
101 }
102
103 @Override
104 public long getProcessingTime() {
105 return processingTimeUpdater.get(this);
106 }
107
108 @Override
109 public long getMaxProcessingTime() {
110 return maxProcessingTimeUpdater.get(this);
111 }
112
113 @Override
114 public void reset() {
115 requestCountUpdater.set(this, 0);
116 bytesSentUpdater.set(this, 0);
117 bytesReceivedUpdater.set(this, 0);
118 errorCountUpdater.set(this, 0);
119 maxProcessingTimeUpdater.set(this, 0);
120 processingTimeUpdater.set(this, 0);
121 maxActiveConnectionsUpdater.set(this, 0);
122 maxActiveRequestsUpdater.set(this, 0);
123
124 }
125
126 public void requestFinished(long bytesSent, long bytesReceived, boolean error) {
127 bytesSentUpdater.addAndGet(this, bytesSent);
128 bytesReceivedUpdater.addAndGet(this, bytesReceived);
129 if (error) {
130 errorCountUpdater.incrementAndGet(this);
131 }
132 }
133
134 public void updateBytesSent(long bytes) {
135 bytesSentUpdater.addAndGet(this, bytes);
136 }
137
138 public void updateBytesReceived(long bytes) {
139 bytesReceivedUpdater.addAndGet(this, bytes);
140 }
141
142 public void setup(HttpServerExchange exchange) {
143 requestCountUpdater.incrementAndGet(this);
144 long current = activeRequestsUpdater.incrementAndGet(this);
145 long maxActiveRequests;
146 do {
147 maxActiveRequests = this.maxActiveRequests;
148 if(current <= maxActiveRequests) {
149 break;
150 }
151 } while (!maxActiveRequestsUpdater.compareAndSet(this, maxActiveRequests, current));
152 exchange.addExchangeCompleteListener(completionListener);
153 }
154
155 public ByteActivityCallback sentAccumulator() {
156 return bytesSentAccumulator;
157 }
158
159 public ByteActivityCallback receivedAccumulator() {
160 return bytesReceivedAccumulator;
161 }
162
163
164 private class BytesSentAccumulator implements ByteActivityCallback {
165 @Override
166 public void activity(long bytes) {
167 bytesSentUpdater.addAndGet(ConnectorStatisticsImpl.this, bytes);
168 }
169 }
170
171 private class BytesReceivedAccumulator implements ByteActivityCallback {
172 @Override
173 public void activity(long bytes) {
174 bytesReceivedUpdater.addAndGet(ConnectorStatisticsImpl.this, bytes);
175 }
176 }
177
178 @Override
179 public long getActiveConnections() {
180 return activeConnections;
181 }
182
183 @Override
184 public long getMaxActiveConnections() {
185 return maxActiveConnections;
186 }
187
188 public void incrementConnectionCount() {
189 long current = activeConnectionsUpdater.incrementAndGet(this);
190 long maxActiveConnections;
191 do {
192 maxActiveConnections = this.maxActiveConnections;
193 if(current <= maxActiveConnections) {
194 return;
195 }
196 } while (!maxActiveConnectionsUpdater.compareAndSet(this, maxActiveConnections, current));
197 }
198
199 public void decrementConnectionCount() {
200 activeConnectionsUpdater.decrementAndGet(this);
201 }
202 @Override
203 public long getActiveRequests() {
204 return activeRequests;
205 }
206
207 @Override
208 public long getMaxActiveRequests() {
209 return maxActiveRequests;
210 }
211 }
212