diff --git a/pom.xml b/pom.xml index e9e2d2e..f1398e8 100644 --- a/pom.xml +++ b/pom.xml @@ -20,5 +20,10 @@ maven-core 3.0.3 + + junit + junit + 4.8.2 + diff --git a/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java b/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java new file mode 100644 index 0000000..e13202c --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/LifecycleProfiler.java @@ -0,0 +1,79 @@ +package io.tesla.lifecycle.profiler; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.maven.eventspy.AbstractEventSpy; +import org.apache.maven.execution.ExecutionEvent; + +/** + * @author Jason van Zyl + */ +@Named +@Singleton +public class LifecycleProfiler extends AbstractEventSpy { + + private SessionProfile sessionProfile; + private ProjectProfile projectProfile; + private PhaseProfile phaseProfile; + private MojoProfile mojoProfile; + + @Override + public void init(Context context) throws Exception { + } + + @Override + public void onEvent(Object event) throws Exception { + if (event instanceof ExecutionEvent) { + + + ExecutionEvent executionEvent = (ExecutionEvent) event; + if (executionEvent.getType() == ExecutionEvent.Type.SessionStarted) { + // + // + // + sessionProfile = new SessionProfile(); + } else if (executionEvent.getType() == ExecutionEvent.Type.SessionEnded) { + // + // + // + sessionProfile.stop(); + + SessionProfileRenderer r = new SessionProfileRenderer(); + r.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) { + // + // + // + projectProfile.stop(); + sessionProfile.addProjectProfile(projectProfile); + } else if (executionEvent.getType() == ExecutionEvent.Type.MojoStarted) { + String phase = executionEvent.getMojoExecution().getLifecyclePhase(); + // + // Create a new phase profile if one doesn't exist or the phase has changed. + // + if(phaseProfile == null) { + phaseProfile = new PhaseProfile(phase); + } else if (!phaseProfile.getPhase().equals(phase)) { + phaseProfile.stop(); + System.out.println(">> phase time : " + phaseProfile.getElapsedTime()); + projectProfile.addPhaseProfile(phaseProfile); + phaseProfile = new PhaseProfile(phase); + } + mojoProfile = new MojoProfile(executionEvent.getMojoExecution()); + } else if (executionEvent.getType() == ExecutionEvent.Type.MojoSucceeded || executionEvent.getType() == ExecutionEvent.Type.MojoFailed) { + // + // + // + mojoProfile.stop(); + phaseProfile.addMojoProfile(mojoProfile); + } + } + } +} diff --git a/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java b/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java new file mode 100644 index 0000000..7d51916 --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/MojoProfile.java @@ -0,0 +1,18 @@ +package io.tesla.lifecycle.profiler; + +import org.apache.maven.plugin.MojoExecution; + +public class MojoProfile extends Profile { + + private MojoExecution mojoExecution; + + protected MojoProfile(MojoExecution mojoExecution) { + super(new Timer()); + this.mojoExecution = mojoExecution; + } + + public String getId() { + return mojoExecution.getGroupId() + ":" + mojoExecution.getArtifactId() + ":" + mojoExecution.getVersion() + " (" + mojoExecution.getExecutionId() + ") "; + } + +} diff --git a/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java b/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java new file mode 100644 index 0000000..90dd838 --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/PhaseProfile.java @@ -0,0 +1,28 @@ +package io.tesla.lifecycle.profiler; + +import java.util.ArrayList; +import java.util.List; + +public class PhaseProfile extends Profile { + + private String phase; + private List mojoProfiles; + + public PhaseProfile(String phase) { + super(new Timer()); + this.phase = phase; + this.mojoProfiles = new ArrayList(); + } + + public void addMojoProfile(MojoProfile mojoProfile) { + mojoProfiles.add(mojoProfile); + } + + public String getPhase() { + return phase; + } + + public List getMojoProfiles() { + return mojoProfiles; + } +} diff --git a/src/main/java/io/tesla/lifecycle/profiler/Profile.java b/src/main/java/io/tesla/lifecycle/profiler/Profile.java new file mode 100644 index 0000000..4988ac7 --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/Profile.java @@ -0,0 +1,26 @@ +package io.tesla.lifecycle.profiler; + +public class Profile { + + protected long elapsedTime; + protected Timer timer; + + protected Profile(Timer 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 new file mode 100644 index 0000000..c9262f0 --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/ProjectProfile.java @@ -0,0 +1,30 @@ +package io.tesla.lifecycle.profiler; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.project.MavenProject; + +public class ProjectProfile extends Profile { + + private MavenProject project; + private List phaseProfiles; + + public ProjectProfile(MavenProject project) { + super(new Timer()); + this.project = project; + this.phaseProfiles = new ArrayList(); + } + + public void addPhaseProfile(PhaseProfile phaseProfile) { + phaseProfiles.add(phaseProfile); + } + + public String getProjectName() { + return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion(); + } + + public List getPhaseProfile() { + return phaseProfiles; + } +} diff --git a/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java b/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java new file mode 100644 index 0000000..0e6c2de --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/SessionProfile.java @@ -0,0 +1,22 @@ +package io.tesla.lifecycle.profiler; + +import java.util.ArrayList; +import java.util.List; + +public class SessionProfile extends Profile { + + private List projectProfiles; + + public SessionProfile() { + super(new Timer()); + this.projectProfiles = new ArrayList(); + } + + public void addProjectProfile(ProjectProfile projectProfile) { + projectProfiles.add(projectProfile); + } + + public List getProjectProfiles() { + return projectProfiles; + } +} diff --git a/src/main/java/io/tesla/lifecycle/profiler/SessionProfileRenderer.java b/src/main/java/io/tesla/lifecycle/profiler/SessionProfileRenderer.java new file mode 100644 index 0000000..9816006 --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/SessionProfileRenderer.java @@ -0,0 +1,22 @@ +package io.tesla.lifecycle.profiler; + +public class SessionProfileRenderer { + + public void render(SessionProfile sessionProfile) { + + for(ProjectProfile pp : sessionProfile.getProjectProfiles()) { + render(pp.getProjectName()); + for(PhaseProfile phaseProfile : pp.getPhaseProfile()) { + render(" " + phaseProfile.getPhase() + " " + Timer.formatTime(phaseProfile.getElapsedTime())); + for(MojoProfile mp : phaseProfile.getMojoProfiles()) { + render(" " + mp.getId() + Timer.formatTime(mp.getElapsedTime())); + } + } + render(""); + } + } + + private void render(String s) { + System.out.println(s); + } +} diff --git a/src/main/java/io/tesla/lifecycle/profiler/Timer.java b/src/main/java/io/tesla/lifecycle/profiler/Timer.java new file mode 100644 index 0000000..c008881 --- /dev/null +++ b/src/main/java/io/tesla/lifecycle/profiler/Timer.java @@ -0,0 +1,47 @@ +package io.tesla.lifecycle.profiler; + +public class Timer { + public static final int MS_PER_SEC = 1000; + public static final int SEC_PER_MIN = 60; + private long start; + private long time; + + public Timer() { + start = System.currentTimeMillis(); + } + + public void stop() { + time = elapsedTime(); + } + + public long getTime() { + return time; + } + + private long elapsedTime() { + return System.currentTimeMillis() - start; + } + + public static String formatTime(long ms) { + long secs = ms / MS_PER_SEC; + long mins = secs / SEC_PER_MIN; + secs = secs % SEC_PER_MIN; + long fractionOfASecond = ms - (secs * 1000); +// System.out.println("mins " + mins); +// System.out.println("secs " + secs); +// System.out.println(fractionOfASecond); +// System.out.println(">> " + fractionOfASecond); + + String msg = mins + "m " + secs + "." + fractionOfASecond; + + if (msg.length() == 3) { + msg += "00s"; + } else if (msg.length() == 4) { + msg += "0s"; + } else { + msg += "s"; + } + + return msg; + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 0000000..c8d2c8b --- /dev/null +++ b/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,12 @@ + + + + + org.apache.maven.eventspy.EventSpy + default + io.tesla.lifecycle.profiler.LifecycleProfiler + + false + + + diff --git a/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java b/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java new file mode 100644 index 0000000..585caa9 --- /dev/null +++ b/src/test/java/io/tesla/lifecycle/profiler/LifecycleProfilerTest.java @@ -0,0 +1,63 @@ +package io.tesla.lifecycle.profiler; + +import junit.framework.TestCase; + +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.project.MavenProject; + + +public class LifecycleProfilerTest extends TestCase { + + public void testSessionProfile() { + + SessionProfile s = new SessionProfile(); + + ProjectProfile p0 = new ProjectProfile(project("g0", "a0", "v0")); + PhaseProfile ph0 = new PhaseProfile("phase0"); + MojoProfile m0 = new MojoProfile(mojoExecution("goal0","m0")); + m0.setElapsedTime(3000); + ph0.addMojoProfile(m0); + MojoProfile m00 = new MojoProfile(mojoExecution("goal00","m00")); + m00.setElapsedTime(5492009); + ph0.addMojoProfile(m00); + p0.addPhaseProfile(ph0); + s.addProjectProfile(p0); + + ProjectProfile p1 = new ProjectProfile(project("g1", "a1", "v1")); + PhaseProfile ph1 = new PhaseProfile("phase1"); + MojoProfile m1 = new MojoProfile(mojoExecution("goal1", "m1")); + m1.setElapsedTime(2500); + ph1.addMojoProfile(m1); + p1.addPhaseProfile(ph1); + s.addProjectProfile(p1); + + ProjectProfile p2 = new ProjectProfile(project("g2", "a2", "v2")); + PhaseProfile ph2 = new PhaseProfile("phase2"); + MojoProfile m2 = new MojoProfile(mojoExecution("goal2","m2")); + m2.setElapsedTime(5000); + ph2.addMojoProfile(m2); + p2.addPhaseProfile(ph2); + s.addProjectProfile(p2); + + SessionProfileRenderer r = new SessionProfileRenderer(); + r.render(s); + } + + protected MavenProject project(String g, String a, String v) { + MavenProject p = new MavenProject(); + p.setGroupId(g); + p.setArtifactId(a); + p.setVersion(v); + return p; + } + + protected MojoExecution mojoExecution(String goal, String executionId) { + Plugin p = new Plugin(); + p.setGroupId("groupId"); + p.setArtifactId("artifactId"); + p.setVersion("version"); + MojoExecution me = new MojoExecution(p, goal, executionId); + return me; + } +}