From d61e65f82c936e5dc986e4f850d4a5998b9caa2d Mon Sep 17 00:00:00 2001 From: evernat Date: Wed, 12 Apr 2017 16:48:57 +0200 Subject: [PATCH] display webapp version at the top and display drop-down to choose period based on webapp versions --- .../java/net/bull/javamelody/Collector.java | 90 +++++++++++++ .../net/bull/javamelody/FilterContext.java | 1 + .../net/bull/javamelody/HtmlCoreReport.java | 119 ++++++++++++++++-- .../net/bull/javamelody/JavaInformations.java | 7 ++ .../net/bull/javamelody/MavenArtifact.java | 32 +++++ .../java/net/bull/javamelody/Parameter.java | 5 + .../resource/translations.properties | 2 + .../resource/translations_de.properties | 2 + .../resource/translations_fr.properties | 2 + .../resource/translations_pt.properties | 2 + .../resource/translations_zh.properties | 3 + 11 files changed, 254 insertions(+), 11 deletions(-) diff --git a/javamelody-core/src/main/java/net/bull/javamelody/Collector.java b/javamelody-core/src/main/java/net/bull/javamelody/Collector.java index 5298e54ef..d04ecd194 100644 --- a/javamelody-core/src/main/java/net/bull/javamelody/Collector.java +++ b/javamelody-core/src/main/java/net/bull/javamelody/Collector.java @@ -18,7 +18,13 @@ package net.bull.javamelody; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -28,7 +34,9 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import net.bull.javamelody.Counter.CounterRequestContextComparator; @@ -39,7 +47,10 @@ * @author Emeric Vernat */ class Collector { // NOPMD + private static final String VERSIONS_FILENAME = "versions.properties"; + private static final String VERSIONS_DATE_PATTERN = "yyyy/MM/dd"; private static final long NOT_A_NUMBER = Long.MIN_VALUE; + // période entre 2 collectes en milli-secondes private final int periodMillis; private final String application; @@ -68,6 +79,10 @@ class Collector { // NOPMD private Date lastDateOfDeletedObsoleteFiles = new Date(); private boolean stopped; private final boolean noDatabase = Parameters.isNoDatabase(); + /** + * Les versions de l'applications avec pour chacune la date de déploiement. + */ + private final Map datesByWebappVersions; /** * Constructeur. @@ -122,6 +137,8 @@ class Collector { // NOPMD LOG.warn("exception while reading counters data from files in " + Parameters.getStorageDirectory(application), e); } + + datesByWebappVersions = readDatesByWebappVersions(); } /** @@ -147,6 +164,10 @@ List getHotspots() { return samplingProfiler.getHotspots(1000); } + Map getDatesByWebappVersions() { + return Collections.unmodifiableMap(datesByWebappVersions); + } + /** * @return La liste des counters de ce collector */ @@ -348,6 +369,14 @@ private long collect(List javaInformationsList) throws IOExcep } } + if (!javaInformationsList.isEmpty()) { + final String webappVersion = javaInformationsList.get(0).getWebappVersion(); + if (webappVersion != null && !datesByWebappVersions.containsKey(webappVersion)) { + addWebappVersion(webappVersion); + datesByWebappVersions.put(webappVersion, new Date()); + } + } + return memorySize; } } @@ -917,6 +946,67 @@ private Collection getDisplayedJRobins(Collection jrobins) { return Collections.unmodifiableCollection(displayedJRobins); } + @SuppressWarnings("unchecked") + private Map readDatesByWebappVersions() { + final Map result = new HashMap(); + final File storageDirectory = Parameters.getStorageDirectory(application); + final File versionsFile = new File(storageDirectory, VERSIONS_FILENAME); + if (versionsFile.exists()) { + final Properties versionsProperties = new Properties(); + try { + final InputStream input = new FileInputStream(versionsFile); + try { + versionsProperties.load(input); + } finally { + input.close(); + } + final List propertyNames = (List) Collections + .list(versionsProperties.propertyNames()); + final SimpleDateFormat dateFormat = new SimpleDateFormat(VERSIONS_DATE_PATTERN, + Locale.US); + for (final String version : propertyNames) { + try { + final Date date = dateFormat.parse(versionsProperties.getProperty(version)); + result.put(version, date); + } catch (final ParseException e) { + continue; + } + } + } catch (final IOException e) { + // lecture échouée, tant pis + LOG.warn("exception while reading versions in " + versionsFile, e); + } + } + return result; + } + + private void addWebappVersion(String webappVersion) throws IOException { + assert webappVersion != null && !webappVersion.isEmpty(); + final File storageDirectory = Parameters.getStorageDirectory(application); + final File versionsFile = new File(storageDirectory, VERSIONS_FILENAME); + final Properties versionsProperties = new Properties(); + if (versionsFile.exists()) { + final InputStream input = new FileInputStream(versionsFile); + try { + versionsProperties.load(input); + } finally { + input.close(); + } + } + assert versionsProperties.getProperty(webappVersion) == null; + + final SimpleDateFormat dateFormat = new SimpleDateFormat(VERSIONS_DATE_PATTERN, Locale.US); + versionsProperties.setProperty(webappVersion, dateFormat.format(new Date())); + + final OutputStream output = new FileOutputStream(versionsFile); + try { + versionsProperties.store(output, "Application deployments with versions and dates"); + } finally { + output.close(); + } + LOG.debug("New application version added: " + webappVersion); + } + /** * Purge les données pour un compteur à partir de son nom. * @param counterName Nom du compteur diff --git a/javamelody-core/src/main/java/net/bull/javamelody/FilterContext.java b/javamelody-core/src/main/java/net/bull/javamelody/FilterContext.java index c4d6825bf..863c79a76 100644 --- a/javamelody-core/src/main/java/net/bull/javamelody/FilterContext.java +++ b/javamelody-core/src/main/java/net/bull/javamelody/FilterContext.java @@ -335,6 +335,7 @@ private void logSystemInformationsAndParameters() { LOG.debug("JavaMelody classes loaded from: " + location); } LOG.debug("Application type: " + applicationType); + LOG.debug("Application version: " + MavenArtifact.getWebappVersion()); LOG.debug("Host: " + Parameters.getHostName() + '@' + Parameters.getHostAddress()); for (final Parameter parameter : Parameter.values()) { final String value = Parameters.getParameter(parameter); diff --git a/javamelody-core/src/main/java/net/bull/javamelody/HtmlCoreReport.java b/javamelody-core/src/main/java/net/bull/javamelody/HtmlCoreReport.java index 661cc4dc9..489a18f40 100644 --- a/javamelody-core/src/main/java/net/bull/javamelody/HtmlCoreReport.java +++ b/javamelody-core/src/main/java/net/bull/javamelody/HtmlCoreReport.java @@ -22,7 +22,11 @@ import java.net.URLEncoder; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -48,16 +52,49 @@ class HtmlCoreReport extends HtmlAbstractReport { private final long start = System.currentTimeMillis(); private final Map menuTextsByAnchorName = new LinkedHashMap(); + private static class MapValueComparator> + implements Comparator> { + MapValueComparator() { + super(); + } + + @Override + public int compare(Map.Entry o1, Map.Entry o2) { + return o1.getValue().compareTo(o2.getValue()); + } + } + private static class HtmlForms extends HtmlAbstractReport { + private static final Comparator> MAP_VALUE_COMPARATOR = Collections + .reverseOrder(new MapValueComparator()); + HtmlForms(Writer writer) { super(writer); } - void writeCustomPeriodLink(Range range, String graphName, String part) throws IOException { + void writeCustomPeriodLinks(Map datesByWebappVersions, Range currentRange, + String graphName, String part) throws IOException { writeln(""); + writeln("title='" + getFormattedString("Choisir_periode", getString("personnalisee")) + + "'>"); writeln("#personnalisee# #personnalisee#"); + + if (!datesByWebappVersions.isEmpty()) { + writeln(" "); + writeln("#par_deploiement# #par_deploiement#"); + } + + writeCustomPeriodDiv(currentRange, graphName, part); + if (!datesByWebappVersions.isEmpty()) { + writeDeploymentPeriodDiv(datesByWebappVersions, currentRange, graphName, part); + } + } + + private void writeCustomPeriodDiv(Range currentRange, String graphName, String part) + throws IOException { writeln("