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

#5 Allow printing report to a JSON file #14

Open
wants to merge 47 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
9db5583
feat: add .idea folder to .gitignore
Feb 11, 2020
ad5e24d
feat: add org.json dependency to pom.xml
Feb 11, 2020
d8cb153
feat: add toJSON function in DiscoveryTimer
Feb 11, 2020
8d5fed8
feat: add toJSON function in MojoTimer
Feb 11, 2020
acb3946
fix: move opening braces to next line
Feb 11, 2020
8eef35f
fix: move opening braces to next line in MojoTimer
Feb 11, 2020
7d90ac4
fix: change discoveryTime type from String to long
Feb 11, 2020
3c5c509
feat: add toJSON function in GoalTimer
Feb 11, 2020
8bd0f7b
feat: add toJSON function in InstallTimer
Feb 11, 2020
5369904
fix: refactor JSON output in InstallTimer
Feb 11, 2020
52493af
feat: add toJSON function in DownloadTimer
Feb 11, 2020
7daeaed
feat: add toJSON function in DeployTimer
Feb 11, 2020
8f0b3a3
feat: add toJSON function in MetadataInstallTimer
Feb 11, 2020
f71fb70
refactor: move all toJSON in AbstractMetadataTimer classes to parent …
Feb 11, 2020
d95e096
fix: remove toJSON function from MetadataInstallTimer
Feb 11, 2020
d5ddc8b
feat: add toJSON function in AbstractMetadataTimer
Feb 11, 2020
7637707
feat: add toJSON function in ProjectTimer
Feb 11, 2020
cda6914
refactor: move stdout report to report function
Feb 11, 2020
39b61b7
feat: use getters when the report is not a JSONObject
Feb 11, 2020
b71d479
feat: use getters when the report is not a JSONObject
Feb 11, 2020
f27c9ed
feat: add toJSON function in BuildTimeProfiler
Feb 11, 2020
7cedd23
fix: handle infinite values in AbstractArtifactTimer
Feb 11, 2020
541855f
feat: temporary feature to print JSON result
Feb 11, 2020
57b6adf
feat: define plugins and phases sections in JSON output
Feb 11, 2020
2a1bbb3
fix: error in plugins section JSON structure
Feb 11, 2020
33dd5a7
feat: make output report selectable via maven-buildtime-profiler-outp…
Feb 11, 2020
8cfae64
feat: make output file selectable via maven-buildtime-profiler-direct…
Feb 11, 2020
61f14a4
fix: read maven-buildtime-profiler-output instead of maven-buildtime-…
Feb 11, 2020
3c64d04
fix: missing return after printing report to file
Feb 11, 2020
9d43be8
fix: time in phase subgroup incrementing badly
Feb 11, 2020
37fa1ab
feat: improve IOException catch when writing to file
Feb 11, 2020
3ed233b
feat: update README
Feb 11, 2020
34a2dc7
fix: use target/ as the default output directory
Feb 12, 2020
f2f940b
fix: JSON metadata field structure and use hyphen separated names
Feb 18, 2020
0fbd446
feat: add none output mode
Feb 19, 2020
a63a74c
feat: update README
Feb 19, 2020
f0ef617
feat: add total build time metric to the JSON output
Feb 19, 2020
eb7086b
feat: use .name properties instead of -name
Feb 20, 2020
0af801c
feat: update README
Feb 20, 2020
9db829d
fix: remove unused imports
Feb 20, 2020
192b5fc
fix: remove more unused imports and leave untouched files equal
Feb 20, 2020
54eb3f7
feat: bump target jvm version to 1.8
Mar 2, 2020
8c46177
feat: add maven execution info to final report
Mar 2, 2020
d2592cb
fix: bump jvm to 1.8
Mar 2, 2020
9e296c9
fix: switch off json command property
Mar 2, 2020
68fff94
Merge branch 'master' of https://github.com/khmarbaise/maven-buildtim…
Mar 4, 2020
7e586f1
feat(config): enable setting config via system properties
Mar 16, 2020
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ target
.project
.classpath
.settings
# IDEA generated
.idea
# Release plugin
release.properties
# TestNG within Eclipse.
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ have to define the following `.mvn/extensions.xml` file:

The download from Maven Central will be done by Maven itself.

This extension allows printing the report to a JSON file instead of the stdout. To enable this you
simply have to set the property `<maven-buildtime-profiler.output>` with value `json`
under `<properties>` section in your project's pom.

Additionally, you can set the property `<maven-buildtime-profiler.directory>` to indicate
the destination folder of the `report.json` file:

```xml
<properties>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paleloser Could we move these properties to extension parameters? Is that possible?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe maven extensions don't allow parameters, as they don't work with Mojos: http://maven.apache.org/examples/maven-3-lifecycle-extensions.html

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically you could use a system property ....?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved at 7e586f1.

<maven-buildtime-profiler>json</maven-buildtime-profiler>
<maven-buildtime-profiler.output>${maven-buildtime-profiler}</maven-buildtime-profiler.output>
<maven-buildtime-profiler.directory>ignore/</maven-buildtime-profiler.directory>
</properties>
```

<small>Note that in this example we can also set the output mode adding `-Dmaven-buildtime-profiler=stdout`</small> to the maven command.

Also, if somehow you don't want to export the profiling result you can set `<maven-buildtime-profiler.output>` to `none`.

Here's an example of what the output will look like:

```
Expand Down
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20190722</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
Expand Down Expand Up @@ -194,6 +199,14 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>

</plugins>
</build>
Expand Down
72 changes: 70 additions & 2 deletions src/main/java/com/soebes/maven/extensions/BuildTimeProfiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
* under the License.
*/

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
Expand All @@ -37,6 +40,7 @@
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.RepositoryEvent;
import org.eclipse.aether.RepositoryEvent.EventType;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -85,6 +89,8 @@ public class BuildTimeProfiler

private final ProjectTimer forkProject;

private final Execution execution;

public BuildTimeProfiler()
{
LOGGER.debug( "LifeCycleProfiler ctor called." );
Expand All @@ -103,7 +109,7 @@ public BuildTimeProfiler()
this.metadataInstallTimer = new MetadataInstallTimer();
this.forkTimer = new ForkTimer();
this.forkProject = new ProjectTimer();

this.execution = new Execution();
}

@Override
Expand Down Expand Up @@ -387,10 +393,50 @@ private void executionRequestEventHandler( MavenExecutionRequest event )
// event.getUserProperties().put( "revision", "1.2.3-SNAPSHOT" );
// event.getSystemProperties().put( "revision", "1.2.3-SNAPSHOT" );
// Can we do something more useful here?
this.execution.setExecutionRequest(event);
LOGGER.debug( "MBTP: executionRequestEventHandler: {}", event.getExecutionListener() );
}

private void executionResultEventHandler( MavenExecutionResult event )
{
String OUTPUT_PROPERTY = "maven-buildtime-profiler.directory";
String output = System.getProperty(OUTPUT_PROPERTY, event.getProject().getProperties().containsKey(OUTPUT_PROPERTY)
? event.getProject().getProperties().getProperty(OUTPUT_PROPERTY) : "stdout");
String filename = null;
String body = null;

switch (output.toLowerCase())
{
case "json":
body = toJSON().toString();
filename = "report.json";
break;
case "none":
break;
case "stdout":
default:
report(event);
}

if (filename != null && body != null)
{
String DIRECTORY_PROPERTY = "maven-buildtime-profiler.directory";
String directory = System.getProperty(DIRECTORY_PROPERTY, event.getProject().getProperties().containsKey(DIRECTORY_PROPERTY)
? event.getProject().getProperties().getProperty(DIRECTORY_PROPERTY) : "target/");
File dest = new File(directory, filename);

try (FileWriter file = new FileWriter(dest))
{
file.write(body);
}
catch (IOException e)
{
LOGGER.warn("Couldn't write to file at {}: {}", dest, e.getMessage());
}
}
}

private void report(MavenExecutionResult event)
{
orderLifeCycleOnPreparedOrder( lifeCyclePhases );

Expand Down Expand Up @@ -445,7 +491,7 @@ private void executionResultEventHandler( MavenExecutionResult event )
for ( Entry<ProjectMojo, SystemTime> pluginInPhase : plugisInPhase.entrySet() )
{
LOGGER.info( "{} ms: {}", String.format( "%8d", pluginInPhase.getValue().getElapsedTime() ),
pluginInPhase.getKey().getMojo().getFullId() );
pluginInPhase.getKey().getMojo().getFullId() );
}

}
Expand All @@ -471,6 +517,28 @@ private void executionResultEventHandler( MavenExecutionResult event )
forkProject.report();
}

private JSONObject toJSON()
{
JSONObject jsonObject = new JSONObject();

jsonObject.put("discovery-time", discoveryTimer.getTime());
jsonObject.put("build", mojoTimer.toJSON());
jsonObject.put("goals", goalTimer.toJSON());
jsonObject.put("install", installTimer.toJSON());
jsonObject.put("download", downloadTimer.toJSON());
jsonObject.put("deploy", deployTimer.toJSON());
JSONObject metadata = new JSONObject();
metadata.put("install", metadataInstallTimer.toJSON());
metadata.put("download", metadataDownloadTimer.toJSON());
metadata.put("deployment", metadataDeploymentTimer.toJSON());
jsonObject.put("metadata", metadata);
jsonObject.put("fork-time", forkTimer.getTime());
jsonObject.put("fork-project", forkProject.toJSON());
jsonObject.put("maven-execution", execution.toJSON());

return jsonObject;
}

private ProjectKey mavenProjectToProjectKey( MavenProject project )
{
return new ProjectKey( project.getGroupId(), project.getArtifactId(), project.getVersion() );
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/soebes/maven/extensions/DiscoveryTimer.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@ public void report()
LOGGER.info( "------------------------------------------------------------------------" );
}

public long getTime()
{
return this.time.getElapsedTime();
}
}
81 changes: 81 additions & 0 deletions src/main/java/com/soebes/maven/extensions/Execution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.soebes.maven.extensions;

import org.apache.maven.execution.MavenExecutionRequest;
import org.json.JSONArray;
import org.json.JSONObject;

public class Execution
{

private MavenExecutionRequest execution;

private String command;

public Execution()
{

}

public Execution(MavenExecutionRequest executionRequest)
{
setExecutionRequest(executionRequest);
}

public void setExecutionRequest(MavenExecutionRequest executionRequest)
{
this.execution = executionRequest;
// initCommand();
}

private void initCommand() {
StringBuilder cmd = new StringBuilder("mvn");

if (this.execution.isUpdateSnapshots())
{
cmd.append(" ").append("-U");
}

if (!this.execution.isRecursive())
{
cmd.append(" ").append("-N");
}

this.execution.getActiveProfiles()
.forEach(profile -> cmd.append(" -P").append(profile));

this.execution.getUserProperties()
.keySet()
.forEach(prop -> cmd.append(" -D").append(prop.toString()));

this.execution.getGoals().forEach(goal -> cmd.append(" ").append(goal));

this.command = cmd.toString();
}

public JSONObject toJSON()
{
JSONObject execution = new JSONObject();

JSONArray goals = new JSONArray();
goals.put(this.execution.getGoals());

JSONObject userProperties = new JSONObject();
this.execution.getUserProperties()
.keySet()
.forEach(key -> userProperties.put((String) key, this.execution.getUserProperties().get(key)));

JSONArray selectedProjects = new JSONArray();
selectedProjects.put(this.execution.getSelectedProjects());

JSONArray profiles = new JSONArray();
this.execution.getActiveProfiles().forEach(profiles::put);

execution.put("goals", goals);
execution.put("user-properties", userProperties);
execution.put("selected-projects", selectedProjects);
execution.put("active-profiles", profiles);
// execution.put("command", this.command);

return execution;
}
}
3 changes: 3 additions & 0 deletions src/main/java/com/soebes/maven/extensions/ForkTimer.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,7 @@ public void report()
LOGGER.info( "ForkTime: {}", this.time.getElapsedTime() );
}

public long getTime() {
return this.time.getElapsedTime();
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/soebes/maven/extensions/GoalTimer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -66,4 +67,16 @@ public void report()
item.getKey().getId() );
}
}

public JSONObject toJSON()
{
JSONObject jsonObject = new JSONObject();

for ( Entry<ProjectGoal, SystemTime> item : this.timerEvents.entrySet() )
{
jsonObject.put(item.getKey().getId(), item.getValue().getElapsedTime());
}

return jsonObject;
}
}
51 changes: 51 additions & 0 deletions src/main/java/com/soebes/maven/extensions/MojoTimer.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -142,4 +143,54 @@ public void report()
LOGGER.info( "{} : {}", item.getKey().getId(), item.getValue().getElapsedTime() );
}
}

public JSONObject toJSON()
{
JSONObject jsonObject = new JSONObject();
JSONObject projectObject = new JSONObject();
JSONObject phaseObject = new JSONObject();
JSONObject pluginsObject = new JSONObject();

long totalTime = 0;

for ( Entry<ProjectMojo, SystemTime> item : this.timerEvents.entrySet() )
{
String artifactId = item.getKey().getProject().getArtifactId();
String phase = item.getKey().getMojo().getPhase();
String plugin = item.getKey().getMojo().getFullId();
long time = item.getValue().getElapsedTime();

// Projects section

JSONObject artifactObject = projectObject.has(artifactId) ? projectObject.getJSONObject(artifactId) : new JSONObject();

artifactObject.put(phase, artifactObject.has(phase) ? (long) artifactObject.get(phase) + time : time);
projectObject.put(artifactId, artifactObject);

// Phases section

phaseObject.put(phase, phaseObject.has(phase) ? (long) phaseObject.get(phase) + time : time);

// Plugins section

if (!pluginsObject.has(phase))
pluginsObject.put(phase, new JSONObject());

long pluginResult = ((JSONObject) pluginsObject.get(phase)).has(plugin) ?
(long) ((JSONObject) pluginsObject.get(phase)).get(plugin) : 0;

pluginResult += time;

((JSONObject) pluginsObject.get(phase)).put(plugin, pluginResult);

totalTime += time;
}

jsonObject.put("projects", projectObject);
jsonObject.put("phases", phaseObject);
jsonObject.put("plugins", pluginsObject);
jsonObject.put("time", totalTime);

return jsonObject;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/soebes/maven/extensions/ProjectTimer.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.project.MavenProject;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -80,4 +81,16 @@ public void report()
LOGGER.info( "ProjectTimer: {} : {}", item.getKey(), item.getValue().getElapsedTime() );
}
}

public JSONObject toJSON()
{
JSONObject jsonObject = new JSONObject();

for ( Entry<String, SystemTime> item : this.timerEvents.entrySet() )
{
jsonObject.put(item.getKey(), item.getValue().getElapsedTime());
}

return jsonObject;
}
}
Loading