From 836c5a30998402fdf4a59f21fcc5ab1daf91eb0d Mon Sep 17 00:00:00 2001
From: DDMili
<130993898+dejan-milisavljevic-sonarsource@users.noreply.github.com>
Date: Thu, 30 May 2024 16:53:11 +0200
Subject: [PATCH] SONAR-22224 live update metric
---
.../container/ComputeEngineContainerImpl.java | 2 +
.../org/sonar/db/issue/IssueGroupDto.java | 10 +++++
.../org/sonar/db/issue/IssueMapper.xml | 3 ++
.../server/metric/IssueCountMetrics.java | 45 +++++++++++++++++++
.../server/metric/IssueCountMetricsTest.java | 34 ++++++++++++++
.../server/measure/live/IssueCounter.java | 7 +++
.../live/MeasureUpdateFormulaFactoryImpl.java | 4 ++
.../MeasureUpdateFormulaFactoryImplTest.java | 7 +++
.../platformlevel/PlatformLevel4.java | 2 +
9 files changed, 114 insertions(+)
create mode 100644 server/sonar-server-common/src/main/java/org/sonar/server/metric/IssueCountMetrics.java
create mode 100644 server/sonar-server-common/src/test/java/org/sonar/server/metric/IssueCountMetricsTest.java
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
index d2a881dc113..ff49a134101 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
@@ -107,6 +107,7 @@ import org.sonar.server.issue.workflow.IssueWorkflow;
import org.sonar.server.l18n.ServerI18n;
import org.sonar.server.log.ServerLogging;
import org.sonar.server.measure.index.ProjectMeasuresIndexer;
+import org.sonar.server.metric.IssueCountMetrics;
import org.sonar.server.metric.UnanalyzedLanguageMetrics;
import org.sonar.server.notification.DefaultNotificationManager;
import org.sonar.server.notification.NotificationService;
@@ -372,6 +373,7 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
// measure
UnanalyzedLanguageMetrics.class,
+ IssueCountMetrics.class,
// components,
FavoriteUpdater.class,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java
index 735711d2983..5aa0e1a9085 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java
@@ -30,6 +30,7 @@ public class IssueGroupDto {
private String status;
private double effort;
private long count;
+ private long prioritizedRule;
private boolean inLeak;
public IssueGroupDto() {
@@ -65,6 +66,10 @@ public class IssueGroupDto {
return inLeak;
}
+ public long getPrioritizedRule() {
+ return prioritizedRule;
+ }
+
public IssueGroupDto setRuleType(int ruleType) {
this.ruleType = ruleType;
return this;
@@ -99,4 +104,9 @@ public class IssueGroupDto {
this.inLeak = inLeak;
return this;
}
+
+ public IssueGroupDto setPrioritizedRule(long prioritizedRule) {
+ this.prioritizedRule = prioritizedRule;
+ return this;
+ }
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
index 0a9a7730ce4..3d70d0aeba2 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
@@ -464,6 +464,7 @@
i.resolution as resolution,
i.status as status, sum(i.effort) as effort,
count(i.issue_type) as "count",
+ sum(case when i.prioritized_rule = true then 1 else 0 end) as prioritizedRule,
(i.issue_creation_date > #{leakPeriodBeginningDate,jdbcType=BIGINT}) as inLeak
@@ -495,6 +496,7 @@
i2.status as status,
sum(i2.effort) as effort,
count(i2.issue_type) as "count",
+ sum(i2.prioritized_rule) as prioritizedRule,
i2.inLeak as inLeak
from (
select
@@ -503,6 +505,7 @@
i.resolution,
i.status,
i.effort,
+ case when prioritized_rule = 1 then 1 else 0 end as prioritized_rule,
case when i.issue_creation_date > #{leakPeriodBeginningDate,jdbcType=BIGINT} then 1 else 0 end as inLeak
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/metric/IssueCountMetrics.java b/server/sonar-server-common/src/main/java/org/sonar/server/metric/IssueCountMetrics.java
new file mode 100644
index 00000000000..1776c05019d
--- /dev/null
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/metric/IssueCountMetrics.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.metric;
+
+import java.util.List;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+
+import static org.sonar.api.measures.CoreMetrics.DOMAIN_ISSUES;
+
+public class IssueCountMetrics implements Metrics {
+
+ public static final String PRIORITIZED_RULE_ISSUES_KEY = "prioritized_rule_issues";
+ public static final Metric PRIORITIZED_RULE_ISSUES = new Metric.Builder(
+ PRIORITIZED_RULE_ISSUES_KEY, "Issues from prioritized rules", Metric.ValueType.INT)
+ .setDescription("Count of issues that have a flag Prioritized Rule.")
+ .setDirection(Metric.DIRECTION_WORST)
+ .setQualitative(true)
+ .setDomain(DOMAIN_ISSUES)
+ .setBestValue(0.0)
+ .setOptimizedBestValue(true)
+ .create();
+
+ @Override
+ public List getMetrics() {
+ return List.of(PRIORITIZED_RULE_ISSUES);
+ }
+}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/metric/IssueCountMetricsTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/metric/IssueCountMetricsTest.java
new file mode 100644
index 00000000000..8d1147e909a
--- /dev/null
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/metric/IssueCountMetricsTest.java
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.metric;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.metric.IssueCountMetrics.PRIORITIZED_RULE_ISSUES;
+
+class IssueCountMetricsTest {
+ @Test
+ void getMetrics() {
+ assertThat(new IssueCountMetrics().getMetrics())
+ .containsExactlyInAnyOrder(PRIORITIZED_RULE_ISSUES);
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueCounter.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueCounter.java
index e2f3840e667..76d7da9d867 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueCounter.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueCounter.java
@@ -47,6 +47,7 @@ class IssueCounter {
private final Map byStatus = new HashMap<>();
private final Map hotspotsByStatus = new HashMap<>();
private final Count unresolved = new Count();
+ private long prioritizedRuleIssues = 0;
private final Count highImpactAccepted = new Count();
private final Map> bySoftwareQualityAndSeverity = new EnumMap<>(SoftwareQuality.class);
@@ -68,6 +69,7 @@ class IssueCounter {
unresolvedByType
.computeIfAbsent(SECURITY_HOTSPOT, k -> new Count())
.add(group);
+ prioritizedRuleIssues += group.getPrioritizedRule();
}
if (group.getStatus() != null) {
hotspotsByStatus
@@ -92,6 +94,7 @@ class IssueCounter {
.computeIfAbsent(ruleType, k -> new Count())
.add(group);
unresolved.add(group);
+ prioritizedRuleIssues += group.getPrioritizedRule();
} else {
byResolution
.computeIfAbsent(group.getResolution(), k -> new Count())
@@ -152,6 +155,10 @@ class IssueCounter {
return value(unresolved, onlyInLeak);
}
+ public long countPrioritizedRuleIssues() {
+ return prioritizedRuleIssues;
+ }
+
public long countHighImpactAccepted(boolean onlyInLeak) {
return value(highImpactAccepted, onlyInLeak);
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImpl.java
index 24c02872a79..61f1b6595f4 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImpl.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImpl.java
@@ -42,6 +42,7 @@ import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
import static org.sonar.server.measure.Rating.RATING_BY_SEVERITY;
+import static org.sonar.server.metric.IssueCountMetrics.PRIORITIZED_RULE_ISSUES;
import static org.sonar.server.security.SecurityReviewRating.computePercent;
import static org.sonar.server.security.SecurityReviewRating.computeRating;
@@ -56,6 +57,9 @@ public class MeasureUpdateFormulaFactoryImpl implements MeasureUpdateFormulaFact
new MeasureUpdateFormula(CoreMetrics.VULNERABILITIES, false, new AddChildren(),
(context, issues) -> context.setValue(issues.countUnresolvedByType(RuleType.VULNERABILITY, false))),
+ new MeasureUpdateFormula(PRIORITIZED_RULE_ISSUES, false, new AddChildren(),
+ (context, issues) -> context.setValue(issues.countPrioritizedRuleIssues())),
+
new MeasureUpdateFormula(CoreMetrics.SECURITY_HOTSPOTS, false, new AddChildren(),
(context, issues) -> context.setValue(issues.countUnresolvedByType(RuleType.SECURITY_HOTSPOT, false))),
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImplTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImplTest.java
index b3ef284a41d..a6f5746718e 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImplTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImplTest.java
@@ -60,6 +60,7 @@ import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING;
+import static org.sonar.server.metric.IssueCountMetrics.PRIORITIZED_RULE_ISSUES;
import static org.sonar.test.JsonAssert.assertJson;
class MeasureUpdateFormulaFactoryImplTest {
@@ -165,6 +166,12 @@ class MeasureUpdateFormulaFactoryImplTest {
with(newGroup(), newGroup(), onLeak).assertThatValueIs(CoreMetrics.VIOLATIONS, 1 + 1 + 11);
}
+ @Test
+ void test_prioritized_rules() {
+ withNoIssues().assertThatValueIs(PRIORITIZED_RULE_ISSUES, 0);
+ with(newGroup().setPrioritizedRule(1), newGroup().setPrioritizedRule(4)).assertThatValueIs(PRIORITIZED_RULE_ISSUES, 5);
+ }
+
@Test
void test_bugs() {
withNoIssues().assertThatValueIs(CoreMetrics.BUGS, 0);
diff --git a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
index 651c3922a9b..8d56e9bac23 100644
--- a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
+++ b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
@@ -154,6 +154,7 @@ import org.sonar.server.management.DelegatingManagedServices;
import org.sonar.server.measure.index.ProjectsEsModule;
import org.sonar.server.measure.live.LiveMeasureModule;
import org.sonar.server.measure.ws.MeasuresWsModule;
+import org.sonar.server.metric.IssueCountMetrics;
import org.sonar.server.metric.UnanalyzedLanguageMetrics;
import org.sonar.server.metric.ws.MetricsWsModule;
import org.sonar.server.monitoring.ComputeEngineMetricStatusTask;
@@ -380,6 +381,7 @@ public class PlatformLevel4 extends PlatformLevel {
new MetricsWsModule(),
new MeasuresWsModule(),
UnanalyzedLanguageMetrics.class,
+ IssueCountMetrics.class,
new QualityGateModule(),
new QualityGateWsModule(),
--
2.39.5