import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_LANGUAGES;
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_MEASURES;
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_NAME;
+import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_NCLOC_LANGUAGE_DISTRIBUTION;
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_ORGANIZATION_UUID;
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_QUALITY_GATE_STATUS;
import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_TAGS;
private static final String FIELD_MEASURES_KEY = FIELD_MEASURES + "." + ProjectMeasuresIndexDefinition.FIELD_MEASURES_KEY;
private static final String FIELD_MEASURES_VALUE = FIELD_MEASURES + "." + ProjectMeasuresIndexDefinition.FIELD_MEASURES_VALUE;
+ private static final String FIELD_DISTRIB_LANGUAGE = FIELD_NCLOC_LANGUAGE_DISTRIBUTION + "." + ProjectMeasuresIndexDefinition.FIELD_DISTRIB_LANGUAGE;
+ private static final String FIELD_DISTRIB_NCLOC = FIELD_NCLOC_LANGUAGE_DISTRIBUTION + "." + ProjectMeasuresIndexDefinition.FIELD_DISTRIB_NCLOC;
private static final Map<String, FacetSetter> FACET_FACTORIES = ImmutableMap.<String, FacetSetter>builder()
.put(NCLOC_KEY, (esSearch, query, facetBuilder) -> addRangeFacet(esSearch, NCLOC_KEY, facetBuilder, LINES_THRESHOLDS))
.size(MAX_PAGE_SIZE)
.minDocCount(1)
.order(Terms.Order.count(false)));
+ request.addAggregation(AggregationBuilders.nested(FIELD_NCLOC_LANGUAGE_DISTRIBUTION, FIELD_NCLOC_LANGUAGE_DISTRIBUTION)
+ .subAggregation(AggregationBuilders.terms(FIELD_NCLOC_LANGUAGE_DISTRIBUTION + "_terms")
+ .field(FIELD_DISTRIB_LANGUAGE)
+ .size(MAX_PAGE_SIZE)
+ .minDocCount(1)
+ .order(Terms.Order.count(false))
+ .subAggregation(sum(FIELD_DISTRIB_NCLOC).field(FIELD_DISTRIB_NCLOC))));
+
Stream.of(LINES_KEY, NCLOC_KEY)
.forEach(metric -> request.addAggregation(AggregationBuilders.nested(metric, FIELD_MEASURES)
.subAggregation(AggregationBuilders.filter(metric + "_filter", termQuery(FIELD_MEASURES_KEY, metric))
long value = Math.round(sum.getValue());
statistics.setSum(metric, value);
});
- statistics.setProjectLanguageDistribution(termsToMap(response.getAggregations().get(FIELD_LANGUAGES)));
+ statistics.setProjectCountByLanguage(termsToMap(response.getAggregations().get(FIELD_LANGUAGES)));
+ Function<Terms.Bucket, Long> bucketToNcloc = bucket -> Math.round(((Sum) bucket.getAggregations().get(FIELD_DISTRIB_NCLOC)).getValue());
+ Map<String, Long> nclocByLanguage = Stream.of((Nested) response.getAggregations().get(FIELD_NCLOC_LANGUAGE_DISTRIBUTION))
+ .map(nested -> (Terms) nested.getAggregations().get(nested.getName() + "_terms"))
+ .flatMap(terms -> terms.getBuckets().stream())
+ .collect(MoreCollectors.uniqueIndex(Bucket::getKeyAsString, bucketToNcloc));
+ statistics.setNclocByLanguage(nclocByLanguage);
return statistics.build();
}
private final long projectCount;
private final long lines;
private final long ncloc;
- private final Map<String, Long> projectLanguageDistribution;
+ private final Map<String, Long> projectCountByLanguage;
+ private final Map<String, Long> nclocByLanguage;
private ProjectMeasuresStatistics(Builder builder) {
projectCount = builder.projectCount;
lines = builder.lines;
ncloc = builder.ncloc;
- projectLanguageDistribution = builder.projectLanguageDistribution;
+ projectCountByLanguage = builder.projectCountByLanguage;
+ nclocByLanguage = builder.nclocByLanguage;
}
public long getProjectCount() {
return ncloc;
}
- public Map<String, Long> getProjectLanguageDistribution() {
- return projectLanguageDistribution;
+ public Map<String, Long> getProjectCountByLanguage() {
+ return projectCountByLanguage;
+ }
+
+ public Map<String, Long> getNclocByLanguage() {
+ return nclocByLanguage;
}
public static Builder builder() {
}
public static class Builder {
- private Map<String, Long> projectLanguageDistribution;
private Long projectCount;
private Long lines;
private Long ncloc;
+ private Map<String, Long> projectCountByLanguage;
+ private Map<String, Long> nclocByLanguage;
private Builder() {
// enforce static factory method
return this;
}
- public void setProjectLanguageDistribution(Map<String, Long> projectLanguageDistribution) {
- this.projectLanguageDistribution = projectLanguageDistribution;
+ public void setProjectCountByLanguage(Map<String, Long> projectCountByLanguage) {
+ this.projectCountByLanguage = projectCountByLanguage;
+ }
+
+ public Builder setNclocByLanguage(Map<String, Long> nclocByLanguage) {
+ this.nclocByLanguage = nclocByLanguage;
+ return this;
}
public ProjectMeasuresStatistics build() {
requireNonNull(projectCount);
requireNonNull(lines);
requireNonNull(ncloc);
- requireNonNull(projectLanguageDistribution);
+ requireNonNull(projectCountByLanguage);
+ requireNonNull(nclocByLanguage);
return new ProjectMeasuresStatistics(this);
}
}
writer.prop(LINES_KEY, statistics.getLines());
writer.prop(NCLOC_KEY, statistics.getNcloc());
writer.name("projectLanguageDistribution");
- writer.valueObject(statistics.getProjectLanguageDistribution());
+ writer.valueObject(statistics.getProjectCountByLanguage());
writer.endObject();
}
telemetryClient.upload(json.toString());
@Test
public void search_statistics() {
es.putDocuments(INDEX_TYPE_PROJECT_MEASURES,
- newDoc("lines", 10, "ncloc", 20, "coverage", 80).setLanguages(Arrays.asList("java", "cs", "js")),
- newDoc("lines", 20, "ncloc", 30, "coverage", 80).setLanguages(Arrays.asList("java", "python", "kotlin")));
+ newDoc("lines", 10, "ncloc", 20, "coverage", 80)
+ .setLanguages(Arrays.asList("java", "cs", "js"))
+ .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 200, "cs", 250, "js", 50)),
+ newDoc("lines", 20, "ncloc", 30, "coverage", 80)
+ .setLanguages(Arrays.asList("java", "python", "kotlin"))
+ .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404)));
ProjectMeasuresStatistics result = underTest.searchTelemetryStatistics();
assertThat(result.getProjectCount()).isEqualTo(2);
assertThat(result.getLines()).isEqualTo(30);
assertThat(result.getNcloc()).isEqualTo(50);
- assertThat(result.getProjectLanguageDistribution()).containsOnly(
+ assertThat(result.getProjectCountByLanguage()).containsOnly(
entry("java", 2L), entry("cs", 1L), entry("js", 1L), entry("python", 1L), entry("kotlin", 1L));
+ assertThat(result.getNclocByLanguage()).containsOnly(
+ entry("java", 500L), entry("cs", 250L), entry("js", 50L), entry("python", 100L), entry("kotlin", 404L));
}
@Test