1
18 package net.bull.javamelody.internal.web.html;
19
20 import java.io.IOException;
21 import java.io.PrintWriter;
22 import java.io.StringWriter;
23 import java.io.Writer;
24 import java.net.URLEncoder;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Date;
28 import java.util.HashMap;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.Map;
33
34 import net.bull.javamelody.Parameter;
35 import net.bull.javamelody.SessionListener;
36 import net.bull.javamelody.internal.common.I18N;
37 import net.bull.javamelody.internal.common.LOG;
38 import net.bull.javamelody.internal.common.Parameters;
39 import net.bull.javamelody.internal.model.Action;
40 import net.bull.javamelody.internal.model.CacheInformations;
41 import net.bull.javamelody.internal.model.Collector;
42 import net.bull.javamelody.internal.model.CollectorServer;
43 import net.bull.javamelody.internal.model.Counter;
44 import net.bull.javamelody.internal.model.CounterRequestContext;
45 import net.bull.javamelody.internal.model.HsErrPid;
46 import net.bull.javamelody.internal.model.JCacheInformations;
47 import net.bull.javamelody.internal.model.JRobin;
48 import net.bull.javamelody.internal.model.JavaInformations;
49 import net.bull.javamelody.internal.model.JobInformations;
50 import net.bull.javamelody.internal.model.Period;
51 import net.bull.javamelody.internal.model.Range;
52 import net.bull.javamelody.internal.model.ThreadInformations;
53 import net.bull.javamelody.internal.model.UpdateChecker;
54 import net.bull.javamelody.internal.model.VirtualMachine;
55
56
60 class HtmlCoreReport extends HtmlAbstractReport {
61 private static final int MAX_CURRENT_REQUESTS_DISPLAYED_IN_MAIN_REPORT = 500;
62 private static final int MAX_THREADS_DISPLAYED_IN_MAIN_REPORT = 500;
63 private static final String SEPARATOR = " ";
64 private static final String END_DIV = "</div>";
65 private final Collector collector;
66 private final List<JavaInformations> javaInformationsList;
67 private final Range range;
68 private final CollectorServer collectorServer;
69 private final long start = System.currentTimeMillis();
70 private final Map<String, String> menuTextsByAnchorName = new LinkedHashMap<>();
71
72 HtmlCoreReport(Collector collector, CollectorServer collectorServer,
73 List<JavaInformations> javaInformationsList, Range range, Writer writer) {
74 super(writer);
75 assert collector != null;
76 assert javaInformationsList != null && !javaInformationsList.isEmpty();
77 assert range != null;
78
79 this.collector = collector;
80 this.collectorServer = collectorServer;
81 this.javaInformationsList = javaInformationsList;
82 this.range = range;
83 }
84
85 @Override
86 void toHtml() throws IOException {
87 toHtml(null, null);
88 }
89
90 void toHtml(String message, String anchorNameForRedirect) throws IOException {
91 writeAlerts();
92 if (collectorServer != null) {
93 writeApplicationsLinks();
94 }
95
96 writeln("<h3 class='chapterTitle'><img src='?resource=systemmonitor.png' alt='#Stats#'/>");
97 writeAnchor("top", I18N.getString("Stats"));
98 writeSummary();
99 writeln("</h3>");
100 write("<a class='donate' href='https:);
101 writeln("<img class='noPrint' src='?resource=donate.gif' alt='Donate' /></a>");
102 writeln("<div align='center'>");
103 writeRefreshAndPeriodLinks(null, null);
104 writeGraphs();
105 writeln(END_DIV);
106
107 final List<Counter> counters = collector.getRangeCountersToBeDisplayed(range);
108 final Map<String, HtmlCounterReport> counterReportsByCounterName = writeCounters(counters);
109
110 if (collectorServer == null) {
111 writeln("<h3 class='chapterTitle'><img src='?resource=hourglass.png' alt='#Requetes_en_cours#'/>");
112 writeAnchor("currentRequests", I18N.getString("Requetes_en_cours"));
113 writeln("#Requetes_en_cours#</h3>");
114
115 writeCurrentRequests(javaInformationsList.get(0), counters,
116 counterReportsByCounterName);
117 }
118
119 writeln("<h3 class='chapterTitle'><img src='?resource=systeminfo.png' alt='#Informations_systemes#'/>");
120 writeAnchor("systeminfo", I18N.getString("Informations_systemes"));
121 writeln("#Informations_systemes#</h3>");
122 if (collectorServer != null) {
123 writeln("<div align='center' class='noPrint'><a href='?part=currentRequests'>");
124 writeln("<img src='?resource=hourglass.png' width='20' height='20' alt=\"#Voir_requetes_en_cours#\" /> #Voir_requetes_en_cours#</a>");
125 writeln(END_DIV);
126 writeln("<br/>");
127 }
128 if (Parameters.isSystemActionsEnabled()) {
129 writeSystemActionsLinks();
130 }
131
132 new HtmlJavaInformationsReport(javaInformationsList, getWriter()).toHtml();
133
134 writeln("<h3 class='chapterTitle'><img src='?resource=threads.png' alt='#Threads#'/>");
135 writeAnchor("threads", I18N.getString("Threads"));
136 writeln("#Threads#</h3>");
137 writeThreads();
138
139 if (isJobEnabled()) {
140 writeln("<h3 class='chapterTitle'><img src='?resource=jobs.png' alt='#Jobs#'/>");
141 writeAnchor("jobs", I18N.getString("Jobs"));
142 writeln("#Jobs#</h3>");
143 writeJobs(collector.getRangeCounter(range, Counter.JOB_COUNTER_NAME));
144 }
145
146 if (isCacheEnabled()) {
147 writeln("<h3 class='chapterTitle'><img src='?resource=caches.png' alt='#Caches#'/>");
148 writeAnchor("caches", I18N.getString("Caches"));
149 writeln("#Caches#</h3>");
150 writeCaches();
151 }
152 if (isJCacheEnabled()) {
153 writeln("<h3 class='chapterTitle'><img src='?resource=caches.png' alt='#Caches#'/>");
154 writeAnchor("caches", I18N.getString("Caches"));
155 writeln("#Caches#</h3>");
156 writeJCaches();
157 }
158
159
160
161
162
163 writeMenu();
164
165 writeMessageIfNotNull(message, null, anchorNameForRedirect);
166 writeDurationAndOverhead();
167 }
168
169 private void writeAlerts() throws IOException {
170 final String newJavamelodyVersion = UpdateChecker.getNewJavamelodyVersion();
171 if (newJavamelodyVersion != null) {
172 writeln("<div class='newVersion' align='center'>");
173 writeln("<img src='?resource=alert.png' alt='alert'/>");
174 writeDirectly(I18N.getFormattedString("version_alert", newJavamelodyVersion,
175 Parameters.JAVAMELODY_VERSION));
176 writeln("</div>");
177 }
178 final Throwable lastCollectorException = collector.getLastCollectorException();
179 if (lastCollectorException != null) {
180 writeln("<div class='alert'>");
181 writeln("<img src='?resource=alert.png' alt='alert'/>");
182 writeDirectly(htmlEncodeButNotSpace(lastCollectorException.toString()));
183 writeln("</div>");
184 writeShowHideLink("detailsLastCollectorException", "#Details#");
185 writeln("<div id='detailsLastCollectorException' class='displayNone'><div>");
186 final StringWriter stackTraceWriter = new StringWriter(200);
187 lastCollectorException.printStackTrace(new PrintWriter(stackTraceWriter));
188 for (final String stackTraceElement : stackTraceWriter.toString().split("[\n\r]")) {
189 if (!stackTraceElement.isEmpty()) {
190
191 writeDirectly(
192 HtmlSourceReport.htmlEncodeStackTraceElementAndTabs(stackTraceElement));
193 writeDirectly("<br/>\n");
194 }
195 }
196 writeln("</div></div>");
197 }
198 if (collectorServer != null
199 && collectorServer.isApplicationDataAvailable(collector.getApplication())
200 && javaInformationsList.size() < collectorServer
201 .getUrlsByApplication(collector.getApplication()).size()) {
202 writeln("<div class='alert'>");
203 writeln("<img src='?resource=alert.png' alt='alert'/> #some_node_unavailable#");
204 writeln("</div><br/>");
205 }
206 }
207
208 private void writeSummary() throws IOException {
209 final String javaMelodyUrl = "<a href='https:;
210 if (range.getPeriod() == Period.TOUT) {
211 final String startDate = I18N.createDateAndTimeFormat()
212 .format(collector.getCounters().get(0).getStartDate());
213 writeDirectly(getFormattedString("Statistiques", javaMelodyUrl,
214 I18N.getCurrentDateAndTime(), startDate, collector.getApplication()));
215 } else {
216 writeDirectly(getFormattedString("Statistiques_sans_depuis", javaMelodyUrl,
217 I18N.getCurrentDateAndTime(), collector.getApplication()));
218 }
219 final String contextDisplayName = javaInformationsList.get(0).getContextDisplayName();
220 final String webappVersion = javaInformationsList.get(0).getWebappVersion();
221 if (contextDisplayName != null) {
222 writeDirectly(" (");
223 writeDirectly(htmlEncodeButNotSpace(contextDisplayName));
224 if (webappVersion != null) {
225 writeDirectly(", " + htmlEncodeButNotSpace(webappVersion));
226 }
227 writeDirectly(")");
228 } else if (webappVersion != null) {
229 writeDirectly(" (");
230 writeDirectly(htmlEncodeButNotSpace(webappVersion));
231 writeDirectly(")");
232 }
233 writeln("");
234 }
235
236 private void writeAnchor(String anchorName, String menuText) throws IOException {
237 write("<a name='" + anchorName + "'></a>");
238 menuTextsByAnchorName.put(anchorName, menuText);
239 }
240
241 private void writeMenu() throws IOException {
242 writeln("<div class='noPrint'> ");
243 writeln("<div id='menuBox' class='menuHide'>");
244 writeln(" <ul id='menuTab'><li><a class='menuBoxToggle'><img id='menuToggle' src='?resource=menu.png' alt='menu' /></a></li></ul>");
245 writeln(" <div id='menuLinks'><div id='menuDeco'>");
246 for (final Map.Entry<String, String> entry : menuTextsByAnchorName.entrySet()) {
247 final String anchorName = entry.getKey();
248 final String menuText = entry.getValue();
249 writeDirectly(" <div class='menuButton'><a href='#" + anchorName + "'>" + menuText
250 + "</a></div>");
251 writeln("");
252 }
253 final String customReports = Parameter.CUSTOM_REPORTS.getValue();
254 if (customReports != null) {
255 for (final String customReport : customReports.split(",")) {
256 final String customReportName = customReport.trim();
257 final String customReportPath = Parameters
258 .getParameterValueByName(customReportName);
259 if (customReportPath == null) {
260 LOG.debug("Parameter not defined in web.xml for custom report: "
261 + customReportName);
262 continue;
263 }
264 writeDirectly(" <div class='menuButton'><a href='?report="
265 + URLEncoder.encode(customReportName, "UTF-8") + "'>"
266 + htmlEncode(customReportName) + "</a></div>");
267 writeln("");
268 }
269 }
270 if (SessionListener.getCurrentSession() != null) {
271 writeDirectly(" <div class='menuButton'><a href='?action=logout"
272 + getCsrfTokenUrlPart() + "'>" + I18N.getString("logout") + "</a></div>");
273 writeln("");
274 }
275 writeln(" </div></div>");
276 writeln("</div></div>");
277 }
278
279 private Map<String, HtmlCounterReport> writeCounters(List<Counter> counters)
280 throws IOException {
281 final Map<String, HtmlCounterReport> counterReportsByCounterName = new HashMap<>();
282 for (final Counter counter : counters) {
283 final HtmlCounterReport htmlCounterReport = writeCounter(counter);
284 counterReportsByCounterName.put(counter.getName(), htmlCounterReport);
285 }
286
287 if (range.getPeriod() == Period.TOUT && counterReportsByCounterName.size() > 1) {
288 writeln("<div align='right'>");
289 writeln("<a href='?action=clear_counter&counter=all" + getCsrfTokenUrlPart()
290 + "' title='#Vider_toutes_stats#'");
291 writeln("class='confirm noPrint' data-confirm='"
292 + htmlEncodeButNotSpaceAndNewLine(getString("confirm_vider_toutes_stats"))
293 + "'>#Reinitialiser_toutes_stats#</a>");
294 writeln(END_DIV);
295 }
296
297 return counterReportsByCounterName;
298 }
299
300 private HtmlCounterReport writeCounter(Counter counter) throws IOException {
301 writeCounterTitle(counter);
302 final HtmlCounterReport htmlCounterReport = new HtmlCounterReport(counter, range,
303 getWriter());
304 htmlCounterReport.toHtml();
305 return htmlCounterReport;
306 }
307
308 private void writeCounterTitle(Counter counter) throws IOException {
309 writeln("<h3 class='chapterTitle'><img src='?resource=" + counter.getIconName() + "' alt='"
310 + counter.getName() + "'/>");
311 writeAnchor(counter.getName(),
312 I18N.getString("Stats") + ' ' + counter.getName().toLowerCase(Locale.ENGLISH));
313 final String counterLabel = getString(counter.getName() + "Label");
314 write(getFormattedString("Statistiques_compteur", counterLabel));
315 write(" - " + range.getLabel());
316 if (range.getPeriod() != Period.TOUT) {
317 write(" #depuis_minuit#");
318 }
319 writeln("</h3>");
320 }
321
322 static void writeAddAndRemoveApplicationLinks(String currentApplication,
323 Collection<String> applications, Writer writer) throws IOException {
324 new HtmlForms(writer).writeAddAndRemoveApplicationLinks(currentApplication, applications);
325 }
326
327 void writeMessageIfNotNull(String message, String partToRedirectTo,
328 String anchorNameForRedirect) throws IOException {
329 if (message != null) {
330 final String href;
331 if (partToRedirectTo == null) {
332 href = anchorNameForRedirect == null ? "?" : "?#" + anchorNameForRedirect;
333 } else {
334 href = "?part=" + partToRedirectTo;
335 }
336 writeDirectly("<span class='alertAndRedirect' data-alert='"
337 + htmlEncodeButNotSpaceAndNewLine(message) + "' data-href='" + href
338 + "'></span>");
339 }
340 }
341
342 private void writeGraphs() throws IOException {
343 if (collector.isStopped()) {
344
345
346 writeln("<div align='center' class='severe'><br/><br/>");
347 writeln("#collect_server_misusage#");
348 writeln("</div>");
349 return;
350 }
351 if (collector.isStorageUsedByMultipleInstances()) {
352 writeln("<div align='center' class='severe'><br/><br/>");
353 writeln("#storage_used_by_multiple_instances#");
354 writeln("</div><br/>");
355 }
356
357 writeGraphs(collector.getDisplayedCounterJRobins(), false);
358 final Collection<JRobin> otherJRobins = collector.getDisplayedOtherJRobins();
359 if (!otherJRobins.isEmpty()) {
360 writeln("<div align='right'>");
361 writeShowHideLink("detailsGraphs", "#Autres_courbes#");
362 writeln(END_DIV);
363 writeln("<div id='detailsGraphs' class='displayNone'><div>");
364 writeGraphs(otherJRobins, true);
365 writeln("</div></div>");
366 }
367 }
368
369 private void writeGraphs(Collection<JRobin> jrobins, boolean lazyGraphs) throws IOException {
370 int i = 0;
371 for (final JRobin jrobin : jrobins) {
372 final String jrobinName = jrobin.getName();
373 write("<a href='?part=graph&graph=" + jrobinName + "'><img class='synthese' ");
374 if (lazyGraphs) {
375 write("data-src");
376 } else {
377 write("src");
378 }
379 writeln("='?width=200&height=" + JRobin.SMALL_HEIGHT + "&graph=" + jrobinName
380 + "' alt=\"" + jrobin.getLabel() + "\" title=\"" + jrobin.getLabel()
381 + "\"/></a>");
382 i++;
383 if (i % 3 == 0) {
384
385 writeln("<br/>");
386 }
387 }
388 }
389
390 private void writeCurrentRequests(JavaInformations javaInformations, List<Counter> counters,
391 Map<String, HtmlCounterReport> counterReportsByCounterName) throws IOException {
392 final List<ThreadInformations> threadInformationsList = javaInformations
393 .getThreadInformationsList();
394 final boolean stackTraceEnabled = javaInformations.isStackTraceEnabled();
395 final List<CounterRequestContext> rootCurrentContexts = collector
396 .getRootCurrentContexts(counters);
397 writeCurrentRequests(threadInformationsList, rootCurrentContexts, stackTraceEnabled,
398 MAX_CURRENT_REQUESTS_DISPLAYED_IN_MAIN_REPORT, false, counterReportsByCounterName);
399 }
400
401 void writeAllCurrentRequestsAsPart(
402 Map<JavaInformations, List<CounterRequestContext>> currentRequests) throws IOException {
403 writeln("<div class='noPrint'>");
404 writeln("<a class='back' href=''><img src='?resource=action_back.png' alt='#Retour#'/> #Retour#</a>");
405 writeln(SEPARATOR);
406 writeln("<a href='?part=currentRequests'><img src='?resource=action_refresh.png' alt='#Actualiser#'/> #Actualiser#</a>");
407 if (isPdfEnabled()) {
408 writeln(SEPARATOR);
409 write("<a href='?part=currentRequests&format=pdf' title='#afficher_PDF#'>");
410 write("<img src='?resource=pdf.png' alt='#PDF#'/> #PDF#</a>");
411 }
412 writeln("</div><br/>");
413 for (final Map.Entry<JavaInformations, List<CounterRequestContext>> entry : currentRequests
414 .entrySet()) {
415 final JavaInformations javaInformations = entry.getKey();
416 final List<CounterRequestContext> rootCurrentContexts = entry.getValue();
417
418 final List<ThreadInformations> threadInformationsList = javaInformations
419 .getThreadInformationsList();
420 final boolean stackTraceEnabled = javaInformations.isStackTraceEnabled();
421 writeCurrentRequests(threadInformationsList, rootCurrentContexts, stackTraceEnabled,
422 Integer.MAX_VALUE, true, null);
423 write("<br/><br/>");
424 }
425 }
426
427 private void writeCurrentRequests(List<ThreadInformations> threadInformationsList,
428 List<CounterRequestContext> rootCurrentContexts, boolean stackTraceEnabled,
429 int maxContextsDisplayed, boolean onlyTitleAndDetails,
430 Map<String, HtmlCounterReport> counterReportsByCounterName) throws IOException {
431
432 final HtmlCounterRequestContextReport htmlCounterRequestContextReport = new HtmlCounterRequestContextReport(
433 rootCurrentContexts, counterReportsByCounterName, threadInformationsList,
434 stackTraceEnabled, maxContextsDisplayed, getWriter());
435 if (onlyTitleAndDetails) {
436 htmlCounterRequestContextReport.writeTitleAndDetails();
437 } else {
438 htmlCounterRequestContextReport.toHtml();
439 }
440 }
441
442 void writeAllThreadsAsPart() throws IOException {
443 final String separator = " ";
444 writeln("<div class='noPrint'>");
445 writeln("<a class='back' href=''><img src='?resource=action_back.png' alt='#Retour#'/> #Retour#</a>");
446 writeln(separator);
447 writeln("<a href='?part=threads'><img src='?resource=action_refresh.png' alt='#Actualiser#'/> #Actualiser#</a>");
448 if (isPdfEnabled()) {
449 writeln(" ");
450 write("<a href='?part=threads&format=pdf' title='#afficher_PDF#'>");
451 write("<img src='?resource=pdf.png' alt='#PDF#'/> #PDF#</a>");
452 }
453 for (final JavaInformations javaInformations : javaInformationsList) {
454 if (javaInformations.isStackTraceEnabled()) {
455 writeln(separator);
456 writeln("<a href='?part=threadsDump'><img src='?resource=text.png' alt='#Dump_threads_en_texte#'/> #Dump_threads_en_texte#</a>");
457 break;
458 }
459 }
460
461 writeln("</div> <br/>");
462 writeTitle("threads.png", getString("Threads"));
463 write(" <br/>");
464
465 for (final JavaInformations javaInformations : javaInformationsList) {
466 write(" <b>");
467 writeDirectly(getFormattedString("Threads_sur", javaInformations.getHost()));
468 write(": </b>");
469 writeln(getFormattedString("thread_count", javaInformations.getThreadCount(),
470 javaInformations.getPeakThreadCount(),
471 javaInformations.getTotalStartedThreadCount()));
472 final HtmlThreadInformationsReport htmlThreadInformationsReport = new HtmlThreadInformationsReport(
473 javaInformations.getThreadInformationsList(),
474 javaInformations.isStackTraceEnabled(), getWriter());
475 htmlThreadInformationsReport.writeDeadlocks();
476 writeln("<br/><br/>");
477 htmlThreadInformationsReport.toHtml();
478 }
479 }
480
481 void writeThreadsDump() throws IOException {
482 writeDirectly(I18N.getCurrentDateAndTime());
483 writeDirectly("\n\n");
484 for (final JavaInformations javaInformations : javaInformationsList) {
485 writeDirectly("===== " + getFormattedString("Threads_sur", javaInformations.getHost())
486 + " =====");
487 writeDirectly("\n\n");
488 final HtmlThreadInformationsReport htmlThreadInformationsReport = new HtmlThreadInformationsReport(
489 javaInformations.getThreadInformationsList(),
490 javaInformations.isStackTraceEnabled(), getWriter());
491 htmlThreadInformationsReport.writeThreadsDump();
492 }
493 }
494
495 private void writeThreads() throws IOException {
496 int i = 0;
497 for (final JavaInformations javaInformations : javaInformationsList) {
498 write("<b>");
499 writeDirectly(getFormattedString("Threads_sur", javaInformations.getHost()));
500 write(": </b>");
501 writeln(getFormattedString("thread_count", javaInformations.getThreadCount(),
502 javaInformations.getPeakThreadCount(),
503 javaInformations.getTotalStartedThreadCount()));
504 writeln(SEPARATOR);
505 final List<ThreadInformations> threadInformationsList = javaInformations
506 .getThreadInformationsList();
507 final HtmlThreadInformationsReport htmlThreadInformationsReport = new HtmlThreadInformationsReport(
508 threadInformationsList, javaInformations.isStackTraceEnabled(), getWriter());
509 if (threadInformationsList.size() <= MAX_THREADS_DISPLAYED_IN_MAIN_REPORT) {
510 final String id = "threads_" + i;
511 writeShowHideLink(id, "#Details#");
512 htmlThreadInformationsReport.writeDeadlocks();
513 writeln("<br/><br/><div id='" + id + "' class='displayNone'>");
514 htmlThreadInformationsReport.toHtml();
515
516 writeln("<div align='right' class='noPrint'><br/>");
517 if (javaInformations.isStackTraceEnabled()) {
518 writeln("<a href='?part=threadsDump'><img src='?resource=text.png' alt='#Dump_threads_en_texte#'/> #Dump_threads_en_texte#</a>");
519 }
520 writeln(SEPARATOR);
521 writeln("<a href='?part=threads'><img src='?resource=threads.png' alt='#Threads#' width='16' height='16'/> #Voir_dans_une_nouvelle_page#</a>");
522 writeln("</div>");
523
524 writeln("</div><br/>");
525 } else {
526
527
528 writeln("<a href='?part=threads' class='noPrint'>#Details#</a><br/>");
529 }
530 i++;
531 }
532 }
533
534 void writeCounterSummaryPerClass(String counterName, String requestId) throws IOException {
535 final Counter counter = collector.getRangeCounter(range, counterName);
536 writeln("<div class='noPrint'>");
537 writeln("<a class='back' href=''><img src='?resource=action_back.png' alt='#Retour#'/> #Retour#</a>");
538 writeln(SEPARATOR);
539 final String hrefStart = "<a href='?part=counterSummaryPerClass&counter="
540 + counter.getName()
541 + (requestId == null ? "" : "&graph=" + urlEncode(requestId));
542 writeln(hrefStart + "'>");
543 writeln("<img src='?resource=action_refresh.png' alt='#Actualiser#'/> #Actualiser#</a>");
544
545 if (isPdfEnabled()) {
546 writeln(SEPARATOR);
547 write(hrefStart);
548 writeln("&format=pdf' title='#afficher_PDF#'>");
549 write("<img src='?resource=pdf.png' alt='#PDF#'/> #PDF#</a>");
550 }
551 writeln("</div>");
552
553 writeCounterTitle(counter);
554 final HtmlCounterReport htmlCounterReport = new HtmlCounterReport(counter, range,
555 getWriter());
556 htmlCounterReport.writeRequestsAggregatedOrFilteredByClassName(requestId);
557 }
558
559 private boolean isGcEnabled() {
560 return Action.GC_ENABLED || collectorServer != null;
561 }
562
563 private boolean isHeapHistoEnabled() {
564 return collectorServer != null || VirtualMachine.isEnabled();
565 }
566
567 private boolean isSamplingEnabled() {
568 return collectorServer != null || collector.getSamplingProfiler() != null;
569 }
570
571 private boolean isDatabaseEnabled() {
572 return !Parameters.isNoDatabase()
573 && javaInformationsList.get(0).getDataBaseVersion() != null
574 && !javaInformationsList.get(0).getDataBaseVersion().contains("Exception");
575 }
576
577 private boolean doesWebXmlExists() {
578 return javaInformationsList.get(0).doesWebXmlExists();
579 }
580
581 private boolean isSessionsEnabled() {
582 return javaInformationsList.get(0).getSessionCount() >= 0;
583 }
584
585 private boolean isSpringBeansEnabled() {
586 return javaInformationsList.get(0).isSpringBeansEnabled();
587 }
588
589 private boolean isCacheEnabled() {
590 for (final JavaInformations javaInformations : javaInformationsList) {
591 if (javaInformations.isCacheEnabled()) {
592 return true;
593 }
594 }
595 return false;
596 }
597
598 private boolean isJCacheEnabled() {
599 for (final JavaInformations javaInformations : javaInformationsList) {
600 if (javaInformations.isJCacheEnabled()) {
601 return true;
602 }
603 }
604 return false;
605 }
606
607 private boolean isJobEnabled() {
608 for (final JavaInformations javaInformations : javaInformationsList) {
609 if (javaInformations.isJobEnabled()) {
610 return true;
611 }
612 }
613 return false;
614 }
615
616 List<HsErrPid> getHsErrPidList() {
617 return HsErrPid.getHsErrPidList(javaInformationsList);
618 }
619
620 private void writeCaches() throws IOException {
621 int i = 0;
622 for (final JavaInformations javaInformations : javaInformationsList) {
623 if (!javaInformations.isCacheEnabled()) {
624 continue;
625 }
626 final List<CacheInformations> cacheInformationsList = javaInformations
627 .getCacheInformationsList();
628 writeln("<b>");
629 writeln(getFormattedString("caches_sur", cacheInformationsList.size(),
630 javaInformations.getHost()));
631 writeln("</b>");
632 writeln(SEPARATOR);
633 final String id = "caches_" + i;
634 writeShowHideLink(id, "#Details#");
635 writeln("<br/><br/><div id='" + id + "' class='displayNone'><div>");
636 new HtmlCacheInformationsReport(cacheInformationsList, getWriter()).toHtml();
637 writeln("</div></div><br/>");
638 i++;
639 }
640 }
641
642 private void writeJCaches() throws IOException {
643 int i = 0;
644 for (final JavaInformations javaInformations : javaInformationsList) {
645 if (!javaInformations.isJCacheEnabled()) {
646 continue;
647 }
648 final List<JCacheInformations> jcacheInformationsList = javaInformations
649 .getJCacheInformationsList();
650 writeln("<b>");
651 writeln(getFormattedString("caches_sur", jcacheInformationsList.size(),
652 javaInformations.getHost()));
653 writeln("</b>");
654 writeln(SEPARATOR);
655 final String id = "jcaches_" + i;
656 writeShowHideLink(id, "#Details#");
657 writeln("<br/><br/><div id='" + id + "' class='displayNone'><div>");
658 new HtmlJCacheInformationsReport(jcacheInformationsList, getWriter()).toHtml();
659 writeln("</div></div><br/>");
660 i++;
661 }
662 }
663
664 private void writeJobs(Counter rangeJobCounter) throws IOException {
665 int i = 0;
666 for (final JavaInformations javaInformations : javaInformationsList) {
667 if (!javaInformations.isJobEnabled()) {
668 continue;
669 }
670 final List<JobInformations> jobInformationsList = javaInformations
671 .getJobInformationsList();
672 writeln("<b>");
673 writeln(getFormattedString("jobs_sur", jobInformationsList.size(),
674 javaInformations.getHost(), javaInformations.getCurrentlyExecutingJobCount()));
675 writeln("</b>");
676 writeln(SEPARATOR);
677 final String id = "job_" + i;
678 writeShowHideLink(id, "#Details#");
679 writeln("<br/><br/><div id='" + id + "' class='displayNone'><div>");
680 new HtmlJobInformationsReport(jobInformationsList, rangeJobCounter, getWriter())
681 .toHtml();
682 writeln("</div></div><br/>");
683 i++;
684 }
685
686 writeCounter(rangeJobCounter);
687 }
688
689
690 private void writeSystemActionsLinks() throws IOException {
691
692 writeln("<div align='center' class='noPrint'>");
693 final String separator = " ";
694 if (isGcEnabled()) {
695 write("<a href='?action=gc" + getCsrfTokenUrlPart() + "' class='confirm' data-confirm='"
696 + htmlEncodeButNotSpaceAndNewLine(getString("confirm_ramasse_miette")) + "'>");
697 } else {
698 write("<a href='?action=gc" + getCsrfTokenUrlPart()
699 + "' class='alertAndStop' data-alert='"
700 + htmlEncodeButNotSpaceAndNewLine(getString("ramasse_miette_desactive"))
701 + "'>");
702 }
703 write("<img src='?resource=broom.png' width='20' height='20' alt='#ramasse_miette#' /> #ramasse_miette#</a>");
704 writeln(separator);
705 write("<a href='?action=heap_dump" + getCsrfTokenUrlPart()
706 + "' class='confirm' data-confirm='"
707 + htmlEncodeButNotSpaceAndNewLine(getString("confirm_heap_dump")) + "'>");
708 write("<img src='?resource=heapdump.png' width='20' height='20' alt=\"#heap_dump#\" /> #heap_dump#</a>");
709 writeln(separator);
710 if (isHeapHistoEnabled()) {
711 write("<a href='?part=heaphisto'>");
712 write("<img src='?resource=memory.png' width='20' height='20' alt=\"#heaphisto#\" /> #heaphisto#</a>");
713 writeln(separator);
714 }
715 if (isSessionsEnabled()) {
716 write("<a href='?action=invalidate_sessions" + getCsrfTokenUrlPart()
717 + "' class='confirm' data-confirm='"
718 + htmlEncodeButNotSpaceAndNewLine(getString("confirm_invalidate_sessions"))
719 + "'>");
720 write("<img src='?resource=user-trash.png' width='18' height='18' alt=\"#invalidate_sessions#\" /> #invalidate_sessions#</a>");
721 writeln(separator);
722 write("<a href='?part=sessions'>");
723 writeln("<img src='?resource=system-users.png' width='20' height='20' alt=\"#sessions#\" /> #sessions#</a>");
724 }
725 if (isSamplingEnabled()) {
726 writeln(separator);
727 write("<a href='?part=hotspots'>");
728 writeln("<img src='?resource=clock.png' width='20' height='20' alt=\"#hotspots#\" /> #hotspots#</a>");
729 }
730
731 writeln("<br />");
732 if (doesWebXmlExists()) {
733
734 writeln(separator);
735 write("<a href='?part=web.xml'>");
736 write("<img src='?resource=xml.png' width='20' height='20' alt=\"#web.xml#\" /> #web.xml#</a>");
737 }
738
739 writeln(separator);
740 write("<a href='?part=mbeans'>");
741 write("<img src='?resource=mbeans.png' width='20' height='20' alt=\"#MBeans#\" /> #MBeans#</a>");
742
743 writeln(separator);
744 write("<a href='?part=processes'>");
745 write("<img src='?resource=processes.png' width='20' height='20' alt=\"#processes#\" /> #processes#</a>");
746
747 final String serverInfo = javaInformationsList.get(0).getServerInfo();
748 if (serverInfo != null && !serverInfo.contains("Winstone")) {
749
750
751
752 writeln(separator);
753 write("<a href='?part=jndi'>");
754 write("<img src='?resource=jndi.png' width='20' height='20' alt=\"#Arbre_JNDI#\" /> #Arbre_JNDI#</a>");
755 }
756
757 if (isSpringBeansEnabled()) {
758 writeln(separator);
759 write("<a href='?part=springBeans'>");
760 write("<img src='?resource=beans.png' width='20' height='20' alt=\"#Spring_beans#\" /> #Spring_beans#</a>");
761 }
762
763 if (isDatabaseEnabled()) {
764 writeln(separator);
765 write("<a href='?part=connections'>");
766 write("<img src='?resource=db.png' width='20' height='20' alt=\"#Connexions_jdbc_ouvertes#\" /> #Connexions_jdbc_ouvertes#</a>");
767
768 writeln(separator);
769 write("<a href='?part=database'>");
770 writeln("<img src='?resource=db.png' width='20' height='20' alt=\"#database#\" /> #database#</a>");
771 }
772
773 final int hsErrPidCount = getHsErrPidList().size();
774 if (hsErrPidCount > 0) {
775 writeln(separator);
776 write("<a href='?part=crashes'>");
777 write("<img src='?resource=alert.png' width='20' height='20' alt=\"#Crashes# ("
778 + hsErrPidCount + ")\" /> #Crashes# (" + hsErrPidCount + ")</a>");
779 }
780
781 writeln("<br/></div>");
782 }
783
784 private void writeApplicationsLinks() throws IOException {
785 assert collectorServer != null;
786 writeln("<div align='center'>");
787 final Collection<String> applications = new ArrayList<>(
788 Parameters.getCollectorUrlsByApplications().keySet());
789 applications.addAll(Parameters.getApplicationsByAggregationApplication().keySet());
790 if (applications.size() > 1
791 || !collectorServer.getLastCollectExceptionsByApplication().isEmpty()) {
792 final boolean tabularList = applications.size() > 10;
793 if (tabularList) {
794 writeln("<table summary='applications'><tr><td>");
795 writeShowHideLink("chooseApplication", "#Choix_application#");
796 if (Parameters.getCollectorApplicationsFile().canWrite()) {
797 writeAddAndRemoveApplicationLinks(collector.getApplication(), applications,
798 getWriter());
799 }
800 writeln("<div id='chooseApplication' class='displayNone'><div> ");
801 writeApplicationsLinks(applications, tabularList);
802 writeln("</div></div></td></tr></table>");
803 } else {
804 writeln(" #Choix_application# : ");
805 writeApplicationsLinks(applications, tabularList);
806 if (Parameters.getCollectorApplicationsFile().canWrite()) {
807 writeAddAndRemoveApplicationLinks(collector.getApplication(), applications,
808 getWriter());
809 }
810 }
811 } else if (Parameters.getCollectorApplicationsFile().canWrite()) {
812 writeAddAndRemoveApplicationLinks(collector.getApplication(), applications,
813 getWriter());
814 }
815 writeln(END_DIV);
816 }
817
818 private void writeApplicationsLinks(Collection<String> applications, boolean tabularList)
819 throws IOException {
820 final Map<String, Throwable> lastCollectExceptionsByApplication = collectorServer
821 .getLastCollectExceptionsByApplication();
822 if (tabularList) {
823 writeln("<table><tr><td>");
824 }
825 final int nbColumns = 5;
826 int i = 0;
827 for (final String application : applications) {
828 final Throwable lastCollectException = lastCollectExceptionsByApplication
829 .get(application);
830 writeln("<a href='?application=" + application + "' class='tooltip'>");
831 if (lastCollectException == null) {
832 writeln("<img src='?resource=bullets/green.png' alt='#Application_disponible#'/>");
833 writeln("<em class='applicationStatus'>");
834 writeln("#Application_disponible#");
835 } else {
836 writeln("<img src='?resource=bullets/red.png' alt='#Application_indisponible#'/>");
837 writeln("<em class='applicationStatus'>");
838 writeln("#Application_indisponible#:<br/>");
839 writeDirectly(htmlEncode(lastCollectException.toString()));
840 writeDirectly("<br/>");
841 for (final StackTraceElement stackTraceElement : lastCollectException
842 .getStackTrace()) {
843 writeDirectly(htmlEncode(stackTraceElement.toString()));
844 writeDirectly("<br/>");
845 }
846 }
847 writeln("</em>");
848 writeln(application + "</a>");
849 i++;
850 if (tabularList) {
851 if (i % nbColumns == 0) {
852 writeln("</td></tr><tr><td>");
853 } else {
854 writeln("</td><td>");
855 }
856 } else {
857 writeln(" ");
858 }
859 }
860 if (tabularList) {
861 writeln("</td></tr></table>");
862 }
863 }
864
865 void writeRefreshAndPeriodLinks(String graphName, String part) throws IOException {
866 writeln("<div class='noPrint'>");
867 final String separator = " ";
868 final String graphParameter = "&graph=";
869 if (graphName == null) {
870 write("<a href='?' title='#Rafraichir#'>");
871 } else {
872 write("<a class='back' href=''><img src='?resource=action_back.png' alt='#Retour#'/> #Retour#</a>");
873 writeln(separator);
874 writeln("<a href='?'><img src='?resource=action_home.png' alt='#Page_principale#'/> #Page_principale#</a>");
875 writeln(separator);
876 write("<a href='?part=" + part + graphParameter + urlEncode(graphName)
877 + "' title='#Rafraichir#'>");
878 }
879 write("<img src='?resource=action_refresh.png' alt='#Actualiser#'/> #Actualiser#</a>");
880 if (isPdfEnabled() && !"usages".equals(part)) {
881 writeln(separator);
882 if (graphName == null) {
883 write("<a href='?format=pdf' title='#afficher_PDF#'>");
884 } else {
885 write("<a href='?part=" + part + graphParameter + urlEncode(graphName)
886 + "&format=pdf' title='#afficher_PDF#'>");
887 }
888 write("<img src='?resource=pdf.png' alt='#PDF#'/> #PDF#</a>");
889 }
890 writeln(separator);
891 write("<a href='?resource=#help_url#' target='_blank'");
892 write(" title=\"#Afficher_aide_en_ligne#\"><img src='?resource=action_help.png' alt='#Aide_en_ligne#'/> #Aide_en_ligne#</a>");
893 writeln(separator);
894 write("<a href='?part=jnlp'");
895 write(" title=\"#RDA#\"><img src='?resource=systemmonitor.png' width='16' height='16' alt='#RDA#'/> #Desktop#</a>");
896 writeln(separator);
897 writeln("#Choix_periode# : ");
898
899
900
901 for (final Period myPeriod : Period.values()) {
902 if (graphName == null) {
903 write("<a href='?period=" + myPeriod.getCode() + "' ");
904 } else {
905 write("<a href='?part=" + part + graphParameter + urlEncode(graphName)
906 + "&period=" + myPeriod.getCode() + "' ");
907 }
908 write("title='" + getFormattedString("Choisir_periode", myPeriod.getLinkLabel())
909 + "'>");
910 write("<img src='?resource=" + myPeriod.getIconName() + "' alt='"
911 + myPeriod.getLinkLabel() + "' /> ");
912 writeln(myPeriod.getLinkLabel() + "</a> ");
913 }
914 final HtmlForms htmlForms = new HtmlForms(getWriter());
915 final Map<String, Date> datesByWebappVersions = collector.getDatesByWebappVersions();
916 htmlForms.writeCustomPeriodLinks(datesByWebappVersions, range, graphName, part);
917
918 writeln(END_DIV);
919 }
920
921 private void writeDurationAndOverhead() throws IOException {
922 final long displayDuration = System.currentTimeMillis() - start;
923 writeln("<a name='bottom'></a>");
924 writeln("<br/><div class='durationAndOverHead'>");
925 writeln("#temps_derniere_collecte#: " + collector.getLastCollectDuration() + " #ms#<br/>");
926 writeln("#temps_affichage#: " + displayDuration + " #ms#<br/>");
927 writeln("#Estimation_overhead_memoire#: < "
928 + (collector.getEstimatedMemorySize() / 1024 / 1024 + 1) + " #Mo#");
929 writeln("<br/>#Usage_disque#: " + (collector.getDiskUsage() / 1024 / 1024 + 1) + " #Mo#");
930 if (Parameters.isSystemActionsEnabled()) {
931 writeln(" <a href='?action=purge_obsolete_files"
932 + getCsrfTokenUrlPart() + "' class='noPrint'>");
933 writeln("<img width='14' height='14' src='?resource=user-trash.png' alt='#Purger_les_fichiers_obsoletes#' title='#Purger_les_fichiers_obsoletes#'/></a>");
934 }
935 if (Parameters.JAVAMELODY_VERSION != null) {
936 writeln("<br/><br/>JavaMelody " + Parameters.JAVAMELODY_VERSION);
937 }
938 if (collectorServer == null) {
939 writeln("<br/>");
940 writeShowHideLink("debuggingLogs", "Debugging logs");
941 writeln("<br/><br/>");
942 writeln("<div id='debuggingLogs' class='displayNone'>");
943 final List<String> debuggingLogs = LOG.getDebuggingLogs();
944 if (debuggingLogs.size() >= LOG.MAX_DEBUGGING_LOGS_COUNT) {
945 writeln("<div class='severe'>Only the last " + LOG.MAX_DEBUGGING_LOGS_COUNT
946 + " messages are displayed</div>");
947 }
948 for (final String msg : debuggingLogs) {
949 writeDirectly(
950 htmlEncodeButNotSpace(msg).replace("\t", " "));
951 writeln("<br/>");
952 }
953 writeln(END_DIV);
954 }
955 writeln(END_DIV);
956 }
957 }
958