diff --git a/.gitignore b/.gitignore
index ecf4036..4d292ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,12 @@
+.*
+!.github
+!.gitignore
+!.mvn
+*.bak
+*.log
+*.diff
+*.patch
+*.iml
target
-.project
-.classpath
-.settings
-release.properties
\ No newline at end of file
+release.properties
+
diff --git a/pom.xml b/pom.xml
index 8592b6b..2461ad5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,14 +47,14 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 1.6
+
+ 1.8
-
+
io.tesla.maven.plugins
tesla-license-plugin
-
+
org.sonatype.plugins
sisu-maven-plugin
diff --git a/src/main/java/io/tesla/lifecycle/profiler/AbstractProfile.java b/src/main/java/io/tesla/lifecycle/profiler/AbstractProfile.java
new file mode 100644
index 0000000..c3275cd
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/AbstractProfile.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2012 to original author or authors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.tesla.lifecycle.profiler;
+
+public abstract class AbstractProfile implements Profile {
+
+ protected long elapsedTime;
+
+ protected AbstractProfile() {
+ super();
+ }
+
+ /**
+ * @param elapsedTime the new value of {@link #getElapsedTime()}.
+ */
+ public void setElapsedTime(long elapsedTime) {
+ this.elapsedTime = elapsedTime;
+ }
+
+ /**
+ * @param millis the milliseconds to add to {@link #getElapsedTime() elapsed time}.
+ */
+ public void addElapsedTime(long millis) {
+
+ this.elapsedTime += millis;
+ }
+
+ @Override
+ public long getElapsedTime() {
+ return elapsedTime;
+ }
+
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/AbstractTimerProfile.java b/src/main/java/io/tesla/lifecycle/profiler/AbstractTimerProfile.java
new file mode 100644
index 0000000..e3ae431
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/AbstractTimerProfile.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2012 to original author or authors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.tesla.lifecycle.profiler;
+
+import io.tesla.lifecycle.profiler.internal.DefaultTimer;
+
+public abstract class AbstractTimerProfile extends AbstractProfile {
+
+ protected final Timer timer;
+
+ protected AbstractTimerProfile() {
+ this.timer = new DefaultTimer();
+ }
+
+ public void stop() {
+ timer.stop();
+ }
+
+ @Override
+ public long getElapsedTime() {
+ if(elapsedTime != 0) {
+ return elapsedTime;
+ }
+ return timer.getElapsedTime();
+ }
+
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/AggregationProfile.java b/src/main/java/io/tesla/lifecycle/profiler/AggregationProfile.java
new file mode 100644
index 0000000..48d1bd6
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/AggregationProfile.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2012 to original author or authors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.tesla.lifecycle.profiler;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AggregationProfile extends AbstractProfile {
+
+ private final String name;
+
+ private final Map childMap;
+
+ private final List children;
+
+ public AggregationProfile() {
+ this("all");
+ }
+
+ public AggregationProfile(String name) {
+ super();
+ this.name = name;
+ this.childMap = new HashMap<>();
+ this.children = new ArrayList<>();
+ }
+
+ @Override
+ public String getName() {
+
+ return this.name;
+ }
+
+ @Override
+ public long getElapsedTime() {
+
+ long millis = this.elapsedTime;
+ if (millis == 0) {
+ for (AggregationProfile child : this.children) {
+ millis += child.getElapsedTime();
+ }
+ }
+ return millis;
+ }
+
+ public AggregationProfile getChild(String name) {
+
+ return this.childMap.get(name);
+ }
+
+ public AggregationProfile getOrCreateChild(String name) {
+
+ return this.childMap.computeIfAbsent(name, this::newAggregationProfile);
+ }
+
+ private AggregationProfile newAggregationProfile(String name) {
+
+ AggregationProfile profile = new AggregationProfile(name);
+ this.children.add(profile);
+ return profile;
+ }
+
+ @Override
+ public Collection extends Profile> getChildren() {
+
+ return this.children;
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java b/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java
index 7c23095..7eac884 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java
@@ -26,12 +26,11 @@
@Singleton
public class LifecycleProfiler extends AbstractEventSpy {
- private final static String TESLA_PROFILE = "maven.profile";
-
- //
- // Components
- //
- private SessionProfileRenderer renderer;
+ private final static String MAVEN_PROFILE = "maven.profile";
+
+ private final SessionProfileRenderer renderer;
+
+ private final boolean disabled;
//
// Profile data
@@ -43,7 +42,9 @@ public class LifecycleProfiler extends AbstractEventSpy {
@Inject
public LifecycleProfiler(SessionProfileRenderer sessionProfileRenderer) {
+ super();
this.renderer = sessionProfileRenderer;
+ this.disabled = (System.getProperty(MAVEN_PROFILE) == null);
}
@Override
@@ -52,30 +53,38 @@ public void init(Context context) throws Exception {
@Override
public void onEvent(Object event) throws Exception {
+ if (this.disabled) {
+ return;
+ }
if (event instanceof ExecutionEvent) {
ExecutionEvent executionEvent = (ExecutionEvent) event;
if (executionEvent.getType() == ExecutionEvent.Type.SessionStarted) {
//
//
//
- sessionProfile = new SessionProfile();
+ StringBuilder command = new StringBuilder("mvn");
+ for (String goal : executionEvent.getSession().getGoals()) {
+ command.append(' ');
+ command.append(goal);
+ }
+ sessionProfile = new SessionProfile(command.toString());
} else if (executionEvent.getType() == ExecutionEvent.Type.SessionEnded) {
//
//
//
sessionProfile.stop();
- if (System.getProperty(TESLA_PROFILE) != null) {
- renderer.render(sessionProfile);
- }
+ renderer.render(sessionProfile);
} else if (executionEvent.getType() == ExecutionEvent.Type.ProjectStarted) {
//
// We need to collect the mojoExecutions within each project
//
projectProfile = new ProjectProfile(executionEvent.getProject());
} else if (executionEvent.getType() == ExecutionEvent.Type.ProjectSucceeded || executionEvent.getType() == ExecutionEvent.Type.ProjectFailed) {
- //
- //
- //
+ if (phaseProfile != null) {
+ phaseProfile.stop();
+ projectProfile.addPhaseProfile(phaseProfile);
+ phaseProfile = null;
+ }
projectProfile.stop();
sessionProfile.addProjectProfile(projectProfile);
} else if (executionEvent.getType() == ExecutionEvent.Type.MojoStarted) {
diff --git a/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java b/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java
index 0324d8a..dbebe7a 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java
@@ -7,21 +7,34 @@
*/
package io.tesla.lifecycle.profiler;
-import io.tesla.lifecycle.profiler.internal.DefaultTimer;
+import java.util.Collections;
+import java.util.List;
import org.apache.maven.plugin.MojoExecution;
-public class MojoProfile extends Profile {
+public class MojoProfile extends AbstractTimerProfile {
private MojoExecution mojoExecution;
-
+
protected MojoProfile(MojoExecution mojoExecution) {
- super(new DefaultTimer());
+ super();
this.mojoExecution = mojoExecution;
}
-
+
public String getId() {
- return mojoExecution.getGroupId() + ":" + mojoExecution.getArtifactId() + ":" + mojoExecution.getVersion() + " (" + mojoExecution.getExecutionId() + ") ";
+ return mojoExecution.getGroupId() + ":" + mojoExecution.getArtifactId() + ":" + mojoExecution.getVersion() + " (" + mojoExecution.getExecutionId() + ")";
+ }
+
+ @Override
+ public String getName() {
+
+ return getId();
+ }
+
+ @Override
+ public List extends Profile> getChildren() {
+
+ return Collections.emptyList();
}
}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java b/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java
index d887b9e..0716df9 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java
@@ -7,22 +7,20 @@
*/
package io.tesla.lifecycle.profiler;
-import io.tesla.lifecycle.profiler.internal.DefaultTimer;
-
import java.util.ArrayList;
import java.util.List;
-public class PhaseProfile extends Profile {
+public class PhaseProfile extends AbstractTimerProfile {
private String phase;
private List mojoProfiles;
-
+
public PhaseProfile(String phase) {
- super(new DefaultTimer());
+ super();
this.phase = phase;
this.mojoProfiles = new ArrayList();
}
-
+
public void addMojoProfile(MojoProfile mojoProfile) {
mojoProfiles.add(mojoProfile);
}
@@ -34,4 +32,16 @@ public String getPhase() {
public List getMojoProfiles() {
return mojoProfiles;
}
+
+ @Override
+ public String getName() {
+
+ return phase;
+ }
+
+ @Override
+ public List extends Profile> getChildren() {
+
+ return getMojoProfiles();
+ }
}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/Profile.java b/src/main/java/io/tesla/lifecycle/profiler/Profile.java
index 58b3bd0..00b490e 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/Profile.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/Profile.java
@@ -7,29 +7,25 @@
*/
package io.tesla.lifecycle.profiler;
-import io.tesla.lifecycle.profiler.internal.DefaultTimer;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Interface for a profile of the profiling. The root profile is {@link SessionProfile} representing the recording of the
+ * entire session. Each {@link Profile} can have {@link #getChildren() children} representing a partition of the whole
+ * into smaller steps to give more details and granularity to trace down leaks and find spots worth to optimize.
+ */
+public interface Profile extends Timing {
+
+ /**
+ * @return the name of this profile (name of e.g. maven project, phase, plugin).
+ */
+ String getName();
+
+ /**
+ * @return the {@link List} of child {@link Profile}s contained in this {@link Profile}. Will be an empty list if this
+ * profile has not children.
+ */
+ Collection extends Profile> getChildren();
-public class Profile {
-
- protected long elapsedTime;
- protected Timer timer;
-
- protected Profile(DefaultTimer timer) {
- this.timer = timer;
- }
-
- public void stop() {
- timer.stop();
- }
-
- void setElapsedTime(long elapsedTime) {
- this.elapsedTime = elapsedTime;
- }
-
- public long getElapsedTime() {
- if(elapsedTime != 0) {
- return elapsedTime;
- }
- return timer.getTime();
- }
}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java b/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java
index 2afcf32..2b696f5 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java
@@ -7,24 +7,22 @@
*/
package io.tesla.lifecycle.profiler;
-import io.tesla.lifecycle.profiler.internal.DefaultTimer;
-
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.project.MavenProject;
-public class ProjectProfile extends Profile {
+public class ProjectProfile extends AbstractTimerProfile {
private MavenProject project;
private List phaseProfiles;
-
+
public ProjectProfile(MavenProject project) {
- super(new DefaultTimer());
+ super();
this.project = project;
this.phaseProfiles = new ArrayList();
}
-
+
public void addPhaseProfile(PhaseProfile phaseProfile) {
phaseProfiles.add(phaseProfile);
}
@@ -36,4 +34,16 @@ public String getProjectName() {
public List getPhaseProfile() {
return phaseProfiles;
}
+
+ @Override
+ public String getName() {
+
+ return getProjectName();
+ }
+
+ @Override
+ public List extends Profile> getChildren() {
+
+ return getPhaseProfile();
+ }
}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java b/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java
index cce073f..9460d0f 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java
@@ -7,20 +7,21 @@
*/
package io.tesla.lifecycle.profiler;
-import io.tesla.lifecycle.profiler.internal.DefaultTimer;
-
import java.util.ArrayList;
import java.util.List;
-public class SessionProfile extends Profile {
+public class SessionProfile extends AbstractTimerProfile {
+
+ private final String name;
private List projectProfiles;
-
- public SessionProfile() {
- super(new DefaultTimer());
- this.projectProfiles = new ArrayList();
+
+ public SessionProfile(String name) {
+ super();
+ this.name = name;
+ this.projectProfiles = new ArrayList<>();
}
-
+
public void addProjectProfile(ProjectProfile projectProfile) {
projectProfiles.add(projectProfile);
}
@@ -28,4 +29,16 @@ public void addProjectProfile(ProjectProfile projectProfile) {
public List getProjectProfiles() {
return projectProfiles;
}
+
+ @Override
+ public String getName() {
+
+ return this.name;
+ }
+
+ @Override
+ public List extends Profile> getChildren() {
+
+ return getProjectProfiles();
+ }
}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/Timer.java b/src/main/java/io/tesla/lifecycle/profiler/Timer.java
index 8783f45..a68da07 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/Timer.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/Timer.java
@@ -7,9 +7,20 @@
*/
package io.tesla.lifecycle.profiler;
-public interface Timer {
+/**
+ * Interface for a simple timer that is like a stop-watch. Once created, it starts ticking until you {@link #stop() stop} it.
+ * Then you can use {@link #getElapsedTime()} to retrieve the elapsed duration.
+ */
+public interface Timer extends Timing {
+ /**
+ * Stops this timer. Should only be called once.
+ */
void stop();
- long getTime();
- String format(long elapsedTime);
+
+// default Duration getDuration() {
+//
+// return Duration.of(getTime(), ChronoUnit.MILLIS);
+// }
+
}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/Timing.java b/src/main/java/io/tesla/lifecycle/profiler/Timing.java
new file mode 100644
index 0000000..ea9e2a1
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/Timing.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2012 to original author or authors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.tesla.lifecycle.profiler;
+
+/**
+ * Interface for an object that records the timing and therefore has an {@link #getElapsedTime() elapsed time}.
+ */
+public interface Timing {
+
+ /**
+ * @return the duration in milliseconds of this timing. Typically the duration from the instantiation a {@link Timer}
+ * until it has been {@link Timer#stop() stop}ed.
+ */
+ long getElapsedTime();
+
+// default Duration getDuration() {
+//
+// return Duration.of(getTime(), ChronoUnit.MILLIS);
+// }
+
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/internal/AbstractSessionProfileRenderer.java b/src/main/java/io/tesla/lifecycle/profiler/internal/AbstractSessionProfileRenderer.java
new file mode 100644
index 0000000..d40efdc
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/internal/AbstractSessionProfileRenderer.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2012 to original author or authors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.tesla.lifecycle.profiler.internal;
+
+import java.util.Locale;
+
+import io.tesla.lifecycle.profiler.SessionProfileRenderer;
+
+/**
+ * Abstract base implementation of {@link SessionProfileRenderer}.
+ */
+public abstract class AbstractSessionProfileRenderer implements SessionProfileRenderer {
+
+ /** Determines if the profiling report shall be logged at the end of the build */
+ protected final boolean logProfileData;
+
+ /**
+ * The constructor.
+ */
+ public AbstractSessionProfileRenderer() {
+
+ super();
+ this.logProfileData = getBooleanProperty("maven.profile.log.output", true);
+ }
+
+ /**
+ * @param name the name of the {@link System#getProperty(String) system property}.
+ * @param defaultValue the default value if the {@link System#getProperty(String) system property} is undefined or invalid.
+ * @return the configured boolean value.
+ */
+ protected static boolean getBooleanProperty(String name, boolean defaultValue) {
+
+ boolean result = defaultValue;
+ String valueAsString = System.getProperty(name);
+ if (valueAsString != null) {
+ valueAsString = valueAsString.toLowerCase(Locale.ROOT);
+ if ("true".equals(valueAsString) || "yes".equals(valueAsString)) {
+ result = true;
+ } else if ("false".equals(valueAsString) || "no".equals(valueAsString)) {
+ result = true;
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/internal/AdvancedSessionProfileRenderer.java b/src/main/java/io/tesla/lifecycle/profiler/internal/AdvancedSessionProfileRenderer.java
new file mode 100644
index 0000000..a2f8134
--- /dev/null
+++ b/src/main/java/io/tesla/lifecycle/profiler/internal/AdvancedSessionProfileRenderer.java
@@ -0,0 +1,184 @@
+/**
+ * Copyright (c) 2012 to original author or authors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package io.tesla.lifecycle.profiler.internal;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatterBuilder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import io.tesla.lifecycle.profiler.AggregationProfile;
+import io.tesla.lifecycle.profiler.Profile;
+import io.tesla.lifecycle.profiler.SessionProfile;
+
+/**
+ * Advanced implementation of {@link AbstractSessionProfileRenderer} that can write both CSV and/or log human readable profiling summary.
+ */
+@Named
+@Singleton
+public class AdvancedSessionProfileRenderer extends AbstractSessionProfileRenderer {
+
+ private final static String WRITE_CSV = "maven.profile.write.csv";
+
+ private static final char CSV_SEPARATOR = ';';
+
+ private final List aggregations;
+
+ private Writer csvWriter;
+
+ public AdvancedSessionProfileRenderer() {
+
+ super();
+ this.aggregations = new ArrayList<>();
+ this.aggregations.add(new AggregationProfile("Aggregation by project"));
+ this.aggregations.add(new AggregationProfile("Aggregation by phase"));
+ this.aggregations.add(new AggregationProfile("Aggregation by mojo"));
+ }
+
+ public void render(SessionProfile sessionProfile) {
+
+ boolean writeCsv = getBooleanProperty(WRITE_CSV, true);
+ OutputStream out = null;
+ if (writeCsv) {
+ String timestamp = new DateTimeFormatterBuilder().appendPattern("YYYY-MM-dd_HH-mm-ss").toFormatter()
+ .format(LocalDateTime.now());
+ String filename = ".maven.profiling." + timestamp + ".csv";
+ try {
+ out = new FileOutputStream(filename);
+ this.csvWriter = new OutputStreamWriter(out, StandardCharsets.UTF_8);
+ try {
+ this.csvWriter.write("Depth");
+ this.csvWriter.write(CSV_SEPARATOR);
+ this.csvWriter.write("Name");
+ this.csvWriter.write(CSV_SEPARATOR);
+ this.csvWriter.write("Duration (ms)");
+ this.csvWriter.write(CSV_SEPARATOR);
+ this.csvWriter.write("Fraction");
+ this.csvWriter.write("\n");
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to write CSV data!", e);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to open file '" + filename + "' for writing!", e);
+ }
+ }
+ try {
+ renderProfile(sessionProfile, true);
+ for (AggregationProfile aggregation : this.aggregations) {
+ aggregation.setElapsedTime(sessionProfile.getElapsedTime());
+ renderProfile(aggregation, false);
+ }
+ } finally {
+ if (writeCsv) {
+ close(this.csvWriter);
+ this.csvWriter = null;
+ close(out);
+ }
+ }
+ }
+
+ private void renderProfile(Profile sessionProfile, boolean aggregate) {
+
+ renderProfile(0, sessionProfile, 0, "");
+ renderProfileRecursive(sessionProfile, 0, "", aggregate);
+ }
+
+ private void close(AutoCloseable out) {
+
+ if (out != null) {
+ try {
+ out.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ private void renderProfileRecursive(Profile profile, int depth, String prefix, boolean aggregate) {
+
+ Collection extends Profile> children = profile.getChildren();
+ AggregationProfile aggregation = null;
+ if (aggregate && (depth < aggregations.size())) {
+ aggregation = this.aggregations.get(depth);
+ }
+ int childDepth = depth + 1;
+ long duration = profile.getElapsedTime();
+ String childPrefix = prefix + " ";
+ for (Profile child : children) {
+ renderProfile(childDepth, child, duration, childPrefix);
+ if (aggregation != null) {
+ aggregation.getOrCreateChild(child.getName()).addElapsedTime(child.getElapsedTime());
+ }
+ renderProfileRecursive(child, childDepth, childPrefix, aggregate);
+ }
+ }
+
+ private void renderProfile(int depth, Profile profile, long total, String prefix) {
+
+ String fraction = "1";
+ String percentage = "100%";
+ if (total > 0) {
+ long duration = profile.getElapsedTime();
+ if (duration < total) {
+ long fract = (duration * 1000) / total;
+ percentage = (fract / 10) + "%";
+ fraction = Long.toString(fract);
+ int zeros = 3 - fraction.length();
+ while (zeros > 0) {
+ fraction = "0" + fraction;
+ zeros--;
+ }
+ fraction = "0." + fraction;
+ } else if (duration > total) {
+ // invalid, should never happen
+ fraction = "";
+ percentage = "";
+ }
+ }
+ renderProfileAsCsv(depth, profile, fraction);
+ if (this.logProfileData) {
+ String message = prefix + profile.getName() + " " + DefaultTimer.formatMilliseconds(profile.getElapsedTime())
+ + "(" + percentage + ")";
+ render(message);
+ }
+ }
+
+ private void renderProfileAsCsv(int depth, Profile profile, String fraction) {
+
+ if (this.csvWriter == null) {
+ return;
+ }
+ try {
+ this.csvWriter.write(Integer.toString(depth));
+ this.csvWriter.write(CSV_SEPARATOR);
+ this.csvWriter.write(profile.getName());
+ this.csvWriter.write(CSV_SEPARATOR);
+ this.csvWriter.write(Long.toString(profile.getElapsedTime()));
+ this.csvWriter.write(CSV_SEPARATOR);
+ this.csvWriter.write(fraction);
+ this.csvWriter.write("\n");
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to write CSV data!", e);
+ }
+ }
+
+ private void render(String s) {
+
+ System.out.println(s);
+ }
+}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultSessionProfileRenderer.java b/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultSessionProfileRenderer.java
index c499fe0..770bfa3 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultSessionProfileRenderer.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultSessionProfileRenderer.java
@@ -11,40 +11,35 @@
import io.tesla.lifecycle.profiler.PhaseProfile;
import io.tesla.lifecycle.profiler.ProjectProfile;
import io.tesla.lifecycle.profiler.SessionProfile;
-import io.tesla.lifecycle.profiler.SessionProfileRenderer;
-import io.tesla.lifecycle.profiler.Timer;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
+// old implementation that has been replaced by AdvancedSessionProfileRenderer. Could actually be removed.
+//@Named
+//@Singleton
+public class DefaultSessionProfileRenderer extends AbstractSessionProfileRenderer {
-@Named
-@Singleton
-public class DefaultSessionProfileRenderer implements SessionProfileRenderer {
-
- private Timer timer;
-
- @Inject
- public DefaultSessionProfileRenderer(Timer timer) {
- this.timer = timer;
+ public DefaultSessionProfileRenderer() {
+ super();
}
-
+
public void render(SessionProfile sessionProfile) {
-
+
+ if (!this.logProfileData) {
+ return;
+ }
for(ProjectProfile pp : sessionProfile.getProjectProfiles()) {
render("");
render(pp.getProjectName());
render("");
for(PhaseProfile phaseProfile : pp.getPhaseProfile()) {
- render(" " + phaseProfile.getPhase() + " " + timer.format(phaseProfile.getElapsedTime()));
+ render(" " + phaseProfile.getPhase() + " " + DefaultTimer.formatMilliseconds(phaseProfile.getElapsedTime()));
for(MojoProfile mp : phaseProfile.getMojoProfiles()) {
- render(" " + mp.getId() + timer.format(mp.getElapsedTime()));
+ render(" " + mp.getId() + DefaultTimer.formatMilliseconds(mp.getElapsedTime()));
}
render("");
}
}
}
-
+
private void render(String s) {
System.out.println(s);
}
diff --git a/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultTimer.java b/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultTimer.java
index 18dfe22..cca5dc7 100644
--- a/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultTimer.java
+++ b/src/main/java/io/tesla/lifecycle/profiler/internal/DefaultTimer.java
@@ -7,17 +7,17 @@
*/
package io.tesla.lifecycle.profiler.internal;
-import io.tesla.lifecycle.profiler.Timer;
-
import javax.inject.Named;
import javax.inject.Singleton;
+import io.tesla.lifecycle.profiler.Timer;
+
@Named
@Singleton
public class DefaultTimer implements Timer {
-
- public static final int MS_PER_SEC = 1000;
- public static final int SEC_PER_MIN = 60;
+ static final int MS_PER_SEC = 1000;
+ static final int SEC_PER_MIN = 60;
+
private long start;
private long time;
@@ -25,11 +25,13 @@ public DefaultTimer() {
start = System.currentTimeMillis();
}
+ @Override
public void stop() {
time = elapsedTime();
}
- public long getTime() {
+ @Override
+ public long getElapsedTime() {
return time;
}
@@ -37,11 +39,12 @@ private long elapsedTime() {
return System.currentTimeMillis() - start;
}
- public String format(long ms) {
- long secs = ms / MS_PER_SEC;
+ protected static String formatMilliseconds(long durationInMillis) {
+
+ long secs = durationInMillis / MS_PER_SEC;
long mins = secs / SEC_PER_MIN;
secs = secs % SEC_PER_MIN;
- long fractionOfASecond = ms - (secs * 1000);
+ long fractionOfASecond = durationInMillis - (secs * 1000);
StringBuilder msg = new StringBuilder();
if (mins > 0) {
@@ -62,4 +65,5 @@ public String format(long ms) {
return msg.toString();
}
+
}
diff --git a/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java b/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java
index 558587c..6335483 100644
--- a/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java
+++ b/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java
@@ -21,7 +21,7 @@ public class LifecycleProfilerTest extends InjectedTestCase {
public void testSessionProfile() {
- SessionProfile s = new SessionProfile();
+ SessionProfile s = new SessionProfile("mvn");
ProjectProfile p0 = new ProjectProfile(project("g0", "a0", "v0"));
PhaseProfile ph0 = new PhaseProfile("phase0");
diff --git a/src/test/java/io/tesla/lifecycle/profiler/TimerTest.java b/src/test/java/io/tesla/lifecycle/profiler/internal/TimerTest.java
similarity index 57%
rename from src/test/java/io/tesla/lifecycle/profiler/TimerTest.java
rename to src/test/java/io/tesla/lifecycle/profiler/internal/TimerTest.java
index e5fa9f5..2889762 100755
--- a/src/test/java/io/tesla/lifecycle/profiler/TimerTest.java
+++ b/src/test/java/io/tesla/lifecycle/profiler/internal/TimerTest.java
@@ -5,15 +5,13 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
-package io.tesla.lifecycle.profiler;
+package io.tesla.lifecycle.profiler.internal;
-import io.tesla.lifecycle.profiler.internal.DefaultTimer;
+import static io.tesla.lifecycle.profiler.internal.DefaultTimer.MS_PER_SEC;
import org.junit.Assert;
import org.junit.Test;
-import static io.tesla.lifecycle.profiler.internal.DefaultTimer.MS_PER_SEC;
-
/**
* @author Kristian Rosenvold
*/
@@ -22,15 +20,13 @@ public class TimerTest {
@Test
public void testTimeFormats() throws Exception {
- Timer timer = new DefaultTimer();
- Assert.assertEquals("1ms", timer.format(1));
- Assert.assertEquals("1s 1ms", timer.format(1001));
- Assert.assertEquals("1m 1s", timer.format(61 * MS_PER_SEC));
+ Assert.assertEquals("1ms", DefaultTimer.formatMilliseconds(1));
+ Assert.assertEquals("1s 1ms", DefaultTimer.formatMilliseconds(1001));
+ Assert.assertEquals("1m 1s", DefaultTimer.formatMilliseconds(61 * MS_PER_SEC));
}
@Test
public void assertDetailLoss() {
- Timer timer = new DefaultTimer();
- Assert.assertEquals("1m 1s", timer.format(61 * MS_PER_SEC + 1));
+ Assert.assertEquals("1m 1s", DefaultTimer.formatMilliseconds(61 * MS_PER_SEC + 1));
}
}