]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/server/ConnectorStatistics.java
Merge "Update notes about password security"
[gigi.git] / lib / jetty / org / eclipse / jetty / server / ConnectorStatistics.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.util.Arrays;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25 import java.util.concurrent.ConcurrentMap;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.atomic.AtomicInteger;
28 import java.util.concurrent.atomic.AtomicLong;
29
30 import org.eclipse.jetty.io.Connection;
31 import org.eclipse.jetty.util.annotation.ManagedAttribute;
32 import org.eclipse.jetty.util.annotation.ManagedObject;
33 import org.eclipse.jetty.util.annotation.ManagedOperation;
34 import org.eclipse.jetty.util.component.AbstractLifeCycle;
35 import org.eclipse.jetty.util.component.Container;
36 import org.eclipse.jetty.util.component.ContainerLifeCycle;
37 import org.eclipse.jetty.util.component.Dumpable;
38 import org.eclipse.jetty.util.statistic.CounterStatistic;
39 import org.eclipse.jetty.util.statistic.SampleStatistic;
40
41
42 /* ------------------------------------------------------------ */
43 /** A Connector.Listener that gathers Connector and Connections Statistics.
44  * Adding an instance of this class as with {@link AbstractConnector#addBean(Object)} 
45  * will register the listener with all connections accepted by that connector.
46  */
47 @ManagedObject("Connector Statistics")
48 public class ConnectorStatistics extends AbstractLifeCycle implements Dumpable, Connection.Listener
49 {
50     private final static Sample ZERO=new Sample();
51     private final AtomicLong _startMillis = new AtomicLong(-1L);
52     private final CounterStatistic _connectionStats = new CounterStatistic();
53     private final SampleStatistic _messagesIn = new SampleStatistic();
54     private final SampleStatistic _messagesOut = new SampleStatistic();
55     private final SampleStatistic _connectionDurationStats = new SampleStatistic();
56     private final ConcurrentMap<Connection, Sample> _samples = new ConcurrentHashMap<>();
57     private final AtomicInteger _closedIn = new AtomicInteger();
58     private final AtomicInteger _closedOut = new AtomicInteger();
59     private AtomicLong _nanoStamp=new AtomicLong();
60     private volatile int _messagesInPerSecond;
61     private volatile int _messagesOutPerSecond;
62
63     @Override
64     public void onOpened(Connection connection)
65     {
66         if (isStarted())
67         {
68             _connectionStats.increment();
69             _samples.put(connection,ZERO);
70         }
71     }
72
73     @Override
74     public void onClosed(Connection connection)
75     {
76         if (isStarted())
77         {
78             int msgsIn=connection.getMessagesIn();
79             int msgsOut=connection.getMessagesOut();
80             _messagesIn.set(msgsIn);
81             _messagesOut.set(msgsOut);
82             _connectionStats.decrement();
83             _connectionDurationStats.set(System.currentTimeMillis()-connection.getCreatedTimeStamp());
84
85             Sample sample=_samples.remove(connection);
86             if (sample!=null)
87             {
88                 _closedIn.addAndGet(msgsIn-sample._messagesIn);
89                 _closedOut.addAndGet(msgsOut-sample._messagesOut);
90             }
91         }
92     }
93
94     @ManagedAttribute("Total number of bytes received by this connector")
95     public int getBytesIn()
96     {
97         // TODO
98         return -1;
99     }
100
101     @ManagedAttribute("Total number of bytes sent by this connector")
102     public int getBytesOut()
103     {
104         // TODO
105         return -1;
106     }
107
108     @ManagedAttribute("Total number of connections seen by this connector")
109     public int getConnections()
110     {
111         return (int)_connectionStats.getTotal();
112     }
113
114     @ManagedAttribute("Connection duration maximum in ms")
115     public long getConnectionDurationMax()
116     {
117         return _connectionDurationStats.getMax();
118     }
119
120     @ManagedAttribute("Connection duration mean in ms")
121     public double getConnectionDurationMean()
122     {
123         return _connectionDurationStats.getMean();
124     }
125
126     @ManagedAttribute("Connection duration standard deviation")
127     public double getConnectionDurationStdDev()
128     {
129         return _connectionDurationStats.getStdDev();
130     }
131
132     @ManagedAttribute("Messages In for all connections")
133     public int getMessagesIn()
134     {
135         return (int)_messagesIn.getTotal();
136     }
137
138     @ManagedAttribute("Messages In per connection maximum")
139     public int getMessagesInPerConnectionMax()
140     {
141         return (int)_messagesIn.getMax();
142     }
143
144     @ManagedAttribute("Messages In per connection mean")
145     public double getMessagesInPerConnectionMean()
146     {
147         return _messagesIn.getMean();
148     }
149
150     @ManagedAttribute("Messages In per connection standard deviation")
151     public double getMessagesInPerConnectionStdDev()
152     {
153         return _messagesIn.getStdDev();
154     }
155
156     @ManagedAttribute("Connections open")
157     public int getConnectionsOpen()
158     {
159         return (int)_connectionStats.getCurrent();
160     }
161
162     @ManagedAttribute("Connections open maximum")
163     public int getConnectionsOpenMax()
164     {
165         return (int)_connectionStats.getMax();
166     }
167
168     @ManagedAttribute("Messages Out for all connections")
169     public int getMessagesOut()
170     {
171         return (int)_messagesIn.getTotal();
172     }
173
174     @ManagedAttribute("Messages In per connection maximum")
175     public int getMessagesOutPerConnectionMax()
176     {
177         return (int)_messagesIn.getMax();
178     }
179
180     @ManagedAttribute("Messages In per connection mean")
181     public double getMessagesOutPerConnectionMean()
182     {
183         return _messagesIn.getMean();
184     }
185
186     @ManagedAttribute("Messages In per connection standard deviation")
187     public double getMessagesOutPerConnectionStdDev()
188     {
189         return _messagesIn.getStdDev();
190     }
191
192     @ManagedAttribute("Connection statistics started ms since epoch")
193     public long getStartedMillis()
194     {
195         long start = _startMillis.get();
196         return start < 0 ? 0 : System.currentTimeMillis() - start;
197     }
198
199     @ManagedAttribute("Messages in per second calculated over period since last called")
200     public int getMessagesInPerSecond()
201     {
202         update();
203         return _messagesInPerSecond;
204     }
205
206     @ManagedAttribute("Messages out per second calculated over period since last called")
207     public int getMessagesOutPerSecond()
208     {
209         update();
210         return _messagesOutPerSecond;
211     }
212
213     @Override
214     public void doStart()
215     {
216         reset();
217     }
218
219     @Override
220     public void doStop()
221     {
222         _samples.clear();
223     }
224
225     @ManagedOperation("Reset the statistics")
226     public void reset()
227     {
228         _startMillis.set(System.currentTimeMillis());
229         _messagesIn.reset();
230         _messagesOut.reset();
231         _connectionStats.reset();
232         _connectionDurationStats.reset();
233         _samples.clear();
234     }
235
236     @Override
237     @ManagedOperation("dump thread state")
238     public String dump()
239     {
240         return ContainerLifeCycle.dump(this);
241     }
242
243     @Override
244     public void dump(Appendable out, String indent) throws IOException
245     {
246         ContainerLifeCycle.dumpObject(out,this);
247         ContainerLifeCycle.dump(out,indent,Arrays.asList(new String[]{"connections="+_connectionStats,"duration="+_connectionDurationStats,"in="+_messagesIn,"out="+_messagesOut}));
248     }
249     
250     public static void addToAllConnectors(Server server)
251     {
252         for (Connector connector : server.getConnectors())
253         {
254             if (connector instanceof Container)
255              ((Container)connector).addBean(new ConnectorStatistics());
256         }
257     }  
258     
259     private static final long SECOND_NANOS=TimeUnit.SECONDS.toNanos(1);
260     private synchronized void update()
261     {
262         long now=System.nanoTime();
263         long then=_nanoStamp.get();
264         long duration=now-then;
265                 
266         if (duration>SECOND_NANOS/2)
267         {
268             if (_nanoStamp.compareAndSet(then,now))
269             {
270                 long msgsIn=_closedIn.getAndSet(0);
271                 long msgsOut=_closedOut.getAndSet(0);
272
273                 for (Map.Entry<Connection, Sample> entry : _samples.entrySet())
274                 {
275                     Connection connection=entry.getKey();
276                     Sample sample = entry.getValue();
277                     Sample next = new Sample(connection);
278                     if (_samples.replace(connection,sample,next))
279                     {
280                         msgsIn+=next._messagesIn-sample._messagesIn;
281                         msgsOut+=next._messagesOut-sample._messagesOut;
282                     }
283                 }
284                 
285                 _messagesInPerSecond=(int)(msgsIn*SECOND_NANOS/duration);
286                 _messagesOutPerSecond=(int)(msgsOut*SECOND_NANOS/duration);
287             }
288         }
289     }
290     
291     private static class Sample
292     {
293         Sample()
294         {
295             _messagesIn=0;
296             _messagesOut=0;
297         }
298         
299         Sample(Connection connection)
300         {
301             _messagesIn=connection.getMessagesIn();
302             _messagesOut=connection.getMessagesOut();
303         }
304         
305         final int _messagesIn;
306         final int _messagesOut;
307     }
308 }