Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP JENKINS-56448 Report of the time spent in each phase of the Maven build (compile, test...) #222

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package org.jenkinsci.plugins.pipeline.maven.model;

import java.io.Serializable;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;

import javax.annotation.Nonnull;

/**
* @author <a href="mailto:[email protected]">Cyrille Le Clerc</a>
*/
public class MavenExecutionDetails implements Comparable<MavenExecutionDetails>, Serializable {

private static final long serialVersionUID = 1L;

private SortedSet<MavenProjectExecutionDetails> mavenProjectExecutionDetails = new TreeSet<>();

@Nonnull
private final ZonedDateTime start;
@Nonnull
private ZonedDateTime stop;

public MavenExecutionDetails(@Nonnull ZonedDateTime start) {
this.start = start;
}

public SortedSet<MavenProjectExecutionDetails> getMavenProjectExecutionDetails() {
return mavenProjectExecutionDetails;
}

@Nonnull
public ZonedDateTime getStart() {
return start;
}

@Nonnull
public ZonedDateTime getStop() {
return stop;
}

public void setStop(@Nonnull ZonedDateTime stop) {
this.stop = stop;
}

@Override
public int compareTo(MavenExecutionDetails o) {
return this.start.compareTo(o.start);
}

/**
* it's a poor comparison but there is no risk of having 2 builds starting at the same time
*
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

MavenExecutionDetails that = (MavenExecutionDetails) o;

return start.equals(that.start);
}

@Override
public int hashCode() {
return start.hashCode();
}

public String getExecutionDurationDetails() {

Map<String, MavenExecutionPhaseDetails> phaseDetailsByPhase = new HashMap<>();

for (MavenProjectExecutionDetails projectExecutionDetails :
getMavenProjectExecutionDetails()) {
for (MavenMojoExecutionDetails mojoExecutionDetails : projectExecutionDetails.getMojoExecutionDetails()) {

MavenExecutionPhaseDetails mavenExecutionPhaseDetails = phaseDetailsByPhase.computeIfAbsent(mojoExecutionDetails.getLifecyclePhase(), phase -> new MavenExecutionPhaseDetails(phase));
mavenExecutionPhaseDetails.getMojoExecutionDetails().add(mojoExecutionDetails);
}
}

StringBuilder sb = new StringBuilder();

int phasesCounter = 0;
int mojoExecutionCounter = 0;
List<MavenExecutionPhaseDetails> mavenExecutionPhaseDetailsList = phaseDetailsByPhase.values().stream().sorted().collect(Collectors.toList());

for (MavenExecutionPhaseDetails phaseDetails : mavenExecutionPhaseDetailsList) {
phasesCounter++;
if (phaseDetails.getMojoExecutionDetails().isEmpty()) {

} else {
sb.append(" * " + phaseDetails.getPhase() + " --- " + phaseDetails.getDuration() + "\n");
for (MavenMojoExecutionDetails mojoExecutionDetails : phaseDetails.getMojoExecutionDetails().stream()/*.filter(m -> m.getDurationMillis() > 1000)*/.collect(Collectors.toList())) {
mojoExecutionCounter++;
sb.append(" * " + mojoExecutionDetails.getPlugin().getArtifactId() + ":" + mojoExecutionDetails.getGoal() + " (" + mojoExecutionDetails.getLifecyclePhase() + " - " + mojoExecutionDetails.getExecutionId() + ")" + " @ " + mojoExecutionDetails.getProject().getArtifactId() + " --- " + mojoExecutionDetails.getDuration() + "\n");
}
}
}

sb.append("\n####\n");
for (MavenExecutionPhaseDetails phaseDetails : mavenExecutionPhaseDetailsList) {
if (phaseDetails.getMojoExecutionDetails().isEmpty()) {
} else {
sb.append(" * " + phaseDetails.getPhase() + " --- " + phaseDetails.getDuration() + "\n");
}
}

sb.append("phases:" + phasesCounter + ", mojoExecutions:" + mojoExecutionCounter);

return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.jenkinsci.plugins.pipeline.maven.model;

/**
* See {@code org.apache.maven.execution.ExecutionEvent.Type}
*/
public enum MavenExecutionEventType {
ProjectDiscoveryStarted,
SessionStarted,
SessionEnded,
ProjectSkipped,
ProjectStarted,
ProjectSucceeded,
ProjectFailed,
MojoSkipped,
MojoStarted,
MojoSucceeded,
MojoFailed,
ForkStarted,
ForkSucceeded,
ForkFailed,
ForkedProjectStarted,
ForkedProjectSucceeded,
ForkedProjectFailed
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.jenkinsci.plugins.pipeline.maven.model;

import edu.umd.cs.findbugs.annotations.NonNull;
import org.apache.commons.lang3.builder.CompareToBuilder;

import java.time.ZonedDateTime;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nonnull;

/**
* @author <a href="mailto:[email protected]">Cyrille Le Clerc</a>
*/
public class MavenExecutionPhaseDetails implements Comparable<MavenExecutionPhaseDetails> {
@NonNull
private final String phase;
@NonNull
private SortedSet<MavenMojoExecutionDetails> mojoExecutionDetails = new TreeSet<>();

public MavenExecutionPhaseDetails(@NonNull String phase) {
this.phase = phase;
}

@Nonnull
public ZonedDateTime getStart() {
return mojoExecutionDetails.first().getStart();
}

@Nonnull
public ZonedDateTime getStop() {
return mojoExecutionDetails.last().getStop();
}

/**
* Duration in seconds
* @return duration (e.g. "12s")
*/
@Nonnull
public String getDuration() {
int durationInSecs = 0;
for (MavenMojoExecutionDetails mojoExecutionDetails:getMojoExecutionDetails()) {
durationInSecs += mojoExecutionDetails.getDurationMillis();
}
return TimeUnit.SECONDS.convert(durationInSecs, TimeUnit.MILLISECONDS) + "s";
}

/**
* Maven lifecycle phase
* @return phase (e.g. "compile")
*/
@NonNull
public String getPhase() {
return phase;
}

public SortedSet<MavenMojoExecutionDetails> getMojoExecutionDetails() {
return mojoExecutionDetails;
}

@Override
public int compareTo(MavenExecutionPhaseDetails other) {
return new CompareToBuilder()
.append(this.getStart(), other.getStart())
.append(this.getStop(), other.getStop())
.toComparison();
}

@Override
public String toString() {
return "MavenExecutionPhaseDetails{" +
"phase=" + phase +
", mojoExecutionDetails=" + mojoExecutionDetails +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.jenkinsci.plugins.pipeline.maven.model;

/**
* See {@code org.apache.maven.execution.BuildSuccess} and {@code org.apache.maven.execution.BuildFailure}
*/
public enum MavenExecutionStatus {Success, Failure}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package org.jenkinsci.plugins.pipeline.maven.model;

import org.jenkinsci.plugins.pipeline.maven.MavenArtifact;

import java.io.Serializable;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

import javax.annotation.Nonnull;

/**
* @author <a href="mailto:[email protected]">Cyrille Le Clerc</a>
*/
public class MavenMojoExecutionDetails implements Comparable<MavenMojoExecutionDetails>, Serializable {

private static final long serialVersionUID = 1L;

@Nonnull
private final MavenArtifact project;
@Nonnull
private final MavenArtifact plugin;
@Nonnull
private final String executionId;
@Nonnull
private final String goal;
@Nonnull
private final String lifecyclePhase;
@Nonnull
private final ZonedDateTime start;
@Nonnull
private ZonedDateTime stop;
@Nonnull
private MavenExecutionEventType type;

public MavenMojoExecutionDetails(@Nonnull MavenArtifact project, @Nonnull MavenArtifact plugin, @Nonnull String executionId, @Nonnull String lifecyclePhase, @Nonnull String goal, @Nonnull ZonedDateTime start, @Nonnull MavenExecutionEventType type) {
this.project = project;
this.plugin = plugin;
this.executionId = executionId;
this.lifecyclePhase = lifecyclePhase;
this.goal = goal;
this.start = start;
this.stop = start;
this.type = type;
}

/**
* See {@code org.apache.maven.execution.ExecutionEvent.Type#MojoStarted}
*/
@Nonnull
public ZonedDateTime getStart() {
return start;
}

/**
* See {@code org.apache.maven.execution.ExecutionEvent.Type#MojoSucceeded} and {@code org.apache.maven.execution.ExecutionEvent.Type#MojoFailed}
*/
@Nonnull
public ZonedDateTime getStop() {
return stop;
}

public void stop(@Nonnull ZonedDateTime stop, MavenExecutionEventType type) {
this.stop = stop;
this.type = type;
}

@Nonnull
public MavenArtifact getProject() {
return project;
}

@Nonnull
public MavenArtifact getPlugin() {
return plugin;
}

@Nonnull
public String getExecutionId() {
return executionId;
}

@Nonnull
public String getLifecyclePhase() {
return lifecyclePhase;
}

@Nonnull
public String getGoal() {
return goal;
}

@Override
public String toString() {
return "MavenMojoExecutionDetails{" +
"project=" + project.getId() +
", plugin=" + plugin.getId() +
", executionId='" + executionId + '\'' +
", lifecyclePhase='" + lifecyclePhase + '\'' +
", goal='" + goal + '\'' +
", start=" + start +
", stop=" + stop +
", type=" + type +
'}';
}

@Override
public int compareTo(MavenMojoExecutionDetails other) {
int comparison = this.getStart().compareTo(other.getStart());

if (comparison == 0) {
comparison = this.getStop().compareTo(other.getStop());
}
return comparison;
}

@Nonnull
public String getDuration() {
return Duration.between(start, stop).getSeconds() + "s";
}

@Nonnull
public long getDurationMillis() {
return start.until(stop, ChronoUnit.MILLIS);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

MavenMojoExecutionDetails that = (MavenMojoExecutionDetails) o;

if (!project.equals(that.project)) return false;
if (!plugin.equals(that.plugin)) return false;
if (!executionId.equals(that.executionId)) return false;
return goal.equals(that.goal);
}

@Override
public int hashCode() {
int result = project.hashCode();
result = 31 * result + plugin.hashCode();
result = 31 * result + executionId.hashCode();
result = 31 * result + goal.hashCode();
return result;
}
}
Loading