File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\node_monitors\ResponseTimeMonitor.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Red Hat, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.node_monitors;
25
26 import hudson.Util;
27 import hudson.Extension;
28 import hudson.slaves.OfflineCause;
29 import hudson.model.Computer;
30 import hudson.remoting.Callable;
31 import hudson.remoting.Future;
32 import hudson.util.TimeUnit2;
33 import hudson.util.IOException2;
34 import net.sf.json.JSONObject;
35 import org.kohsuke.stapler.StaplerRequest;
36
37 import java.io.IOException;
38 import java.util.concurrent.ExecutionException;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.TimeoutException;
41 import java.util.logging.Logger;
42 import org.kohsuke.stapler.export.Exported;
43 import org.kohsuke.stapler.export.ExportedBean;
44
45 /**
46 * Monitors the round-trip response time to this slave.
47 *
48 * @author Kohsuke Kawaguchi
49 */
50 public class ResponseTimeMonitor extends NodeMonitor {
51 @Extension
52 public static final AbstractNodeMonitorDescriptor<Data> DESCRIPTOR = new AbstractNodeMonitorDescriptor<Data>() {
53 protected Data monitor(Computer c) throws IOException, InterruptedException {
54 Data old = get(c);
55 Data d;
56
57 long start = System.nanoTime();
58 Future<String> f = c.getChannel().callAsync(new NoopTask());
59 try {
60 f.get(TIMEOUT, TimeUnit.MILLISECONDS);
61 long end = System.nanoTime();
62 d = new Data(old,TimeUnit2.NANOSECONDS.toMillis(end-start));
63 } catch (ExecutionException e) {
64 throw new IOException2(e.getCause()); // I don't think this is possible
65 } catch (TimeoutException e) {
66 // special constant to indicate that the processing timed out.
67 d = new Data(old,-1L);
68 }
69
70 if(d.hasTooManyTimeouts() && !isIgnored()) {
71 // unlike other monitors whose failure still allow us to communicate with the slave,
72 // the failure in this monitor indicates that we are just unable to make any requests
73 // to this slave. So we should severe the connection, as opposed to marking it temporarily
74 // off line, which still keeps the underlying channel open.
75 c.disconnect(d);
76 LOGGER.warning(Messages.ResponseTimeMonitor_MarkedOffline(c.getName()));
77 }
78 return d;
79 }
80
81 public String getDisplayName() {
82 return Messages.ResponseTimeMonitor_DisplayName();
83 }
84
85 @Override
86 public NodeMonitor newInstance(StaplerRequest req, JSONObject formData) throws FormException {
87 return new ResponseTimeMonitor();
88 }
89 };
90
91 /**
92 * Immutable representation of the monitoring data.
93 */
94 @ExportedBean
95 public static final class Data extends OfflineCause {
96 /**
97 * Record of the past 5 times. -1 if time out. Otherwise in milliseconds.
98 * Old ones first.
99 */
100 private final long[] past5;
101
102 private Data(Data old, long newDataPoint) {
103 if(old==null)
104 past5 = new long[] {newDataPoint};
105 else {
106 past5 = new long[Math.min(5,old.past5.length+1)];
107 int copyLen = past5.length - 1;
108 System.arraycopy(old.past5, old.past5.length-copyLen, this.past5, 0, copyLen);
109 past5[past5.length-1] = newDataPoint;
110 }
111 }
112
113 /**
114 * Computes the recurrence of the time out
115 */
116 private int failureCount() {
117 int cnt=0;
118 for(int i=past5.length-1; i>=0 && past5[i]<0; i--, cnt++)
119 ;
120 return cnt;
121 }
122
123 /**
124 * Computes the average response time, by taking the time out into account.
125 */
126 @Exported
127 public long getAverage() {
128 long total=0;
129 for (long l : past5) {
130 if(l<0) total += TIMEOUT;
131 else total += l;
132 }
133 return total/past5.length;
134 }
135
136 public boolean hasTooManyTimeouts() {
137 return failureCount()>=5;
138 }
139
140 /**
141 * HTML rendering of the data
142 */
143 @Override
144 public String toString() {
145 // StringBuilder buf = new StringBuilder();
146 // for (long l : past5) {
147 // if(buf.length()>0) buf.append(',');
148 // buf.append(l);
149 // }
150 // return buf.toString();
151 int fc = failureCount();
152 if(fc>0)
153 return Util.wrapToErrorSpan(Messages.ResponseTimeMonitor_TimeOut(fc));
154 return getAverage()+"ms";
155 }
156 }
157
158 private static class NoopTask implements Callable<String,RuntimeException> {
159 public String call() {
160 return null;
161 }
162
163 private static final long serialVersionUID = 1L;
164 }
165
166 /**
167 * Time out interval in milliseconds.
168 */
169 private static final long TIMEOUT = 5000;
170
171 private static final Logger LOGGER = Logger.getLogger(ResponseTimeMonitor.class.getName());
172 }
173