aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2013-06-12 09:47:28 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2013-06-12 09:48:14 +0200
commit4c0b66d797afc6ecc322caaaa84c4e6542443d18 (patch)
tree8be7be868afc98bab516a8b3fac50c406e7d04be /sonar-batch
parent722a02188710fe1b15229e70dc7541a3caa033c5 (diff)
downloadsonarqube-4c0b66d797afc6ecc322caaaa84c4e6542443d18.tar.gz
sonarqube-4c0b66d797afc6ecc322caaaa84c4e6542443d18.zip
SONAR-4384 Add missing phases to Sonar profiling
Diffstat (limited to 'sonar-batch')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/events/BatchStepEvent.java62
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/events/BatchStepHandler.java47
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/InitializerExecutionEvent.java49
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/InitializersExecutor.java13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/InitializersPhaseEvent.java51
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/MavenPhaseEvent.java41
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java91
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/profiling/AbstractTimeProfiling.java28
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/profiling/ModuleProfiling.java38
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/profiling/PhaseProfiling.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java87
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java58
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java134
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java61
14 files changed, 650 insertions, 121 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/events/BatchStepEvent.java b/sonar-batch/src/main/java/org/sonar/batch/events/BatchStepEvent.java
new file mode 100644
index 00000000000..30036917e3b
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/events/BatchStepEvent.java
@@ -0,0 +1,62 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.events;
+
+/**
+ * Generic event for some steps of project scan.
+ * @since 3.7
+ *
+ */
+public class BatchStepEvent extends BatchEvent<BatchStepHandler>
+ implements BatchStepHandler.BatchStepEvent {
+
+ private final boolean start;
+
+ private String stepName;
+
+ public BatchStepEvent(String stepName, boolean start) {
+ this.start = start;
+ this.stepName = stepName;
+ }
+
+ @Override
+ public String stepName() {
+ return stepName;
+ }
+
+ public final boolean isStart() {
+ return start;
+ }
+
+ public final boolean isEnd() {
+ return !start;
+ }
+
+ @Override
+ protected void dispatch(BatchStepHandler handler) {
+ handler.onBatchStep(this);
+ }
+
+ @Override
+ protected Class getType() {
+ return BatchStepHandler.class;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/events/BatchStepHandler.java b/sonar-batch/src/main/java/org/sonar/batch/events/BatchStepHandler.java
new file mode 100644
index 00000000000..2f4a39548c9
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/events/BatchStepHandler.java
@@ -0,0 +1,47 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.events;
+
+import org.sonar.api.batch.events.EventHandler;
+
+/**
+ * @since 3.7
+ */
+public interface BatchStepHandler extends EventHandler {
+
+ /**
+ * This interface is not intended to be implemented by clients.
+ */
+ interface BatchStepEvent {
+
+ String stepName();
+
+ boolean isStart();
+
+ boolean isEnd();
+
+ }
+
+ /**
+ * Called before and after execution of each final step of project analysis
+ */
+ void onBatchStep(BatchStepEvent event);
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/InitializerExecutionEvent.java b/sonar-batch/src/main/java/org/sonar/batch/phases/InitializerExecutionEvent.java
new file mode 100644
index 00000000000..e85969d94b5
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/InitializerExecutionEvent.java
@@ -0,0 +1,49 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases;
+
+import org.sonar.api.batch.Initializer;
+import org.sonar.api.batch.events.InitializerExecutionHandler;
+
+class InitializerExecutionEvent extends AbstractPhaseEvent<InitializerExecutionHandler>
+ implements org.sonar.api.batch.events.InitializerExecutionHandler.InitializerExecutionEvent {
+
+ private final Initializer initializer;
+
+ InitializerExecutionEvent(Initializer initializer, boolean start) {
+ super(start);
+ this.initializer = initializer;
+ }
+
+ public Initializer getInitializer() {
+ return initializer;
+ }
+
+ @Override
+ public void dispatch(InitializerExecutionHandler handler) {
+ handler.onInitializerExecution(this);
+ }
+
+ @Override
+ public Class getType() {
+ return InitializerExecutionHandler.class;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/InitializersExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/InitializersExecutor.java
index e3d391659b2..e57f5908a9e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/InitializersExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/InitializersExecutor.java
@@ -19,6 +19,7 @@
*/
package org.sonar.batch.phases;
+import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,8 +29,9 @@ import org.sonar.api.batch.maven.DependsUponMavenPlugin;
import org.sonar.api.batch.maven.MavenPluginHandler;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.TimeProfiler;
-import org.sonar.batch.scan.maven.MavenPluginExecutor;
+import org.sonar.batch.events.EventBus;
import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
+import org.sonar.batch.scan.maven.MavenPluginExecutor;
import java.util.Collection;
@@ -42,27 +44,34 @@ public class InitializersExecutor {
private DefaultModuleFileSystem fs;
private Project project;
private BatchExtensionDictionnary selector;
+ private EventBus eventBus;
- public InitializersExecutor(BatchExtensionDictionnary selector, Project project, DefaultModuleFileSystem fs, MavenPluginExecutor mavenExecutor) {
+ public InitializersExecutor(BatchExtensionDictionnary selector, Project project, DefaultModuleFileSystem fs, MavenPluginExecutor mavenExecutor, EventBus eventBus) {
this.selector = selector;
this.mavenExecutor = mavenExecutor;
this.project = project;
this.fs = fs;
+ this.eventBus = eventBus;
}
public void execute() {
Collection<Initializer> initializers = selector.select(Initializer.class, project, true);
+ eventBus.fireEvent(new InitializersPhaseEvent(Lists.newArrayList(initializers), true));
if (LOG.isDebugEnabled()) {
LOG.debug("Initializers : {}", StringUtils.join(initializers, " -> "));
}
for (Initializer initializer : initializers) {
+ eventBus.fireEvent(new InitializerExecutionEvent(initializer, true));
executeMavenPlugin(initializer);
TimeProfiler profiler = new TimeProfiler(LOG).start("Initializer " + initializer);
initializer.execute(project);
profiler.stop();
+ eventBus.fireEvent(new InitializerExecutionEvent(initializer, false));
}
+
+ eventBus.fireEvent(new InitializersPhaseEvent(Lists.newArrayList(initializers), false));
}
private void executeMavenPlugin(Initializer sensor) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/InitializersPhaseEvent.java b/sonar-batch/src/main/java/org/sonar/batch/phases/InitializersPhaseEvent.java
new file mode 100644
index 00000000000..a3d48fc2654
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/InitializersPhaseEvent.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases;
+
+import org.sonar.api.batch.Initializer;
+import org.sonar.api.batch.events.InitializersPhaseHandler;
+
+import java.util.List;
+
+class InitializersPhaseEvent extends AbstractPhaseEvent<InitializersPhaseHandler>
+ implements org.sonar.api.batch.events.InitializersPhaseHandler.InitializersPhaseEvent {
+
+ private final List<Initializer> initializers;
+
+ InitializersPhaseEvent(List<Initializer> initializers, boolean start) {
+ super(start);
+ this.initializers = initializers;
+ }
+
+ public List<Initializer> getInitializers() {
+ return initializers;
+ }
+
+ @Override
+ protected void dispatch(InitializersPhaseHandler handler) {
+ handler.onInitializersPhase(this);
+ }
+
+ @Override
+ protected Class getType() {
+ return InitializersPhaseHandler.class;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/MavenPhaseEvent.java b/sonar-batch/src/main/java/org/sonar/batch/phases/MavenPhaseEvent.java
new file mode 100644
index 00000000000..1552e50dc7d
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/MavenPhaseEvent.java
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.phases;
+
+import org.sonar.api.batch.events.MavenPhaseHandler;
+
+class MavenPhaseEvent extends AbstractPhaseEvent<MavenPhaseHandler>
+ implements org.sonar.api.batch.events.MavenPhaseHandler.MavenPhaseEvent {
+
+ MavenPhaseEvent(boolean start) {
+ super(start);
+ }
+
+ @Override
+ protected void dispatch(MavenPhaseHandler handler) {
+ handler.onMavenPhase(this);
+ }
+
+ @Override
+ protected Class getType() {
+ return MavenPhaseHandler.class;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
index b690f19d43e..8b8dd93c7a9 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
@@ -24,6 +24,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
+import org.sonar.batch.events.BatchStepEvent;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.PersistenceManager;
@@ -40,9 +41,9 @@ public final class PhaseExecutor {
public static final Logger LOGGER = LoggerFactory.getLogger(PhaseExecutor.class);
public static Collection<Class> getPhaseClasses() {
- return Lists.<Class>newArrayList(DecoratorsExecutor.class, MavenPhaseExecutor.class, MavenPluginsConfigurator.class,
- PostJobsExecutor.class, SensorsExecutor.class,
- InitializersExecutor.class, ProjectInitializer.class, UpdateStatusJob.class);
+ return Lists.<Class> newArrayList(DecoratorsExecutor.class, MavenPhaseExecutor.class, MavenPluginsConfigurator.class,
+ PostJobsExecutor.class, SensorsExecutor.class,
+ InitializersExecutor.class, ProjectInitializer.class, UpdateStatusJob.class);
}
private EventBus eventBus;
@@ -63,11 +64,11 @@ public final class PhaseExecutor {
private final JsonReport jsonReport;
public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
- MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
- PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
- PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
- EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi,
- ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport) {
+ MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
+ PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
+ PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
+ EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi,
+ ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport) {
this.phases = phases;
this.decoratorsExecutor = decoratorsExecutor;
this.mavenPhaseExecutor = mavenPhaseExecutor;
@@ -87,12 +88,12 @@ public final class PhaseExecutor {
}
public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
- MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
- PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
- PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
- EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport) {
+ MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor,
+ PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
+ PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index,
+ EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport) {
this(phases, decoratorsExecutor, mavenPhaseExecutor, mavenPluginsConfigurator, initializersExecutor, postJobsExecutor,
- sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, jsonReport);
+ sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, jsonReport);
}
/**
@@ -100,37 +101,33 @@ public final class PhaseExecutor {
*/
public void execute(Project module) {
pi.execute(module);
+
eventBus.fireEvent(new ProjectAnalysisEvent(module, true));
- if (phases.isEnabled(Phases.Phase.MAVEN)) {
- mavenPluginsConfigurator.execute(module);
- mavenPhaseExecutor.execute(module);
- }
- if (phases.isEnabled(Phases.Phase.INIT)) {
- initializersExecutor.execute();
- fsLogger.log();
- }
+
+ executeMavenPhase(module);
+
+ executeInitializersPhase();
persistenceManager.setDelayedMode(true);
+
if (phases.isEnabled(Phases.Phase.SENSOR)) {
sensorsExecutor.execute(sensorContext);
}
+
if (phases.isEnabled(Phases.Phase.DECORATOR)) {
decoratorsExecutor.execute();
}
+
+ eventBus.fireEvent(new BatchStepEvent("Save measures", true));
persistenceManager.dump();
+ eventBus.fireEvent(new BatchStepEvent("Save measures", false));
persistenceManager.setDelayedMode(false);
if (module.isRoot()) {
jsonReport.execute();
- LOGGER.info("Store results in database");
- for (ScanPersister persister : persisters) {
- LOGGER.debug("Execute {}", persister.getClass().getName());
- persister.persist();
- }
- if (updateStatusJob != null) {
- updateStatusJob.execute();
- }
+ executePersisters();
+ updateStatusJob();
if (phases.isEnabled(Phases.Phase.POSTJOB)) {
postJobsExecutor.execute(sensorContext);
}
@@ -139,8 +136,44 @@ public final class PhaseExecutor {
eventBus.fireEvent(new ProjectAnalysisEvent(module, false));
}
+ private void executePersisters() {
+ LOGGER.info("Store results in database");
+ eventBus.fireEvent(new BatchStepEvent("Persisters", true));
+ for (ScanPersister persister : persisters) {
+ LOGGER.debug("Execute {}", persister.getClass().getName());
+ persister.persist();
+ }
+ eventBus.fireEvent(new BatchStepEvent("Persisters", false));
+ }
+
+ private void updateStatusJob() {
+ if (updateStatusJob != null) {
+ eventBus.fireEvent(new BatchStepEvent("Update status job", true));
+ updateStatusJob.execute();
+ eventBus.fireEvent(new BatchStepEvent("Update status job", false));
+ }
+ }
+
+ private void executeInitializersPhase() {
+ if (phases.isEnabled(Phases.Phase.INIT)) {
+ initializersExecutor.execute();
+ fsLogger.log();
+ }
+ }
+
+ private void executeMavenPhase(Project module) {
+ if (phases.isEnabled(Phases.Phase.MAVEN)) {
+ eventBus.fireEvent(new MavenPhaseEvent(true));
+ mavenPluginsConfigurator.execute(module);
+ mavenPhaseExecutor.execute(module);
+ eventBus.fireEvent(new MavenPhaseEvent(false));
+ }
+ }
+
private void cleanMemory() {
+ eventBus.fireEvent(new BatchStepEvent("Clean memory", true));
persistenceManager.clear();
index.clear();
+ eventBus.fireEvent(new BatchStepEvent("Clean memory", false));
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/profiling/AbstractTimeProfiling.java b/sonar-batch/src/main/java/org/sonar/batch/profiling/AbstractTimeProfiling.java
index a610520ef5f..badcec28122 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/profiling/AbstractTimeProfiling.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/profiling/AbstractTimeProfiling.java
@@ -25,7 +25,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
public abstract class AbstractTimeProfiling {
@@ -64,16 +66,20 @@ public abstract class AbstractTimeProfiling {
this.setTotalTime(this.totalTime() + other.totalTime());
}
- static <G extends AbstractTimeProfiling> List<G> sortByDescendingTotalTime(Collection<G> unsorted) {
- List<G> result = new ArrayList<G>(unsorted.size());
- result.addAll(unsorted);
- Collections.sort(result, new Comparator<G>() {
+ static <G extends AbstractTimeProfiling> Map<Object, G> sortByDescendingTotalTime(Map<?, G> unsorted) {
+ List<Map.Entry<?, G>> entries =
+ new ArrayList<Map.Entry<?, G>>(unsorted.entrySet());
+ Collections.sort(entries, new Comparator<Map.Entry<?, G>>() {
@Override
- public int compare(G o1, G o2) {
- return Long.valueOf(o2.totalTime()).compareTo(o1.totalTime());
+ public int compare(Map.Entry<?, G> o1, Map.Entry<?, G> o2) {
+ return Long.valueOf(o2.getValue().totalTime()).compareTo(o1.getValue().totalTime());
}
});
- return result;
+ Map<Object, G> sortedMap = new LinkedHashMap<Object, G>();
+ for (Map.Entry<?, G> entry : entries) {
+ sortedMap.put(entry.getKey(), entry.getValue());
+ }
+ return sortedMap;
}
static <G extends AbstractTimeProfiling> List<G> truncate(Collection<G> sortedList) {
@@ -95,4 +101,12 @@ public abstract class AbstractTimeProfiling {
PhasesSumUpTimeProfiler.println(msg);
}
+ protected void println(String text, Double percent, AbstractTimeProfiling phaseProfiling) {
+ PhasesSumUpTimeProfiler.println(text, percent, phaseProfiling);
+ }
+
+ protected void println(String text, AbstractTimeProfiling phaseProfiling) {
+ println(text, null, phaseProfiling);
+ }
+
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/profiling/ModuleProfiling.java b/sonar-batch/src/main/java/org/sonar/batch/profiling/ModuleProfiling.java
index e1b48fcba69..e7ba4104cb0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/profiling/ModuleProfiling.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/profiling/ModuleProfiling.java
@@ -19,20 +19,22 @@
*/
package org.sonar.batch.profiling;
+import com.google.common.collect.Maps;
import org.sonar.api.resources.Project;
-import org.sonar.api.utils.TimeUtils;
import org.sonar.batch.phases.Phases;
import org.sonar.batch.phases.Phases.Phase;
import javax.annotation.CheckForNull;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
public class ModuleProfiling extends AbstractTimeProfiling {
private Map<Phases.Phase, PhaseProfiling> profilingPerPhase = new HashMap<Phases.Phase, PhaseProfiling>();
+ private Map<String, ItemProfiling> profilingPerBatchStep = new LinkedHashMap<String, ItemProfiling>();
private Clock clock;
private Project module;
@@ -53,24 +55,32 @@ public class ModuleProfiling extends AbstractTimeProfiling {
return profilingPerPhase.get(phase);
}
+ public ItemProfiling getProfilingPerBatchStep(String stepName) {
+ return profilingPerBatchStep.get(stepName);
+ }
+
public void addPhaseProfiling(Phase phase) {
profilingPerPhase.put(phase, PhaseProfiling.create(clock, phase));
}
+ public void addBatchStepProfiling(String stepName) {
+ profilingPerBatchStep.put(stepName, new ItemProfiling(clock, stepName));
+ }
+
public void dump() {
double percent = this.totalTime() / 100.0;
- for (PhaseProfiling phaseProfiling : sortByDescendingTotalTime(profilingPerPhase.values())) {
- StringBuilder sb = new StringBuilder();
- sb.append(" * ").append(phaseProfiling.phase()).append(" execution time: ").append(phaseProfiling.totalTimeAsString())
- .append(" (").append((int) (phaseProfiling.totalTime() / percent)).append("%)");
- println(sb.toString());
+ Map<Object, AbstractTimeProfiling> categories = Maps.newLinkedHashMap();
+ categories.putAll(profilingPerPhase);
+ categories.putAll(profilingPerBatchStep);
+
+ for (Map.Entry<Object, AbstractTimeProfiling> batchStep : sortByDescendingTotalTime(categories).entrySet()) {
+ println(" * " + batchStep.getKey() + " execution time: ", percent, batchStep.getValue());
}
+ // Breakdown per phase
for (Phase phase : Phases.Phase.values()) {
- if (profilingPerPhase.containsKey(phase)) {
- StringBuilder sb = new StringBuilder();
- sb.append("\n * ").append(phase).append(" execution time breakdown: ")
- .append(TimeUtils.formatDuration(getProfilingPerPhase(phase).totalTime()));
- println(sb.toString());
+ if (profilingPerPhase.containsKey(phase) && getProfilingPerPhase(phase).hasItems()) {
+ println("");
+ println(" * " + phase + " execution time breakdown: ", getProfilingPerPhase(phase));
getProfilingPerPhase(phase).dump();
}
}
@@ -84,6 +94,12 @@ public class ModuleProfiling extends AbstractTimeProfiling {
}
this.getProfilingPerPhase(entry.getKey()).merge(entry.getValue());
}
+ for (Map.Entry<String, ItemProfiling> entry : other.profilingPerBatchStep.entrySet()) {
+ if (!this.profilingPerBatchStep.containsKey(entry.getKey())) {
+ profilingPerBatchStep.put(entry.getKey(), new ItemProfiling(clock, entry.getKey()));
+ }
+ this.getProfilingPerBatchStep(entry.getKey()).add(entry.getValue());
+ }
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhaseProfiling.java b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhaseProfiling.java
index 8bb5bcbdacd..45ba18a17bb 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhaseProfiling.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhaseProfiling.java
@@ -47,6 +47,10 @@ public class PhaseProfiling extends AbstractTimeProfiling {
return phase;
}
+ public boolean hasItems() {
+ return !profilingPerItem.isEmpty();
+ }
+
public ItemProfiling getProfilingPerItem(Object item) {
String stringOrSimpleName = toStringOrSimpleName(item);
return profilingPerItem.get(stringOrSimpleName);
@@ -73,11 +77,8 @@ public class PhaseProfiling extends AbstractTimeProfiling {
public void dump() {
double percent = this.totalTime() / 100.0;
- for (ItemProfiling itemProfiling : truncate(sortByDescendingTotalTime(profilingPerItem.values()))) {
- StringBuilder sb = new StringBuilder();
- sb.append(" o ").append(itemProfiling.itemName()).append(": ").append(itemProfiling.totalTimeAsString())
- .append(" (").append((int) (itemProfiling.totalTime() / percent)).append("%)");
- println(sb.toString());
+ for (ItemProfiling itemProfiling : truncate(sortByDescendingTotalTime(profilingPerItem).values())) {
+ println(" o " + itemProfiling.itemName() + ": ", percent, itemProfiling);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java
index 6137b79875e..6aebf4f1b86 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java
@@ -21,11 +21,15 @@ package org.sonar.batch.profiling;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Decorator;
import org.sonar.api.batch.events.DecoratorExecutionHandler;
import org.sonar.api.batch.events.DecoratorsPhaseHandler;
+import org.sonar.api.batch.events.InitializerExecutionHandler;
+import org.sonar.api.batch.events.InitializersPhaseHandler;
+import org.sonar.api.batch.events.MavenPhaseHandler;
import org.sonar.api.batch.events.PostJobExecutionHandler;
import org.sonar.api.batch.events.PostJobsPhaseHandler;
import org.sonar.api.batch.events.ProjectAnalysisHandler;
@@ -33,9 +37,10 @@ import org.sonar.api.batch.events.SensorExecutionHandler;
import org.sonar.api.batch.events.SensorsPhaseHandler;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.TimeUtils;
+import org.sonar.batch.events.BatchStepHandler;
import org.sonar.batch.phases.Phases;
-import java.util.ArrayList;
+import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
@@ -44,15 +49,17 @@ import static org.sonar.batch.profiling.AbstractTimeProfiling.sortByDescendingTo
import static org.sonar.batch.profiling.AbstractTimeProfiling.truncate;
public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorExecutionHandler, DecoratorExecutionHandler, PostJobExecutionHandler, DecoratorsPhaseHandler,
- SensorsPhaseHandler, PostJobsPhaseHandler {
+ SensorsPhaseHandler, PostJobsPhaseHandler, MavenPhaseHandler, InitializersPhaseHandler, InitializerExecutionHandler, BatchStepHandler {
static Logger LOG = LoggerFactory.getLogger(PhasesSumUpTimeProfiler.class);
+ private static final int TEXT_RIGHT_PAD = 60;
+ private static final int TIME_LEFT_PAD = 10;
@VisibleForTesting
ModuleProfiling currentModuleProfiling;
@VisibleForTesting
ModuleProfiling totalProfiling;
- private List<ModuleProfiling> modulesProfilings = new ArrayList<ModuleProfiling>();
+ private Map<Project, ModuleProfiling> modulesProfilings = new HashMap<Project, ModuleProfiling>();
private DecoratorsProfiler decoratorsProfiler;
private Clock clock;
@@ -65,6 +72,15 @@ public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorEx
LOG.info(msg);
}
+ static void println(String text, Double percent, AbstractTimeProfiling phaseProfiling) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(StringUtils.rightPad(text, TEXT_RIGHT_PAD)).append(StringUtils.leftPad(phaseProfiling.totalTimeAsString(), TIME_LEFT_PAD));
+ if (percent != null) {
+ sb.append(" (").append((int) (phaseProfiling.totalTime() / percent)).append("%)");
+ }
+ println(sb.toString());
+ }
+
@VisibleForTesting
PhasesSumUpTimeProfiler(Clock clock) {
this.clock = clock;
@@ -80,11 +96,15 @@ public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorEx
}
else {
currentModuleProfiling.stop();
- modulesProfilings.add(currentModuleProfiling);
+ modulesProfilings.put(module, currentModuleProfiling);
long moduleTotalTime = currentModuleProfiling.totalTime();
- println("\n -------- Profiling of module " + module.getName() + ": " + TimeUtils.formatDuration(moduleTotalTime) + " --------\n");
+ println("");
+ println(" -------- Profiling of module " + module.getName() + ": " + TimeUtils.formatDuration(moduleTotalTime) + " --------");
+ println("");
currentModuleProfiling.dump();
- println("\n -------- End of profiling of module " + module.getName() + " --------\n");
+ println("");
+ println(" -------- End of profiling of module " + module.getName() + " --------");
+ println("");
totalProfiling.merge(currentModuleProfiling);
if (module.isRoot() && !module.getModules().isEmpty()) {
dumpTotalExecutionSummary();
@@ -95,18 +115,19 @@ public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorEx
private void dumpTotalExecutionSummary() {
totalProfiling.stop();
long totalTime = totalProfiling.totalTime();
- println("\n ======== Profiling of total execution: " + TimeUtils.formatDuration(totalTime) + " ========\n");
+ println("");
+ println(" ======== Profiling of total execution: " + TimeUtils.formatDuration(totalTime) + " ========");
+ println("");
println(" * Module execution time breakdown: ");
double percent = totalTime / 100.0;
- for (ModuleProfiling modulesProfiling : truncate(sortByDescendingTotalTime(modulesProfilings))) {
- StringBuilder sb = new StringBuilder();
- sb.append(" o ").append(modulesProfiling.moduleName()).append(" execution time: ").append(modulesProfiling.totalTimeAsString())
- .append(" (").append((int) (modulesProfiling.totalTime() / percent)).append("%)");
- println(sb.toString());
+ for (ModuleProfiling modulesProfiling : truncate(sortByDescendingTotalTime(modulesProfilings).values())) {
+ println(" o " + modulesProfiling.moduleName() + " execution time: ", percent, modulesProfiling);
}
println("");
totalProfiling.dump();
- println("\n ======== End of profiling of total execution ========\n");
+ println("");
+ println(" ======== End of profiling of total execution ========");
+ println("");
}
public void onSensorsPhase(SensorsPhaseEvent event) {
@@ -170,6 +191,46 @@ public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorEx
}
}
+ @Override
+ public void onMavenPhase(MavenPhaseEvent event) {
+ if (event.isStart()) {
+ currentModuleProfiling.addPhaseProfiling(Phases.Phase.MAVEN);
+ }
+ else {
+ currentModuleProfiling.getProfilingPerPhase(Phases.Phase.MAVEN).stop();
+ }
+ }
+
+ @Override
+ public void onInitializersPhase(InitializersPhaseEvent event) {
+ if (event.isStart()) {
+ currentModuleProfiling.addPhaseProfiling(Phases.Phase.INIT);
+ }
+ else {
+ currentModuleProfiling.getProfilingPerPhase(Phases.Phase.INIT).stop();
+ }
+ }
+
+ @Override
+ public void onInitializerExecution(InitializerExecutionEvent event) {
+ PhaseProfiling profiling = currentModuleProfiling.getProfilingPerPhase(Phases.Phase.INIT);
+ if (event.isStart()) {
+ profiling.newItemProfiling(event.getInitializer());
+ } else {
+ profiling.getProfilingPerItem(event.getInitializer()).stop();
+ }
+ }
+
+ @Override
+ public void onBatchStep(BatchStepEvent event) {
+ if (event.isStart()) {
+ currentModuleProfiling.addBatchStepProfiling(event.stepName());
+ }
+ else {
+ currentModuleProfiling.getProfilingPerBatchStep(event.stepName()).stop();
+ }
+ }
+
class DecoratorsProfiler {
List<Decorator> decorators = Lists.newArrayList();
Map<Decorator, Long> durations = new IdentityHashMap<Decorator, Long>();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java b/sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java
index 33b2097ee3f..49bfcc5fa02 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/JsonReport.java
@@ -34,10 +34,16 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.scan.filesystem.ModuleFileSystem;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.SonarException;
+import org.sonar.batch.events.BatchStepEvent;
+import org.sonar.batch.events.EventBus;
import org.sonar.batch.issue.IssueCache;
import org.sonar.core.i18n.RuleI18nManager;
-import java.io.*;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
import java.util.Locale;
import java.util.Set;
@@ -55,18 +61,22 @@ public class JsonReport implements BatchComponent {
private final Server server;
private final RuleI18nManager ruleI18nManager;
private final IssueCache issueCache;
+ private EventBus eventBus;
- public JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache) {
+ public JsonReport(Settings settings, ModuleFileSystem fileSystem, Server server, RuleI18nManager ruleI18nManager, IssueCache issueCache, EventBus eventBus) {
this.settings = settings;
this.fileSystem = fileSystem;
this.server = server;
this.ruleI18nManager = ruleI18nManager;
this.issueCache = issueCache;
+ this.eventBus = eventBus;
}
public void execute() {
if (settings.getBoolean(CoreProperties.DRY_RUN)) {
+ eventBus.fireEvent(new BatchStepEvent("JSON report", true));
exportResults();
+ eventBus.fireEvent(new BatchStepEvent("JSON report", false));
}
}
@@ -114,19 +124,19 @@ public class JsonReport implements BatchComponent {
for (DefaultIssue issue : getIssues()) {
if (issue.resolution() == null) {
json
- .beginObject()
- .name("key").value(issue.key())
- .name("component").value(issue.componentKey())
- .name("line").value(issue.line())
- .name("message").value(issue.message())
- .name("severity").value(issue.severity())
- .name("rule").value(issue.ruleKey().toString())
- .name("status").value(issue.status())
- .name("resolution").value(issue.resolution())
- .name("isNew").value(issue.isNew())
- .name("reporter").value(issue.reporter())
- .name("assignee").value(issue.assignee())
- .name("effortToFix").value(issue.effortToFix());
+ .beginObject()
+ .name("key").value(issue.key())
+ .name("component").value(issue.componentKey())
+ .name("line").value(issue.line())
+ .name("message").value(issue.message())
+ .name("severity").value(issue.severity())
+ .name("rule").value(issue.ruleKey().toString())
+ .name("status").value(issue.status())
+ .name("resolution").value(issue.resolution())
+ .name("isNew").value(issue.isNew())
+ .name("reporter").value(issue.reporter())
+ .name("assignee").value(issue.assignee())
+ .name("effortToFix").value(issue.effortToFix());
if (issue.creationDate() != null) {
json.name("creationDate").value(DateUtils.formatDateTime(issue.creationDate()));
}
@@ -148,9 +158,9 @@ public class JsonReport implements BatchComponent {
json.name("components").beginArray();
for (String componentKey : componentKeys) {
json
- .beginObject()
- .name("key").value(componentKey)
- .endObject();
+ .beginObject()
+ .name("key").value(componentKey)
+ .endObject();
}
json.endArray();
}
@@ -159,12 +169,12 @@ public class JsonReport implements BatchComponent {
json.name("rules").beginArray();
for (RuleKey ruleKey : ruleKeys) {
json
- .beginObject()
- .name("key").value(ruleKey.toString())
- .name("rule").value(ruleKey.rule())
- .name("repository").value(ruleKey.repository())
- .name("name").value(getRuleName(ruleKey))
- .endObject();
+ .beginObject()
+ .name("key").value(ruleKey.toString())
+ .name("rule").value(ruleKey.rule())
+ .name("repository").value(ruleKey.repository())
+ .name("name").value(getRuleName(ruleKey))
+ .endObject();
}
json.endArray();
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java b/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java
index b7a56ce60a4..9c504dbe35a 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java
@@ -23,11 +23,15 @@ import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.Decorator;
import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.batch.Initializer;
import org.sonar.api.batch.PostJob;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.events.DecoratorExecutionHandler;
import org.sonar.api.batch.events.DecoratorsPhaseHandler;
+import org.sonar.api.batch.events.InitializerExecutionHandler;
+import org.sonar.api.batch.events.InitializersPhaseHandler;
+import org.sonar.api.batch.events.MavenPhaseHandler;
import org.sonar.api.batch.events.PostJobExecutionHandler;
import org.sonar.api.batch.events.PostJobsPhaseHandler;
import org.sonar.api.batch.events.ProjectAnalysisHandler;
@@ -38,6 +42,7 @@ import org.sonar.api.batch.events.SensorsPhaseHandler;
import org.sonar.api.batch.events.SensorsPhaseHandler.SensorsPhaseEvent;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
+import org.sonar.batch.events.BatchStepHandler;
import org.sonar.batch.phases.Phases.Phase;
import java.util.Arrays;
@@ -67,6 +72,8 @@ public class PhasesSumUpTimeProfilerTest {
fakeAnalysis(profiler, project);
+ assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.MAVEN).totalTime()).isEqualTo(4L);
+ assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.INIT).getProfilingPerItem(new FakeInitializer()).totalTime()).isEqualTo(7L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(10L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(20L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(30L);
@@ -84,11 +91,15 @@ public class PhasesSumUpTimeProfilerTest {
fakeAnalysis(profiler, moduleB);
fakeAnalysis(profiler, project);
+ assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.MAVEN).totalTime()).isEqualTo(4L);
+ assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.INIT).getProfilingPerItem(new FakeInitializer()).totalTime()).isEqualTo(7L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(10L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(20L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator2()).totalTime()).isEqualTo(10L);
assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(30L);
+ assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.MAVEN).totalTime()).isEqualTo(12L);
+ assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.INIT).getProfilingPerItem(new FakeInitializer()).totalTime()).isEqualTo(21L);
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(30L);
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(60L);
assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator2()).totalTime()).isEqualTo(30L);
@@ -136,9 +147,12 @@ public class PhasesSumUpTimeProfilerTest {
private void fakeAnalysis(PhasesSumUpTimeProfiler profiler, final Project module) throws InterruptedException {
// Start of moduleA
profiler.onProjectAnalysis(projectEvent(module, true));
+ mavenPhase(profiler);
+ initializerPhase(profiler);
sensorPhase(profiler);
decoratorPhase(profiler);
postJobPhase(profiler);
+ batchStep(profiler);
// End of moduleA
profiler.onProjectAnalysis(projectEvent(module, false));
}
@@ -172,6 +186,35 @@ public class PhasesSumUpTimeProfilerTest {
profiler.onDecoratorsPhase(decoratorsEvent(false));
}
+ private void batchStep(PhasesSumUpTimeProfiler profiler) throws InterruptedException {
+ // Start of batch step
+ profiler.onBatchStep(batchStepEvent(true, "Free memory"));
+ clock.sleep(9);
+ // End of batch step
+ profiler.onBatchStep(batchStepEvent(false, "Free memory"));
+ }
+
+ private void mavenPhase(PhasesSumUpTimeProfiler profiler) throws InterruptedException {
+ // Start of maven phase
+ profiler.onMavenPhase(mavenEvent(true));
+ clock.sleep(4);
+ // End of maven phase
+ profiler.onMavenPhase(mavenEvent(false));
+ }
+
+ private void initializerPhase(PhasesSumUpTimeProfiler profiler) throws InterruptedException {
+ Initializer initializer = new FakeInitializer();
+ // Start of initializer phase
+ profiler.onInitializersPhase(initializersEvent(true));
+ // Start of an initializer
+ profiler.onInitializerExecution(initializerEvent(initializer, true));
+ clock.sleep(7);
+ // End of an initializer
+ profiler.onInitializerExecution(initializerEvent(initializer, false));
+ // End of initializer phase
+ profiler.onInitializersPhase(initializersEvent(false));
+ }
+
private void sensorPhase(PhasesSumUpTimeProfiler profiler) throws InterruptedException {
Sensor sensor = new FakeSensor();
// Start of sensor phase
@@ -218,6 +261,26 @@ public class PhasesSumUpTimeProfilerTest {
};
}
+ private InitializerExecutionHandler.InitializerExecutionEvent initializerEvent(final Initializer initializer, final boolean start) {
+ return new InitializerExecutionHandler.InitializerExecutionEvent() {
+
+ @Override
+ public boolean isStart() {
+ return start;
+ }
+
+ @Override
+ public boolean isEnd() {
+ return !start;
+ }
+
+ @Override
+ public Initializer getInitializer() {
+ return initializer;
+ }
+ };
+ }
+
private DecoratorExecutionHandler.DecoratorExecutionEvent decoratorEvent(final Decorator decorator, final boolean start) {
return new DecoratorExecutionHandler.DecoratorExecutionEvent() {
@@ -278,6 +341,61 @@ public class PhasesSumUpTimeProfilerTest {
};
}
+ private BatchStepHandler.BatchStepEvent batchStepEvent(final boolean start, final String stepName) {
+ return new BatchStepHandler.BatchStepEvent() {
+
+ @Override
+ public boolean isStart() {
+ return start;
+ }
+
+ @Override
+ public boolean isEnd() {
+ return !start;
+ }
+
+ @Override
+ public String stepName() {
+ return stepName;
+ }
+ };
+ }
+
+ private MavenPhaseHandler.MavenPhaseEvent mavenEvent(final boolean start) {
+ return new MavenPhaseHandler.MavenPhaseEvent() {
+
+ @Override
+ public boolean isStart() {
+ return start;
+ }
+
+ @Override
+ public boolean isEnd() {
+ return !start;
+ }
+ };
+ }
+
+ private InitializersPhaseHandler.InitializersPhaseEvent initializersEvent(final boolean start) {
+ return new InitializersPhaseHandler.InitializersPhaseEvent() {
+
+ @Override
+ public boolean isStart() {
+ return start;
+ }
+
+ @Override
+ public boolean isEnd() {
+ return !start;
+ }
+
+ @Override
+ public List<Initializer> getInitializers() {
+ return null;
+ }
+ };
+ }
+
private PostJobsPhaseHandler.PostJobsPhaseEvent postJobsEvent(final boolean start) {
return new PostJobsPhaseHandler.PostJobsPhaseEvent() {
@@ -342,24 +460,40 @@ public class PhasesSumUpTimeProfilerTest {
public void analyse(Project project, SensorContext context) {
}
+ @Override
+ public boolean shouldExecuteOnProject(Project project) {
+ return true;
+ }
+ }
+
+ public class FakeInitializer extends Initializer {
+ @Override
+ public void execute(Project project) {
+ }
+
+ @Override
public boolean shouldExecuteOnProject(Project project) {
return true;
}
}
public class FakeDecorator1 implements Decorator {
+ @Override
public void decorate(Resource resource, DecoratorContext context) {
}
+ @Override
public boolean shouldExecuteOnProject(Project project) {
return true;
}
}
public class FakeDecorator2 implements Decorator {
+ @Override
public void decorate(Resource resource, DecoratorContext context) {
}
+ @Override
public boolean shouldExecuteOnProject(Project project) {
return true;
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java
index 3f92ad420f3..51ad93918b4 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/JsonReportTest.java
@@ -35,6 +35,7 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
import org.sonar.api.scan.filesystem.ModuleFileSystem;
import org.sonar.api.utils.DateUtils;
+import org.sonar.batch.events.EventBus;
import org.sonar.batch.issue.IssueCache;
import org.sonar.core.i18n.RuleI18nManager;
import org.sonar.test.TestUtils;
@@ -69,61 +70,61 @@ public class JsonReportTest {
settings = new Settings();
settings.setProperty(CoreProperties.DRY_RUN, true);
- jsonReport = new JsonReport(settings, fileSystem, server, ruleI18nManager, issueCache);
+ jsonReport = new JsonReport(settings, fileSystem, server, ruleI18nManager, issueCache, mock(EventBus.class));
}
@Test
public void should_write_json() throws JSONException {
DefaultIssue issue = new DefaultIssue()
- .setKey("200")
- .setComponentKey("struts:org.apache.struts.Action")
- .setRuleKey(RuleKey.of("squid", "AvoidCycles"))
- .setMessage("There are 2 cycles")
- .setSeverity("MINOR")
- .setStatus(Issue.STATUS_OPEN)
- .setResolution(null)
- .setLine(1)
- .setEffortToFix(3.14)
- .setReporter("julien")
- .setAssignee("simon")
- .setCreationDate(DateUtils.parseDate("2013-04-24"))
- .setUpdateDate(DateUtils.parseDate("2013-04-25"))
- .setNew(false);
+ .setKey("200")
+ .setComponentKey("struts:org.apache.struts.Action")
+ .setRuleKey(RuleKey.of("squid", "AvoidCycles"))
+ .setMessage("There are 2 cycles")
+ .setSeverity("MINOR")
+ .setStatus(Issue.STATUS_OPEN)
+ .setResolution(null)
+ .setLine(1)
+ .setEffortToFix(3.14)
+ .setReporter("julien")
+ .setAssignee("simon")
+ .setCreationDate(DateUtils.parseDate("2013-04-24"))
+ .setUpdateDate(DateUtils.parseDate("2013-04-25"))
+ .setNew(false);
when(ruleI18nManager.getName("squid", "AvoidCycles", Locale.getDefault())).thenReturn("Avoid Cycles");
- when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
+ when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue> newArrayList(issue));
StringWriter writer = new StringWriter();
jsonReport.writeJson(writer);
JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/JsonReportTest/report.json"),
- writer.toString(), false);
+ writer.toString(), false);
}
@Test
public void should_exclude_resolved_issues() throws JSONException {
DefaultIssue issue = new DefaultIssue()
- .setKey("200")
- .setComponentKey("struts:org.apache.struts.Action")
- .setRuleKey(RuleKey.of("squid", "AvoidCycles"))
- .setStatus(Issue.STATUS_CLOSED)
- .setResolution(Issue.RESOLUTION_FIXED)
- .setCreationDate(DateUtils.parseDate("2013-04-24"))
- .setUpdateDate(DateUtils.parseDate("2013-04-25"))
- .setCloseDate(DateUtils.parseDate("2013-04-26"))
- .setNew(false);
+ .setKey("200")
+ .setComponentKey("struts:org.apache.struts.Action")
+ .setRuleKey(RuleKey.of("squid", "AvoidCycles"))
+ .setStatus(Issue.STATUS_CLOSED)
+ .setResolution(Issue.RESOLUTION_FIXED)
+ .setCreationDate(DateUtils.parseDate("2013-04-24"))
+ .setUpdateDate(DateUtils.parseDate("2013-04-25"))
+ .setCloseDate(DateUtils.parseDate("2013-04-26"))
+ .setNew(false);
when(ruleI18nManager.getName("squid", "AvoidCycles", Locale.getDefault())).thenReturn("Avoid Cycles");
- when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue>newArrayList(issue));
+ when(jsonReport.getIssues()).thenReturn(Lists.<DefaultIssue> newArrayList(issue));
StringWriter writer = new StringWriter();
jsonReport.writeJson(writer);
JSONAssert.assertEquals(TestUtils.getResourceContent("/org/sonar/batch/scan/JsonReportTest/report-without-resolved-issues.json"),
- writer.toString(), false);
+ writer.toString(), false);
}
@Test
public void should_ignore_components_without_issue() throws JSONException {
- when(jsonReport.getIssues()).thenReturn(Collections.<DefaultIssue>emptyList());
+ when(jsonReport.getIssues()).thenReturn(Collections.<DefaultIssue> emptyList());
StringWriter writer = new StringWriter();
jsonReport.writeJson(writer);
@@ -137,7 +138,7 @@ public class JsonReportTest {
Rule rule = Rule.create("squid", "AvoidCycles");
when(ruleI18nManager.getName(rule, Locale.getDefault())).thenReturn("Avoid Cycles");
- when(jsonReport.getIssues()).thenReturn(Collections.<DefaultIssue>emptyList());
+ when(jsonReport.getIssues()).thenReturn(Collections.<DefaultIssue> emptyList());
settings.setProperty("sonar.report.export.path", "output.json");
when(fileSystem.workingDir()).thenReturn(sonarDirectory);