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