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

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
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.model;
25
26 import hudson.Extension;
27 import hudson.model.MultiStageTimeSeries.TimeScale;
28 import hudson.model.MultiStageTimeSeries.TrendChart;
29 import hudson.util.ColorPalette;
30 import hudson.util.NoOverlapCategoryAxis;
31 import jenkins.model.Jenkins;
32 import org.jfree.chart.ChartFactory;
33 import org.jfree.chart.JFreeChart;
34 import org.jfree.chart.axis.CategoryAxis;
35 import org.jfree.chart.axis.CategoryLabelPositions;
36 import org.jfree.chart.axis.NumberAxis;
37 import org.jfree.chart.plot.CategoryPlot;
38 import org.jfree.chart.plot.PlotOrientation;
39 import org.jfree.chart.renderer.category.LineAndShapeRenderer;
40 import org.jfree.data.category.CategoryDataset;
41 import org.jfree.ui.RectangleInsets;
42 import org.kohsuke.stapler.QueryParameter;
43 import org.kohsuke.stapler.export.ExportedBean;
44 import org.kohsuke.stapler.export.Exported;
45
46 import java.awt.*;
47 import java.io.IOException;
48 import java.util.List;
49
50 /**
51 * Utilization statistics for a node or a set of nodes.
52 *
53 * <h2>Implementation Note</h2>
54 * <p>
55 * Instances of this class is not capable of updating the statistics itself
56 * &mdash; instead, it's done by the {@link LoadStatisticsUpdater} timer.
57 * This is more efficient (as it allows us a single pass to update all stats),
58 * but it's not clear to me if the loss of autonomy is worth it.
59 *
60 * @author Kohsuke Kawaguchi
61 * @see Label#loadStatistics
62 * @see Jenkins#overallLoad
63 * @see Jenkins#unlabeledLoad
64 */
65 @ExportedBean
66 public abstract class LoadStatistics {
67 /**
68 * Number of busy executors and how it changes over time.
69 */
70 @Exported
71 public final MultiStageTimeSeries busyExecutors;
72
73 /**
74 * Number of total executors and how it changes over time.
75 */
76 @Exported
77 public final MultiStageTimeSeries totalExecutors;
78
79 /**
80 * Number of {@link Queue.BuildableItem}s that can run on any node in this node set but blocked.
81 */
82 @Exported
83 public final MultiStageTimeSeries queueLength;
84
85 protected LoadStatistics(int initialTotalExecutors, int initialBusyExecutors) {
86 this.totalExecutors = new MultiStageTimeSeries(
87 Messages._LoadStatistics_Legends_TotalExecutors(), ColorPalette.BLUE, initialTotalExecutors,DECAY);
88 this.busyExecutors = new MultiStageTimeSeries(
89 Messages._LoadStatistics_Legends_BusyExecutors(), ColorPalette.RED, initialBusyExecutors,DECAY);
90 this.queueLength = new MultiStageTimeSeries(
91 Messages._LoadStatistics_Legends_QueueLength(),ColorPalette.GREY, 0, DECAY);
92 }
93
94 public float getLatestIdleExecutors(TimeScale timeScale) {
95 return totalExecutors.pick(timeScale).getLatest() - busyExecutors.pick(timeScale).getLatest();
96 }
97
98 /**
99 * Computes the # of idle executors right now and obtains the snapshot value.
100 */
101 public abstract int computeIdleExecutors();
102
103 /**
104 * Computes the # of total executors right now and obtains the snapshot value.
105 */
106 public abstract int computeTotalExecutors();
107
108 /**
109 * Computes the # of queue length right now and obtains the snapshot value.
110 */
111 public abstract int computeQueueLength();
112
113 /**
114 * Creates a trend chart.
115 */
116 public JFreeChart createChart(CategoryDataset ds) {
117 final JFreeChart chart = ChartFactory.createLineChart(null, // chart title
118 null, // unused
119 null, // range axis label
120 ds, // data
121 PlotOrientation.VERTICAL, // orientation
122 true, // include legend
123 true, // tooltips
124 false // urls
125 );
126
127 chart.setBackgroundPaint(Color.white);
128
129 final CategoryPlot plot = chart.getCategoryPlot();
130 plot.setBackgroundPaint(Color.WHITE);
131 plot.setOutlinePaint(null);
132 plot.setRangeGridlinesVisible(true);
133 plot.setRangeGridlinePaint(Color.black);
134
135 final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
136 renderer.setBaseStroke(new BasicStroke(3));
137 configureRenderer(renderer);
138
139 final CategoryAxis domainAxis = new NoOverlapCategoryAxis(null);
140 plot.setDomainAxis(domainAxis);
141 domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
142 domainAxis.setLowerMargin(0.0);
143 domainAxis.setUpperMargin(0.0);
144 domainAxis.setCategoryMargin(0.0);
145
146 final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
147 rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
148
149 // crop extra space around the graph
150 plot.setInsets(new RectangleInsets(0, 0, 0, 5.0));
151
152 return chart;
153 }
154
155 protected void configureRenderer(LineAndShapeRenderer renderer) {
156 renderer.setSeriesPaint(0, ColorPalette.BLUE); // total
157 renderer.setSeriesPaint(1, ColorPalette.RED); // busy
158 renderer.setSeriesPaint(2, ColorPalette.GREY); // queue
159 }
160
161 /**
162 * Creates {@link CategoryDataset} which then becomes the basis
163 * of the load statistics graph.
164 */
165 public TrendChart createTrendChart(TimeScale timeScale) {
166 return MultiStageTimeSeries.createTrendChart(timeScale,totalExecutors,busyExecutors,queueLength);
167 }
168
169 /**
170 * Generates the load statistics graph.
171 */
172 public TrendChart doGraph(@QueryParameter String type) throws IOException {
173 return createTrendChart(TimeScale.parse(type));
174 }
175
176 public Api getApi() {
177 return new Api(this);
178 }
179
180 /**
181 * Updates {@link #totalExecutors} and {@link #busyExecutors} by using
182 * the current snapshot value.
183 *
184 * {@link #queueLength} is updated separately via {@link LoadStatisticsUpdater} to
185 * improve the efficiency because we are counting this for all {@link LoadStatistics} at once.
186 */
187 protected void updateExecutorCounts() {
188 int t = computeTotalExecutors();
189 int i = computeIdleExecutors();
190 totalExecutors.update(t);
191 busyExecutors.update(t-i);
192 }
193
194 /**
195 * With 0.90 decay ratio for every 10sec, half reduction is about 1 min.
196 */
197 public static final float DECAY = Float.parseFloat(System.getProperty(LoadStatistics.class.getName()+".decay","0.9"));
198 /**
199 * Load statistics clock cycle in milliseconds. Specify a small value for quickly debugging this feature and node provisioning through cloud.
200 */
201 public static int CLOCK = Integer.getInteger(LoadStatistics.class.getName()+".clock",10*1000);
202
203 /**
204 * Periodically update the load statistics average.
205 */
206 @Extension
207 public static class LoadStatisticsUpdater extends PeriodicWork {
208 public long getRecurrencePeriod() {
209 return CLOCK;
210 }
211
212 protected void doRun() {
213 Jenkins j = Jenkins.getInstance();
214 List<Queue.BuildableItem> bis = j.getQueue().getBuildableItems();
215
216 // update statistics on slaves
217 for( Label l : j.getLabels() ) {
218 l.loadStatistics.updateExecutorCounts();
219 l.loadStatistics.queueLength.update(count(bis, l));
220 }
221
222 // update statistics of the entire system
223 j.unlabeledLoad.updateExecutorCounts();
224 j.unlabeledLoad.queueLength.update(count(bis, null));
225
226 j.overallLoad.updateExecutorCounts();
227 j.overallLoad.queueLength.update(bis.size());
228 }
229
230 private int count(List<Queue.BuildableItem> bis, Label l) {
231 int q=0;
232 for (Queue.BuildableItem bi : bis) {
233 if(bi.task.getAssignedLabel()==l)
234 q++;
235 }
236 return q;
237 }
238 }
239 }
240