diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-10-21 13:00:00 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-10-24 12:02:33 +0200 |
commit | 1a64babff4c22cb4e412fd86b6fdb802e9c9983d (patch) | |
tree | 3bc670c8e3564e28dbc8b94ec555d9f1b1620b28 | |
parent | a0cfbf2ec2c6d6313b532df054dad8feaad3442f (diff) | |
download | sonarqube-1a64babff4c22cb4e412fd86b6fdb802e9c9983d.tar.gz sonarqube-1a64babff4c22cb4e412fd86b6fdb802e9c9983d.zip |
SONAR-8221 Fix project measures indexing on MySQL
Replace streaming of projects by first loading all projects once, then load measures project by project
-rw-r--r-- | server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresDoc.java | 4 | ||||
-rw-r--r-- | server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndexer.java | 38 | ||||
-rw-r--r-- | sonar-db/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java (renamed from server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresResultSetIterator.java) | 231 | ||||
-rw-r--r-- | sonar-db/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresResultSetIteratorTest.java) | 95 | ||||
-rw-r--r-- | sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java | 4 |
5 files changed, 235 insertions, 137 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresDoc.java b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresDoc.java index 67f0590af77..357c2719389 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresDoc.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresDoc.java @@ -94,10 +94,10 @@ public class ProjectMeasuresDoc extends BaseDoc { return this; } - public ProjectMeasuresDoc setMeasuresFromMap(Map<String, Object> measures) { + public ProjectMeasuresDoc setMeasuresFromMap(Map<String, Double> measures) { setMeasures( measures.entrySet().stream() - .map(entry -> ImmutableMap.of( + .map(entry -> ImmutableMap.<String, Object>of( ProjectMeasuresIndexDefinition.FIELD_MEASURES_KEY, entry.getKey(), ProjectMeasuresIndexDefinition.FIELD_MEASURES_VALUE, entry.getValue())) .collect(Collectors.toList())); diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndexer.java index 59da24cedfd..a7b32d9cccf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresIndexer.java @@ -26,6 +26,8 @@ import javax.annotation.Nullable; import org.elasticsearch.action.index.IndexRequest; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.measure.ProjectMeasuresIndexerIterator; +import org.sonar.db.measure.ProjectMeasuresIndexerIterator.ProjectMeasures; import org.sonar.server.es.BaseIndexer; import org.sonar.server.es.BulkIndexer; import org.sonar.server.es.EsClient; @@ -67,24 +69,22 @@ public class ProjectMeasuresIndexer extends BaseIndexer { } private long doIndex(BulkIndexer bulk, long lastUpdatedAt, @Nullable String projectUuid) { - try (DbSession dbSession = dbClient.openSession(false)) { - ProjectMeasuresResultSetIterator rowIt = ProjectMeasuresResultSetIterator.create(dbClient, dbSession, lastUpdatedAt, projectUuid); - long maxDate = doIndex(bulk, rowIt); - rowIt.close(); - return maxDate; + try (DbSession dbSession = dbClient.openSession(false); + ProjectMeasuresIndexerIterator rowIt = ProjectMeasuresIndexerIterator.create(dbSession, lastUpdatedAt, projectUuid)) { + return doIndex(bulk, rowIt); } } - private static long doIndex(BulkIndexer bulk, Iterator<ProjectMeasuresDoc> docs) { + private static long doIndex(BulkIndexer bulk, Iterator<ProjectMeasures> docs) { bulk.start(); long maxDate = 0L; while (docs.hasNext()) { - ProjectMeasuresDoc doc = docs.next(); - bulk.add(newIndexRequest(doc)); + ProjectMeasures doc = docs.next(); + bulk.add(newIndexRequest(toProjectMeasuresDoc(doc))); - Date analysisDate = doc.getAnalysedAt(); + Long analysisDate = doc.getProject().getAnalysisDate(); // it's more efficient to sort programmatically than in SQL on some databases (MySQL for instance) - maxDate = Math.max(maxDate, analysisDate == null ? 0L : analysisDate.getTime()); + maxDate = Math.max(maxDate, analysisDate == null ? 0L : analysisDate); } bulk.stop(); return maxDate; @@ -97,9 +97,21 @@ public class ProjectMeasuresIndexer extends BaseIndexer { } private static IndexRequest newIndexRequest(ProjectMeasuresDoc doc) { - return new IndexRequest(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES, doc.getId()) - .routing(doc.getId()) - .parent(doc.getId()) + String projectUuid = doc.getId(); + return new IndexRequest(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES, projectUuid) + .routing(projectUuid) + .parent(projectUuid) .source(doc.getFields()); } + + private static ProjectMeasuresDoc toProjectMeasuresDoc(ProjectMeasures projectMeasures) { + Long analysisDate = projectMeasures.getProject().getAnalysisDate(); + return new ProjectMeasuresDoc() + .setId(projectMeasures.getProject().getUuid()) + .setKey(projectMeasures.getProject().getKey()) + .setName(projectMeasures.getProject().getName()) + .setQualityGate(projectMeasures.getMeasures().getQualityGateStatus()) + .setAnalysedAt(analysisDate == null ? null : new Date(analysisDate)) + .setMeasuresFromMap(projectMeasures.getMeasures().getNumericMeasures()); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresResultSetIterator.java b/sonar-db/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java index adffa8f9429..b61b3850826 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/es/ProjectMeasuresResultSetIterator.java +++ b/sonar-db/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java @@ -18,31 +18,44 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.component.es; +package org.sonar.db.measure; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Date; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; -import org.sonar.db.DbClient; +import org.sonar.core.util.CloseableIterator; +import org.sonar.db.DatabaseUtils; import org.sonar.db.DbSession; -import org.sonar.db.ResultSetIterator; import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; -import static org.sonar.api.measures.Metric.ValueType.DATA; -import static org.sonar.api.measures.Metric.ValueType.DISTRIB; +import static org.sonar.api.measures.Metric.ValueType.BOOL; +import static org.sonar.api.measures.Metric.ValueType.FLOAT; +import static org.sonar.api.measures.Metric.ValueType.INT; +import static org.sonar.api.measures.Metric.ValueType.LEVEL; +import static org.sonar.api.measures.Metric.ValueType.MILLISEC; +import static org.sonar.api.measures.Metric.ValueType.PERCENT; +import static org.sonar.api.measures.Metric.ValueType.RATING; +import static org.sonar.api.measures.Metric.ValueType.WORK_DUR; import static org.sonar.db.DatabaseUtils.repeatCondition; -public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectMeasuresDoc> { +public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMeasuresIndexerIterator.ProjectMeasures> { + + private static final Set<String> METRIC_TYPES = ImmutableSet.of(INT.name(), FLOAT.name(), PERCENT.name(), BOOL.name(), MILLISEC.name(), LEVEL.name(), RATING.name(), + WORK_DUR.name()); private static final Joiner METRICS_JOINER = Joiner.on("','"); @@ -55,8 +68,8 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM private static final String PROJECT_FILTER = " AND p.uuid=?"; private static final String SQL_METRICS = "SELECT m.id, m.name FROM metrics m " + - "WHERE m.val_type NOT IN ('" + METRICS_JOINER.join(DATA.name(), DISTRIB.name()) + "') " + - "AND m.enabled=? AND m.hidden=?"; + "WHERE m.val_type IN ('" + METRICS_JOINER.join(METRIC_TYPES) + "') " + + "AND m.enabled=?"; private static final String SQL_MEASURES = "SELECT pm.metric_id, pm.value, pm.variation_value_1, pm.text_value FROM project_measures pm " + "WHERE pm.component_uuid = ? AND pm.analysis_uuid = ? " + @@ -64,31 +77,67 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM "AND (pm.value IS NOT NULL OR pm.variation_value_1 IS NOT NULL OR pm.text_value IS NOT NULL) " + "AND pm.person_id IS NULL "; - private final DbSession dbSession; - private final Map<Long, String> metrics; + private final PreparedStatement measuresStatement; + private final Map<Long, String> metricKeysByIds; + private final Iterator<Project> projects; - private ProjectMeasuresResultSetIterator(PreparedStatement stmt, DbSession dbSession, Map<Long, String> metrics) throws SQLException { - super(stmt); - this.dbSession = dbSession; - this.metrics = metrics; + private ProjectMeasuresIndexerIterator(PreparedStatement measuresStatement, Map<Long, String> metricKeysByIds, List<Project> projects) throws SQLException { + this.measuresStatement = measuresStatement; + this.metricKeysByIds = metricKeysByIds; + this.projects = projects.iterator(); } - static ProjectMeasuresResultSetIterator create(DbClient dbClient, DbSession session, long afterDate, @Nullable String projectUuid) { + public static ProjectMeasuresIndexerIterator create(DbSession session, long afterDate, @Nullable String projectUuid) { try { - PreparedStatement projectsStatement = createProjectsStatement(dbClient, session, afterDate, projectUuid); - Map<Long, String> metricIds = selectMetricIds(session); - return new ProjectMeasuresResultSetIterator(projectsStatement, session, metricIds); + Map<Long, String> metrics = selectMetricKeysByIds(session); + List<Project> projects = selectProjects(session, afterDate, projectUuid); + PreparedStatement projectsStatement = createMeasuresStatement(session, metrics.keySet()); + return new ProjectMeasuresIndexerIterator(projectsStatement, metrics, projects); } catch (SQLException e) { throw new IllegalStateException("Fail to execute request to select all project measures", e); } } - private static PreparedStatement createProjectsStatement(DbClient dbClient, DbSession session, long afterDate, @Nullable String projectUuid) { + private static Map<Long, String> selectMetricKeysByIds(DbSession session) { + Map<Long, String> metrics = new HashMap<>(); + try (PreparedStatement stmt = createMetricsStatement(session); + ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + metrics.put(rs.getLong(1), rs.getString(2)); + } + return metrics; + } catch (SQLException e) { + throw new IllegalStateException("Fail to execute request to select all metrics", e); + } + } + + private static PreparedStatement createMetricsStatement(DbSession session) throws SQLException { + PreparedStatement stmt = session.getConnection().prepareStatement(SQL_METRICS); + stmt.setBoolean(1, true); + return stmt; + } + + private static List<Project> selectProjects(DbSession session, long afterDate, @Nullable String projectUuid) { + List<Project> projects = new ArrayList<>(); + try (PreparedStatement stmt = createProjectsStatement(session, afterDate, projectUuid); + ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + long analysisDate = rs.getLong(5); + Project project = new Project(rs.getString(1), rs.getString(2), rs.getString(3), getString(rs, 4).orElseGet(() -> null), rs.wasNull() ? null : analysisDate); + projects.add(project); + } + return projects; + } catch (SQLException e) { + throw new IllegalStateException("Fail to execute request to select all projects", e); + } + } + + private static PreparedStatement createProjectsStatement(DbSession session, long afterDate, @Nullable String projectUuid) { try { String sql = SQL_PROJECTS; sql += afterDate <= 0L ? "" : DATE_FILTER; sql += projectUuid == null ? "" : PROJECT_FILTER; - PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql); + PreparedStatement stmt = session.getConnection().prepareStatement(sql); stmt.setBoolean(1, true); stmt.setBoolean(2, true); stmt.setString(3, Scopes.PROJECT); @@ -107,59 +156,55 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM } } - private static Map<Long, String> selectMetricIds(DbSession session) { - Map<Long, String> metrics = new HashMap<>(); - try (PreparedStatement stmt = createMetricsStatement(session); - ResultSet rs = stmt.executeQuery()) { - while (rs.next()) { - metrics.put(rs.getLong(1), rs.getString(2)); + private static PreparedStatement createMeasuresStatement(DbSession session, Set<Long> metricIds) throws SQLException { + try { + String sql = StringUtils.replace(SQL_MEASURES, "{metricIds}", repeatCondition("?", metricIds.size(), ",")); + PreparedStatement stmt = session.getConnection().prepareStatement(sql); + int index = 3; + for (Long metricId : metricIds) { + stmt.setLong(index, metricId); + index++; } - return metrics; + return stmt; } catch (SQLException e) { - throw new IllegalStateException("Fail to execute request to select all metrics", e); + throw new IllegalStateException("Fail to prepare SQL request to select measures", e); } } - private static PreparedStatement createMetricsStatement(DbSession session) throws SQLException { - PreparedStatement stmt = session.getConnection().prepareStatement(SQL_METRICS); - stmt.setBoolean(1, true); - stmt.setBoolean(2, false); - return stmt; + @Override + @CheckForNull + protected ProjectMeasures doNext() { + if (!projects.hasNext()) { + return null; + } + Project project = projects.next(); + Measures measures = selectMeasures(project.getUuid(), project.getAnalysisUuid()); + return new ProjectMeasures(project, measures); } - @Override - protected ProjectMeasuresDoc read(ResultSet rs) throws SQLException { - String projectUuid = rs.getString(1); - Measures measures = selectMeasures(projectUuid, getString(rs, 4)); - ProjectMeasuresDoc doc = new ProjectMeasuresDoc() - .setId(projectUuid) - .setKey(rs.getString(2)) - .setName(rs.getString(3)) - .setQualityGate(measures.getQualityGateStatus()) - .setMeasuresFromMap(measures.getNumericMeasures()); - long analysisDate = rs.getLong(5); - doc.setAnalysedAt(rs.wasNull() ? null : new Date(analysisDate)); - return doc; - } - - private Measures selectMeasures(String projectUuid, Optional<String> analysisUuid) { + private Measures selectMeasures(String projectUuid, @Nullable String analysisUuid) { Measures measures = new Measures(); - if (!analysisUuid.isPresent()) { + if (analysisUuid == null || metricKeysByIds.isEmpty()) { return measures; } - try (PreparedStatement stmt = createMeasuresStatement(projectUuid, analysisUuid.get()); - ResultSet rs = stmt.executeQuery()) { + ResultSet rs = null; + try { + measuresStatement.setString(1, projectUuid); + measuresStatement.setString(2, analysisUuid); + rs = measuresStatement.executeQuery(); while (rs.next()) { readMeasure(rs, measures); } return measures; } catch (Exception e) { throw new IllegalStateException(String.format("Fail to execute request to select measures of project %s, analysis %s", projectUuid, analysisUuid), e); + } finally { + DatabaseUtils.closeQuietly(rs); } } private void readMeasure(ResultSet rs, Measures measures) throws SQLException { - String metricKey = metrics.get(rs.getLong(1)); + String metricKey = metricKeysByIds.get(rs.getLong(1)); Optional<Double> value = metricKey.startsWith("new_") ? getDouble(rs, 3) : getDouble(rs, 2); if (value.isPresent()) { measures.addNumericMeasure(metricKey, value.get()); @@ -174,17 +219,9 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM throw new IllegalArgumentException("Measure has no value"); } - private PreparedStatement createMeasuresStatement(String projectUuid, String analysisUuid) throws SQLException { - String sql = StringUtils.replace(SQL_MEASURES, "{metricIds}", repeatCondition("?", metrics.size(), ",")); - PreparedStatement stmt = dbSession.getConnection().prepareStatement(sql); - stmt.setString(1, projectUuid); - stmt.setString(2, analysisUuid); - int index = 3; - for (Long metricId : metrics.keySet()) { - stmt.setLong(index, metricId); - index++; - } - return stmt; + @Override + protected void doClose() throws Exception { + measuresStatement.close(); } private static Optional<Double> getDouble(ResultSet rs, int index) { @@ -211,8 +248,47 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM } } - private static class Measures { - private Map<String, Object> numericMeasures = new HashMap<>(); + public static class Project { + private final String uuid; + private final String key; + private final String name; + private final String analysisUuid; + private final Long analysisDate; + + public Project(String uuid, String key, String name, @Nullable String analysisUuid, @Nullable Long analysisDate) { + this.uuid = uuid; + this.key = key; + this.name = name; + this.analysisUuid = analysisUuid; + this.analysisDate = analysisDate; + } + + public String getUuid() { + return uuid; + } + + public String getKey() { + return key; + } + + public String getName() { + return name; + } + + @CheckForNull + public String getAnalysisUuid() { + return analysisUuid; + } + + @CheckForNull + public Long getAnalysisDate() { + return analysisDate; + } + } + + public static class Measures { + + private Map<String, Double> numericMeasures = new HashMap<>(); private String qualityGateStatus; Measures addNumericMeasure(String metricKey, double value) { @@ -220,7 +296,7 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM return this; } - public Map<String, Object> getNumericMeasures() { + public Map<String, Double> getNumericMeasures() { return numericMeasures; } @@ -235,4 +311,23 @@ public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectM } } + public static class ProjectMeasures { + private Project project; + private Measures measures; + + public ProjectMeasures(Project project, Measures measures) { + this.project = project; + this.measures = measures; + } + + public Project getProject() { + return project; + } + + public Measures getMeasures() { + return measures; + } + + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresResultSetIteratorTest.java b/sonar-db/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java index 09086ad2a30..69763cf453e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/es/ProjectMeasuresResultSetIteratorTest.java +++ b/sonar-db/src/test/java/org/sonar/db/measure/ProjectMeasuresIndexerIteratorTest.java @@ -18,11 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.component.es; +package org.sonar.db.measure; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; -import java.util.Date; import java.util.Map; import javax.annotation.Nullable; import org.junit.Rule; @@ -36,23 +34,24 @@ import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; -import org.sonar.db.measure.MeasureDto; -import org.sonar.db.measure.MeasureTesting; +import org.sonar.db.measure.ProjectMeasuresIndexerIterator.ProjectMeasures; import org.sonar.db.metric.MetricDto; import org.sonar.db.metric.MetricTesting; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; +import static org.sonar.api.measures.Metric.Level.WARN; import static org.sonar.api.measures.Metric.ValueType.DATA; import static org.sonar.api.measures.Metric.ValueType.DISTRIB; import static org.sonar.api.measures.Metric.ValueType.INT; import static org.sonar.api.measures.Metric.ValueType.LEVEL; +import static org.sonar.api.measures.Metric.ValueType.STRING; import static org.sonar.db.component.ComponentTesting.newDeveloper; import static org.sonar.db.component.ComponentTesting.newProjectDto; import static org.sonar.db.component.ComponentTesting.newView; import static org.sonar.db.component.SnapshotTesting.newAnalysis; -import static org.sonar.server.computation.task.projectanalysis.measure.Measure.Level.WARN; -public class ProjectMeasuresResultSetIteratorTest { +public class ProjectMeasuresIndexerIteratorTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -74,18 +73,16 @@ public class ProjectMeasuresResultSetIteratorTest { insertMeasure(project, analysis, metric1, 10d); insertMeasure(project, analysis, metric2, 20d); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(); assertThat(docsById).hasSize(1); - ProjectMeasuresDoc doc = docsById.get(project.uuid()); + ProjectMeasures doc = docsById.get(project.uuid()); assertThat(doc).isNotNull(); - assertThat(doc.getId()).isEqualTo(project.uuid()); - assertThat(doc.getKey()).isEqualTo("Project-Key"); - assertThat(doc.getName()).isEqualTo("Project Name"); - assertThat(doc.getAnalysedAt()).isNotNull().isEqualTo(new Date(analysis.getCreatedAt())); - assertThat(doc.getMeasures()).containsOnly( - ImmutableMap.of("key", "ncloc", "value", 10d), - ImmutableMap.of("key", "coverage", "value", 20d)); + assertThat(doc.getProject().getUuid()).isEqualTo(project.uuid()); + assertThat(doc.getProject().getKey()).isEqualTo("Project-Key"); + assertThat(doc.getProject().getName()).isEqualTo("Project Name"); + assertThat(doc.getProject().getAnalysisDate()).isNotNull().isEqualTo(analysis.getCreatedAt()); + assertThat(doc.getMeasures().getNumericMeasures()).containsOnly(entry("ncloc", 10d), entry("coverage", 20d)); } @Test @@ -95,12 +92,9 @@ public class ProjectMeasuresResultSetIteratorTest { SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project); insertMeasureOnLeak(project, analysis, metric, 10d); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(); - assertThat(docsById).hasSize(1); - ProjectMeasuresDoc doc = docsById.get(project.uuid()); - assertThat(doc).isNotNull(); - assertThat(doc.getMeasures()).containsOnly(ImmutableMap.of("key", "new_lines", "value", 10d)); + assertThat(docsById.get(project.uuid()).getMeasures().getNumericMeasures()).containsOnly(entry("new_lines", 10d)); } @Test @@ -110,40 +104,37 @@ public class ProjectMeasuresResultSetIteratorTest { SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project); insertMeasure(project, analysis, metric, WARN.name()); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(); - assertThat(docsById).hasSize(1); - assertThat(docsById.get(project.uuid()).getQualityGate()).isEqualTo("WARN"); + assertThat(docsById.get(project.uuid()).getMeasures().getQualityGateStatus()).isEqualTo("WARN"); } @Test public void does_not_return_none_numeric_metrics() throws Exception { MetricDto dataMetric = insertMetric("data", DATA); MetricDto distribMetric = insertMetric("distrib", DISTRIB); + MetricDto stringMetric = insertMetric("string", STRING); ComponentDto project = newProjectDto(); SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project); - insertMeasure(project, analysis, dataMetric, 10d); - insertMeasure(project, analysis, distribMetric, 10d); + insertMeasure(project, analysis, dataMetric, "dat"); + insertMeasure(project, analysis, distribMetric, "dis"); + insertMeasure(project, analysis, stringMetric, "str"); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(); - assertThat(docsById).hasSize(1); - ProjectMeasuresDoc doc = docsById.get(project.uuid()); - assertThat(doc.getMeasures()).isEmpty(); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(); + + assertThat(docsById.get(project.uuid()).getMeasures().getNumericMeasures()).isEmpty(); } @Test - public void does_not_return_disabled_and_hidden_metrics() throws Exception { + public void does_not_return_disabled_metrics() throws Exception { MetricDto disabledMetric = insertMetric("disabled", false, false, INT); - MetricDto hiddenMetric = insertMetric("hidden", true, true, INT); ComponentDto project = newProjectDto(); SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project); insertMeasure(project, analysis, disabledMetric, 10d); - insertMeasure(project, analysis, hiddenMetric, 10d); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(); - assertThat(docsById).hasSize(1); - ProjectMeasuresDoc doc = docsById.get(project.uuid()); - assertThat(doc.getMeasures()).isEmpty(); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(); + + assertThat(docsById.get(project.uuid()).getMeasures().getNumericMeasures()).isEmpty(); } @Test @@ -172,11 +163,11 @@ public class ProjectMeasuresResultSetIteratorTest { dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setLast(false)); dbSession.commit(); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(); assertThat(docsById).hasSize(1); - ProjectMeasuresDoc doc = docsById.get(project.uuid()); - assertThat(doc.getAnalysedAt()).isNull(); + ProjectMeasures doc = docsById.get(project.uuid()); + assertThat(doc.getProject().getAnalysisDate()).isNull(); } @Test @@ -205,15 +196,15 @@ public class ProjectMeasuresResultSetIteratorTest { componentDbTester.insertProjectAndSnapshot(newProjectDto()); componentDbTester.insertProjectAndSnapshot(newProjectDto()); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(0L, project.uuid()); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(0L, project.uuid()); assertThat(docsById).hasSize(1); - ProjectMeasuresDoc doc = docsById.get(project.uuid()); + ProjectMeasures doc = docsById.get(project.uuid()); assertThat(doc).isNotNull(); - assertThat(doc.getId()).isEqualTo(project.uuid()); - assertThat(doc.getKey()).isNotNull().isEqualTo(project.getKey()); - assertThat(doc.getName()).isNotNull().isEqualTo(project.name()); - assertThat(doc.getAnalysedAt()).isNotNull().isEqualTo(new Date(analysis.getCreatedAt())); + assertThat(doc.getProject().getUuid()).isEqualTo(project.uuid()); + assertThat(doc.getProject().getKey()).isNotNull().isEqualTo(project.getKey()); + assertThat(doc.getProject().getName()).isNotNull().isEqualTo(project.name()); + assertThat(doc.getProject().getAnalysisDate()).isNotNull().isEqualTo(analysis.getCreatedAt()); } @Test @@ -226,7 +217,7 @@ public class ProjectMeasuresResultSetIteratorTest { dbClient.snapshotDao().insert(dbSession, newAnalysis(project2).setCreatedAt(2_000_000L)); dbSession.commit(); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(1_500_000L, null); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(1_500_000L, null); assertThat(docsById).hasSize(1); assertThat(docsById.get(project2.uuid())).isNotNull(); @@ -236,18 +227,18 @@ public class ProjectMeasuresResultSetIteratorTest { public void return_nothing_on_unknown_project() throws Exception { componentDbTester.insertProjectAndSnapshot(newProjectDto()); - Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(0L, "UNKNOWN"); + Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(0L, "UNKNOWN"); assertThat(docsById).isEmpty(); } - private Map<String, ProjectMeasuresDoc> createResultSetAndReturnDocsById() { + private Map<String, ProjectMeasures> createResultSetAndReturnDocsById() { return createResultSetAndReturnDocsById(0L, null); } - private Map<String, ProjectMeasuresDoc> createResultSetAndReturnDocsById(long date, @Nullable String projectUuid) { - ProjectMeasuresResultSetIterator it = ProjectMeasuresResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), date, projectUuid); - Map<String, ProjectMeasuresDoc> docsById = Maps.uniqueIndex(it, ProjectMeasuresDoc::getId); + private Map<String, ProjectMeasures> createResultSetAndReturnDocsById(long date, @Nullable String projectUuid) { + ProjectMeasuresIndexerIterator it = ProjectMeasuresIndexerIterator.create(dbTester.getSession(), date, projectUuid); + Map<String, ProjectMeasures> docsById = Maps.uniqueIndex(it, pm -> pm.getProject().getUuid()); it.close(); return docsById; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java index 425777eada6..2fdfbff01f2 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java @@ -29,8 +29,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; -import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.InstantiationStrategy; +import org.sonar.api.batch.ScannerSide; import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; @@ -223,7 +223,7 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a * @param userManaged whether the metric is user managed */ private Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, @Nullable String domain, - boolean userManaged) { + boolean userManaged) { this.key = key; this.description = description; this.type = type; |