View Javadoc

1   package org.whatsitcalled.webflange.webapp;
2   
3   import java.awt.Color;
4   import java.awt.Graphics2D;
5   import java.io.File;
6   import java.text.Format;
7   import java.text.SimpleDateFormat;
8   import java.util.ArrayList;
9   import java.util.Date;
10  import java.util.List;
11  
12  import org.apache.log4j.Logger;
13  import org.apache.wicket.AttributeModifier;
14  import org.apache.wicket.PageParameters;
15  import org.apache.wicket.behavior.HeaderContributor;
16  import org.apache.wicket.behavior.SimpleAttributeModifier;
17  import org.apache.wicket.markup.html.IHeaderContributor;
18  import org.apache.wicket.markup.html.IHeaderResponse;
19  import org.apache.wicket.markup.html.basic.Label;
20  import org.apache.wicket.markup.html.form.Button;
21  import org.apache.wicket.markup.html.form.CheckBox;
22  import org.apache.wicket.markup.html.form.Form;
23  import org.apache.wicket.markup.html.form.RequiredTextField;
24  import org.apache.wicket.markup.html.form.TextField;
25  import org.apache.wicket.markup.html.image.Image;
26  import org.apache.wicket.markup.html.image.resource.RenderedDynamicImageResource;
27  import org.apache.wicket.markup.html.link.BookmarkablePageLink;
28  import org.apache.wicket.markup.html.link.DownloadLink;
29  import org.apache.wicket.markup.html.link.Link;
30  import org.apache.wicket.markup.html.list.ListItem;
31  import org.apache.wicket.markup.html.list.ListView;
32  import org.apache.wicket.markup.html.panel.Panel;
33  import org.apache.wicket.markup.repeater.Item;
34  import org.apache.wicket.markup.repeater.data.DataView;
35  import org.apache.wicket.markup.repeater.data.IDataProvider;
36  import org.apache.wicket.model.AbstractReadOnlyModel;
37  import org.apache.wicket.model.CompoundPropertyModel;
38  import org.apache.wicket.model.IModel;
39  import org.apache.wicket.model.Model;
40  import org.apache.wicket.model.PropertyModel;
41  import org.whatsitcalled.webflange.ResourceFactory;
42  import org.whatsitcalled.webflange.model.Chart;
43  import org.whatsitcalled.webflange.model.LoadTest;
44  import org.whatsitcalled.webflange.model.LoadTestRun;
45  import org.whatsitcalled.webflange.model.LoadTestSummary;
46  import org.whatsitcalled.webflange.service.LoadTestRunningException;
47  import org.whatsitcalled.webflange.webapp.model.LoadTestSummaryDataProvider;
48  
49  public class ReportsPanel extends Panel {
50  
51  	private static final Logger LOGGER = Logger.getLogger(ReportsPanel.class);
52  
53  	private LoadTestReportPanel loadTestReportPanel;
54  
55  	private LoadTestRunReportPanel loadTestRunReportPanel;
56  
57  	public ReportsPanel(String arg0, PageParameters parameters) {
58  		super(arg0);
59  		loadTestReportPanel = new LoadTestReportPanel("loadTestReportPanel");
60  		loadTestReportPanel.setVisible(false);
61  		loadTestRunReportPanel = new LoadTestRunReportPanel(
62  				"loadTestRunReportPanel");
63  		loadTestRunReportPanel.setVisible(false);
64  		add(loadTestReportPanel);
65  		add(loadTestRunReportPanel);
66  
67  		if (parameters.containsKey("testId")) {
68  			Long id = parameters.getLong("testId");
69  			LoadTest test = ResourceFactory.getLoadTestDAO().getLoadTest(id);
70  			loadTestReportPanel.setModel(new CompoundPropertyModel(test));
71  			loadTestReportPanel.setVisible(true);
72  			loadTestRunReportPanel.setVisible(false);
73  		} else if (parameters.containsKey("runId")) {
74  			Long id = parameters.getLong("runId");
75  			LoadTestRun run = ResourceFactory.getLoadTestRunDAO()
76  					.getLoadTestRun(id);
77  			loadTestRunReportPanel.setModel(new CompoundPropertyModel(run));
78  			loadTestRunReportPanel.setVisible(true);
79  			loadTestReportPanel.setVisible(false);
80  		}
81  	}
82  	
83  	public class ChartNavPanel extends Panel {
84  		private LoadTest test;
85  		private LoadTestRun run;
86  		private List<Chart> charts;
87  		public ChartNavPanel(String id, LoadTest test) {
88  			super(id);
89  			this.test = test;
90  			this.run = null;
91  			if (test.getRuns().size() < 1) {
92  				this.charts = new ArrayList<Chart>();
93  				this.setVisible(false);
94  			} else {
95  				this.charts = test.getCharts();
96  				this.setVisible(true);
97  			}
98  			setModel(new CompoundPropertyModel(this.charts));
99  		}
100 
101 		public ChartNavPanel(String id, LoadTestRun run) {
102 			super(id);
103 			this.test = null;
104 			this.run = run;
105 			this.charts = run.getCharts();
106 			setModel(new CompoundPropertyModel(this.charts));
107 		}
108 
109 		@Override
110 		protected void onModelChanged() {
111 			super.onModelChanged();
112 			removeAll();
113 			addOrReplace(new ListView("chartList", this.charts) {
114 				public void populateItem(final ListItem item) {
115 					
116 					final Chart chart = (Chart) item.getModelObject();
117 
118 					// Add the chart Label
119 					item.add(new Label("chartName", chart.getName() + " "));
120 
121 					// Add the Chart Link
122 					Link chartLink = new Link("chartLink") {
123 						public void onClick() {
124 							Chart chart = (Chart) getParent().getModelObject();
125 							if (chart.isVisible()) {
126 								LOGGER
127 										.debug("Hiding chart: "
128 												+ chart.getName());
129 								chart.setVisible(false);
130 							} else {
131 								LOGGER.debug("Showing chart: "
132 										+ chart.getName());
133 								chart.setVisible(true);
134 							}
135 							ResourceFactory.getChartService().saveChart(chart);
136 						}
137 					};
138 					chartLink.add(new Label("chartVisible", new Model() {
139 						public Object getObject() {
140 							return chart.isVisible() ? "hide" : "show";
141 						}
142 					}));
143 					item.add(chartLink);
144 					item.add(new Link("deleteChart") {
145 						public void onClick() {
146 							Chart chart = (Chart) getParent().getModelObject();
147 							if (run == null) {
148 								ResourceFactory.getChartService().removeChart(chart, test);
149 								loadTestReportPanel.removeAll();
150 								loadTestReportPanel.setModelObject(test);
151 								loadTestReportPanel.modelChanged();
152 							} else {
153 								ResourceFactory.getChartService().removeChart(chart, run);
154 								loadTestRunReportPanel.removeAll();
155 								loadTestRunReportPanel.setModelObject(run);
156 								loadTestRunReportPanel.modelChanged();
157 							}
158 						}
159 					});
160 				}
161 			});
162 
163 			addOrReplace(new ListView("charts", this.charts) {
164 				public void populateItem(final ListItem item) {
165 					final Chart chart = (Chart) item.getModelObject();
166 					
167 					// Prepare the chart
168 					if (run == null ) {
169 						ResourceFactory.getChartService().prepareChart(chart, test.getId());
170 					}
171 					else ResourceFactory.getChartService().prepareChart(chart, run);
172 					
173 					ChartDynamicImageResource resource = new ChartDynamicImageResource(chart);
174 
175 					// Add the Chart image
176 					Image chartImage = new Image("chartImage", resource);
177 					item.add(chartImage);
178 					item.setVisible(chart.isVisible());
179 				}
180 			});
181 		}
182 	}
183 
184 	public class LoadTestReportPanel extends Panel {
185 
186 		private String name = "";
187 
188 		public LoadTestReportPanel(String arg0) {
189 			super(arg0);
190 		}
191 
192 		@Override
193 		protected void onModelChanged() {
194 			super.onModelChanged();
195 			removeAll();
196 			final LoadTest test = (LoadTest) getModelObject();
197 
198 			if (test.getEnabled()) {
199 				// Add refresh to the header
200 				HeaderContributor contributor = new HeaderContributor(
201 						new IHeaderContributor() {
202 							public void renderHead(IHeaderResponse response) {
203 								response
204 										.renderString("<meta http-equiv=\"refresh\" content=\"60\" >\n");
205 							}
206 						});
207 				add(contributor);
208 			}
209 
210 			addOrReplace(new Label("testName", test.getName()));
211 			
212 			// The Chart Panel
213 			ChartNavPanel chartNavPanel = new ChartNavPanel("chartNav", test);
214 			chartNavPanel.setVisible(test.getCharts().size() > 0);
215 			addOrReplace(chartNavPanel);
216 			
217 			//The ChartForm
218 			LoadTestChartForm chartForm = new LoadTestChartForm("chartForm",
219 					new CompoundPropertyModel(new Chart()),test);
220 			addOrReplace(chartForm);
221 		}
222 		public void setLoadTest(final Long id) {
223 			LoadTest newLoadTest = ResourceFactory
224 			.getLoadTestService().getLoadTest(id);
225 			ResourceFactory
226 			.getLoadTestService().saveLoadTest(newLoadTest);
227 			setModel(new CompoundPropertyModel(newLoadTest));
228 		}
229 		
230 	}
231 
232 	public class LoadTestChartForm extends Form {
233 
234 		private LoadTest loadTest;
235 		private LoadTestSummaryDataView view;
236 
237 		public LoadTestChartForm(String arg0, IModel arg1, LoadTest test) {
238 			super(arg0, arg1);
239 			setLoadTest(test);
240 			this.view = new LoadTestSummaryDataView("summaries",
241 					new LoadTestSummaryDataProvider(test), test);
242 			addOrReplace(view);
243 			final Button delete = new Button("deleteButton") {
244 				public void onSubmit() {
245 					List<LoadTestRun> runs = view.getRuns();
246 					try {
247 						ResourceFactory.getLoadTestService()
248 								.removeSelectedRuns(loadTest.getId(), runs);
249 						loadTestReportPanel.setLoadTest(loadTest.getId());
250 					} catch (LoadTestRunningException e) {
251 						LOGGER.error("Unable to delete runs...");
252 					}
253 				}
254 			};
255 			delete.add(new SimpleAttributeModifier("onclick",
256 					"return confirm('Delete selected runs?');"));
257 			delete.add(new TestNotEnabledValidator(test.getId(), test.getName() + " must not be enabled or running to delete run data!"));
258 			add(delete);
259 
260 			final Button chart = new Button("chartButton") {
261 				public void onSubmit() {
262 					Chart chart = getChart();
263 					ResourceFactory.getChartService().generateDefaultChart(
264 							chart, loadTest.getId());
265 					// Have a look at the selected runs
266 					List<LoadTestRun> runs = view.getRuns();
267 					for (LoadTestRun run : runs) {
268 						if (run.getSelected()) {
269 							LOGGER.debug("Run is selected: " + run.getTime());
270 						}
271 					}
272 					loadTestReportPanel.setLoadTest(loadTest.getId());
273 				}
274 
275 			};
276 			add(chart);
277 
278 			TextField name = new TextField("name") {
279 				public boolean isRequired() {
280 					Form form = (Form) findParent(Form.class);
281 					return form.getRootForm().findSubmittingButton() == chart;
282 				}
283 
284 			};
285 
286 			add(name);
287 			add(new CheckBox("showTests"));
288 			add(new CheckBox("showErrors"));
289 			add(new CheckBox("showMeanTestTime"));
290 			add(new CheckBox("showTestTimeStandardDeviation"));
291 			add(new CheckBox("showMeanResponseLength"));
292 			add(new CheckBox("showResponseBytesPerSecond"));
293 			add(new CheckBox("showResponseErrors"));
294 			add(new CheckBox("showMeanTimeToResolveHost"));
295 			add(new CheckBox("showMeanTimeToEstablishConnection"));
296 			add(new CheckBox("showMeanTimeToFirstByte"));
297 
298 		}
299 
300 		private Chart getChart() {
301 			return (Chart) this.getModelObject();
302 		}
303 
304 		public LoadTest getLoadTest() {
305 			return loadTest;
306 		}
307 
308 		public void setLoadTest(final LoadTest loadTest) {
309 			this.loadTest = loadTest;
310 		}
311 		
312 	}
313 
314 	public class LoadTestRunReportPanel extends Panel {
315 
316 		private String name = "";
317 
318 		public LoadTestRunReportPanel(String arg0) {
319 			super(arg0);
320 		}
321 
322 		@Override
323 		protected void onModelChanged() {
324 			super.onModelChanged();
325 			final LoadTestRun run = (LoadTestRun) getModelObject();
326 
327 			// Add the links for Grinder logs
328 			File dataFile = ResourceFactory.getLoadTestService().getDataFile(
329 					run);
330 			DownloadLink dfLink = new DownloadLink("dataFileLink", dataFile);
331 			dfLink.setVisible(dataFile.exists());
332 			addOrReplace(dfLink);
333 
334 			File summaryFile = ResourceFactory.getLoadTestService()
335 					.getSummaryFile(run);
336 			DownloadLink sfLink = new DownloadLink("summaryFileLink",
337 					summaryFile);
338 			sfLink.setVisible(summaryFile.exists());
339 			addOrReplace(sfLink);
340 
341 			File errorFile = ResourceFactory.getLoadTestService()
342 					.getErrorFile(run);
343 			DownloadLink efLink = new DownloadLink("errorFileLink", errorFile);
344 			efLink.setVisible(errorFile.exists());
345 			addOrReplace(efLink);
346 
347 			// The test name is a link back
348 			Label testNameLabel = new Label("testName", run.getLoadTest()
349 					.getName());
350 			Link testLink = new BookmarkablePageLink("testLink",
351 					HomePage.class, new PageParameters("testId="
352 							+ run.getLoadTest().getId()));
353 			testLink.add(testNameLabel);
354 			addOrReplace(testLink);
355 			addOrReplace(new Label("runName", getFormattedDate(run.getTime())));
356 
357 			// The Chart Panel
358 			ChartNavPanel chartNavPanel = new ChartNavPanel("chartNav", run);
359 			chartNavPanel.setVisible(run.getCharts().size() > 0);
360 			addOrReplace(chartNavPanel);
361 
362 			LoadTestRunChartForm chartForm = new LoadTestRunChartForm(
363 					"chartForm", new CompoundPropertyModel(new Chart()));
364 			addOrReplace(chartForm);
365 			chartForm.setRun(run);
366 		}
367 		public void setRun(final Long id) {
368 			LoadTestRun newLoadTestRun = ResourceFactory
369 			.getLoadTestRunDAO().getLoadTestRun(id);
370 			ResourceFactory.getLoadTestRunDAO().saveLoadTestRun(newLoadTestRun);
371 			setModel(new CompoundPropertyModel(newLoadTestRun));
372 		}
373 	}
374 
375 	public class LoadTestRunChartForm extends Form {
376 
377 		private LoadTestRun run;
378 
379 		public LoadTestRunChartForm(String arg0, IModel arg1) {
380 			super(arg0, arg1);
381 			add(new RequiredTextField("name"));
382 			add(new CheckBox("showTests"));
383 			add(new CheckBox("showErrors"));
384 			add(new CheckBox("showMeanTestTime"));
385 			add(new CheckBox("showTestTimeStandardDeviation"));
386 			add(new CheckBox("showMeanResponseLength"));
387 			add(new CheckBox("showResponseBytesPerSecond"));
388 			add(new CheckBox("showResponseErrors"));
389 			add(new CheckBox("showMeanTimeToResolveHost"));
390 			add(new CheckBox("showMeanTimeToEstablishConnection"));
391 			add(new CheckBox("showMeanTimeToFirstByte"));
392 
393 		}
394 
395 		@Override
396 		protected void onSubmit() {
397 			Chart chart = getChart();
398 			ResourceFactory.getChartService().generateDefaultChart(chart, run);
399 			loadTestRunReportPanel.setRun(run.getId());
400 		}
401 
402 		private Chart getChart() {
403 			return (Chart) this.getModelObject();
404 		}
405 
406 		public LoadTestRun getRun() {
407 			return run;
408 		}
409 
410 		public void setRun(final LoadTestRun run) {
411 			this.run = run;
412 			add(new LoadTestRunSummaryDataView("summaries",
413 					new LoadTestSummaryDataProvider(run), run));
414 		}
415 
416 	}
417 
418 	public String getFormattedDate(long ldate) {
419 		Format formatter = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
420 		Date date = new Date(ldate);
421 		return formatter.format(date);
422 	}
423 
424 	protected final class LoadTestSummaryDataView extends DataView {
425 		private LoadTest test = null;
426 		private List<LoadTestRun> runs = new ArrayList<LoadTestRun>();
427 		
428 		protected LoadTestSummaryDataView(String arg0, IDataProvider arg1,
429 				LoadTest test) {
430 			super(arg0, arg1);
431 			this.test = test;
432 		}
433 
434 		protected void populateItem(final Item item) {
435 			final LoadTestSummary summary = (LoadTestSummary) item
436 					.getModelObject();
437 			// For deleting and manipulating run related data
438 			LoadTestRun curRun = summary.getRun();
439 			runs.add(curRun);
440 			CheckBox runCheckBox = new CheckBox("selected", new PropertyModel(
441 					curRun, "selected"));
442 			item.add(runCheckBox);
443 
444 			// The rest of the data
445 			String name = null;
446 			BookmarkablePageLink link = null;
447 			String dateString = getFormattedDate(summary.getRun().getTime());
448 			name = dateString;
449 			link = new BookmarkablePageLink("link", HomePage.class,
450 					new PageParameters("runId=" + summary.getRun().getId()));
451 			link.add(new Label("test", name));
452 			item.add(link);
453 			item.add(new Label("errors", Long.toString(summary.getErrors())));
454 			item.add(new Label("meanResponseLength", Long.toString(summary
455 					.getMeanResponseLength())));
456 			item.add(new Label("meanTestTime", Long.toString(summary
457 					.getMeanTestTime())));
458 			item.add(new Label("meanTimeToEstablishConnection", Long
459 					.toString(summary.getMeanTimeToEstablishConnection())));
460 			item.add(new Label("meanTimeToFirstByte", Long.toString(summary
461 					.getMeanTimeToFirstByte())));
462 			item.add(new Label("meanTimeToResolveHost", Long.toString(summary
463 					.getMeanTimeToResolveHost())));
464 			item.add(new Label("responseBytesPerSecond", Long.toString(summary
465 					.getResponseBytesPerSecond())));
466 			item.add(new Label("responseErrors", Long.toString(summary
467 					.getResponseErrors())));
468 			item.add(new Label("tests", Long.toString(summary.getTests())));
469 			item.add(new Label("testTimeStandardDeviation", Float
470 					.toString(summary.getTestTimeStandardDeviation())));
471 
472 			item.add(new AttributeModifier("class", true,
473 					new AbstractReadOnlyModel() {
474 						public Object getObject() {
475 							return (item.getIndex() % 2 == 1) ? "even" : "odd";
476 						}
477 					}));
478 
479 		}
480 
481 		public List<LoadTestRun> getRuns() {
482 			return runs;
483 		}
484 
485 		public void setRuns(List<LoadTestRun> runs) {
486 			this.runs = runs;
487 		}
488 
489 	}
490 
491 	public class ChartDynamicImageResource extends RenderedDynamicImageResource {
492 
493 		private Chart chart;
494 
495 		public ChartDynamicImageResource(Chart c) {
496 			super(c.getChartImage().getWidth(), c.getChartImage().getHeight());
497 			this.chart = c;
498 		}
499 
500 		@Override
501 		protected boolean render(Graphics2D g) {
502 			g.drawImage(chart.getChartImage(), 0, 0, Color.WHITE, null);
503 			return true;
504 		}
505 
506 	}
507 
508 	protected final class LoadTestRunSummaryDataView extends DataView {
509 		private LoadTestRun run = null;
510 
511 		private List<LoadTestRun> runs = new ArrayList<LoadTestRun>();
512 
513 		protected LoadTestRunSummaryDataView(String arg0, IDataProvider arg1,
514 				LoadTestRun run) {
515 			super(arg0, arg1);
516 			this.run = run;
517 		}
518 
519 		protected void populateItem(final Item item) {
520 			final LoadTestSummary summary = (LoadTestSummary) item
521 					.getModelObject();
522 
523 			// The rest of the data
524 			String name = null;
525 			BookmarkablePageLink link = null;
526 			name = summary.getTestName();
527 			link = new BookmarkablePageLink("link", HomePage.class,
528 					new PageParameters("testId=" + run.getLoadTest().getId()));
529 			link.add(new Label("test", name));
530 			item.add(link);
531 			item.add(new Label("errors", Long.toString(summary.getErrors())));
532 			item.add(new Label("meanResponseLength", Long.toString(summary
533 					.getMeanResponseLength())));
534 			item.add(new Label("meanTestTime", Long.toString(summary
535 					.getMeanTestTime())));
536 			item.add(new Label("meanTimeToEstablishConnection", Long
537 					.toString(summary.getMeanTimeToEstablishConnection())));
538 			item.add(new Label("meanTimeToFirstByte", Long.toString(summary
539 					.getMeanTimeToFirstByte())));
540 			item.add(new Label("meanTimeToResolveHost", Long.toString(summary
541 					.getMeanTimeToResolveHost())));
542 			item.add(new Label("responseBytesPerSecond", Long.toString(summary
543 					.getResponseBytesPerSecond())));
544 			item.add(new Label("responseErrors", Long.toString(summary
545 					.getResponseErrors())));
546 			item.add(new Label("tests", Long.toString(summary.getTests())));
547 			item.add(new Label("testTimeStandardDeviation", Float
548 					.toString(summary.getTestTimeStandardDeviation())));
549 
550 			item.add(new Label("uri", summary.getTestUri()));
551 			item.add(new AttributeModifier("class", true,
552 					new AbstractReadOnlyModel() {
553 						public Object getObject() {
554 							return (item.getIndex() % 2 == 1) ? "even" : "odd";
555 						}
556 					}));
557 
558 		}
559 
560 	}
561 	
562 	
563 }