Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.mathan.sonar.dependencyupdates.Metrics Maven / Gradle / Ivy
/*
* mathan-dependency-updates-sonar-plugin
* Copyright (c) 2019 Matthias Hanisch
* [email protected]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.mathan.sonar.dependencyupdates;
import io.mathan.sonar.dependencyupdates.parser.Analysis;
import io.mathan.sonar.dependencyupdates.parser.Dependency;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.Range;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.config.Configuration;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metric.ValueType;
public final class Metrics implements org.sonar.api.measures.Metrics {
private static final String DOMAIN = "Dependency Updates";
static final String KEY_DEPENDENCIES = "metrics.dependencies";
static final String KEY_DEPENDENCIES_DATA = "metrics.dependencies.data";
static final String KEY_PATCHES = "metrics.patches";
static final String KEY_PATCHES_DATA = "metrics.patches.data";
static final String KEY_PATCHES_RATIO = "metrics.patches.ratio";
static final String KEY_PATCHES_MISSED = "metrics.patches.repeatedly";
static final String KEY_PATCHES_RATING = "metrios.patches.rating";
static final String KEY_UPGRADES = "metrics.upgrades";
static final String KEY_UPGRADES_DATA = "metrics.upgrades.data";
static final String KEY_UPGRADES_RATIO = "metrics.upgrades.ratio";
static final String KEY_UPGRADES_MISSED = "metrics.upgrades.repeatedly";
static final String KEY_UPGRADES_RATING = "metrios.upgrades.rating";
private static final int RATING_A = 1;
private static final int RATING_B = 2;
private static final int RATING_C = 3;
private static final int RATING_D = 4;
private static final int RATING_E = 5;
private static Map, Map, Integer>> mapping = new HashMap<>();
static {
Range range = Range.between(0, 10);
Map, Integer> ratings = new HashMap<>();
ratings.put(Range.between(0, 0), RATING_A);
ratings.put(Range.between(1, 1), RATING_B);
ratings.put(Range.between(2, 2), RATING_C);
ratings.put(Range.between(3, 5), RATING_D);
ratings.put(Range.between(6, 10), RATING_E);
mapping.put(range, ratings);
range = Range.between(11, 20);
ratings = new HashMap<>();
ratings.put(Range.between(0, 1), RATING_A);
ratings.put(Range.between(2, 3), RATING_B);
ratings.put(Range.between(4, 5), RATING_C);
ratings.put(Range.between(6, 10), RATING_D);
ratings.put(Range.between(11, 20), RATING_E);
mapping.put(range, ratings);
range = Range.between(21, 50);
ratings = new HashMap<>();
ratings.put(Range.between(0, 2), RATING_A);
ratings.put(Range.between(3, 5), RATING_B);
ratings.put(Range.between(6, 10), RATING_C);
ratings.put(Range.between(11, 25), RATING_D);
ratings.put(Range.between(26, 50), RATING_E);
mapping.put(range, ratings);
range = Range.between(51, Integer.MAX_VALUE);
ratings = new HashMap<>();
ratings.put(Range.between(0, 5), RATING_A);
ratings.put(Range.between(6, 10), RATING_B);
ratings.put(Range.between(11, 20), RATING_C);
ratings.put(Range.between(21, 50), RATING_D);
ratings.put(Range.between(51, Integer.MAX_VALUE), RATING_E);
mapping.put(range, ratings);
}
private static final Metric DEPENDENCIES = new Metric.Builder(Metrics.KEY_DEPENDENCIES, "Dependencies total", ValueType.INT)
.setDescription("Total number of dependencies")
.setDirection(Metric.DIRECTION_NONE)
.setQualitative(Boolean.FALSE)
.setDomain(Metrics.DOMAIN)
.setHidden(false)
.create();
private static final Metric DEPENDENCIES_DATA = new Metric.Builder(Metrics.KEY_DEPENDENCIES_DATA, "List of dependencies", ValueType.STRING)
.setDescription("All dependencies concatenated in a list")
.setDirection(Metric.DIRECTION_NONE)
.setQualitative(false)
.setDomain(Metrics.DOMAIN)
.setHidden(true)
.create();
private static final Metric PATCHES = new Metric.Builder(Metrics.KEY_PATCHES, "Dependencies to patch", ValueType.INT)
.setDescription("Dependencies with patches to apply")
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setBestValue(0.0)
.create();
private static final Metric PATCHES_DATA = new Metric.Builder(Metrics.KEY_PATCHES_DATA, "List of patches", ValueType.STRING)
.setDescription("All dependencies to patch concatenated in a list")
.setDirection(Metric.DIRECTION_NONE)
.setQualitative(false)
.setDomain(Metrics.DOMAIN)
.setHidden(true)
.create();
private static final Metric PATCHES_RATIO = new Metric.Builder(Metrics.KEY_PATCHES_RATIO, "Dependencies to patch (Ratio)", ValueType.PERCENT)
.setDescription("Ratio of dependencies with patches")
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setBestValue(0.0)
.create();
private static final Metric PATCHES_MISSED = new Metric.Builder(Metrics.KEY_PATCHES_MISSED, "Patches missed", ValueType.INT)
.setDescription("Total number of releases patches missed")
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setBestValue(0.0)
.create();
private static final Metric UPGRADES = new Metric.Builder(Metrics.KEY_UPGRADES, "Dependencies to upgrade", ValueType.INT)
.setDescription("Dependencies with upgrades to apply")
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setBestValue(0.0)
.create();
private static final Metric UPGRADES_DATA = new Metric.Builder(Metrics.KEY_UPGRADES_DATA, "List of upgrades", ValueType.STRING)
.setDescription("All dependencies to upgrade concatenated in a list")
.setDirection(Metric.DIRECTION_NONE)
.setQualitative(false)
.setDomain(Metrics.DOMAIN)
.setHidden(true)
.create();
private static final Metric UPGRADES_RATIO = new Metric.Builder(Metrics.KEY_UPGRADES_RATIO, "Dependencies to upgrade (Ratio)", ValueType.PERCENT)
.setDescription("Ratio of dependencies with upgrades")
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setBestValue(0.0)
.create();
private static final Metric UPGRADES_MISSED = new Metric.Builder(Metrics.KEY_UPGRADES_MISSED, "Upgrades missed", ValueType.INT)
.setDescription("Total number of released upgrades missed")
.setDirection(Metric.DIRECTION_WORST)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setBestValue(0.0)
.create();
private static final Metric PATCHES_RATING = new Metric.Builder(Metrics.KEY_PATCHES_RATING, "Patch Maintenance", ValueType.RATING)
.setDescription("Rating of the maintenance of applying patches")
.setDirection(Metric.DIRECTION_BETTER)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setWorstValue(5.0)
.setBestValue(1.0)
.create();
private static final Metric UPGRADES_RATING = new Metric.Builder(Metrics.KEY_UPGRADES_RATING, "Upgrade Maintenance", ValueType.RATING)
.setDescription("Rating of the maintenance of applying upgrades")
.setDirection(Metric.DIRECTION_BETTER)
.setQualitative(Boolean.TRUE)
.setDomain(Metrics.DOMAIN)
.setWorstValue(5.0)
.setBestValue(1.0)
.create();
private final Configuration configuration;
public Metrics(Configuration configuration) {
this.configuration = configuration;
PATCHES_RATIO.setHidden(configuration.getBoolean(Constants.CONFIG_MEASURE_HIDE_RATIO).orElse(Constants.CONFIG_MEASURE_HIDE_RATIO_DEFAULT));
UPGRADES_RATIO.setHidden(configuration.getBoolean(Constants.CONFIG_MEASURE_HIDE_RATIO).orElse(Constants.CONFIG_MEASURE_HIDE_RATIO_DEFAULT));
PATCHES_RATING.setHidden(configuration.getBoolean(Constants.CONFIG_MEASURE_HIDE_RATING).orElse(Constants.CONFIG_MEASURE_HIDE_RATING_DEFAULT));
UPGRADES_RATING.setHidden(configuration.getBoolean(Constants.CONFIG_MEASURE_HIDE_RATING).orElse(Constants.CONFIG_MEASURE_HIDE_RATING_DEFAULT));
PATCHES_MISSED.setHidden(configuration.getBoolean(Constants.CONFIG_MEASURE_HIDE_MISSED).orElse(Constants.CONFIG_MEASURE_HIDE_MISSED_DEFAULT));
UPGRADES_MISSED.setHidden(configuration.getBoolean(Constants.CONFIG_MEASURE_HIDE_MISSED).orElse(Constants.CONFIG_MEASURE_HIDE_MISSED_DEFAULT));
}
/**
* Calculates all metrics provided by this Sonar-Plugin based on the given Analysis.
*/
static void calculateMetricsModule(SensorContext context, Analysis analysis) {
calculateMetrics(context, context.fileSystem().inputFile(context.fileSystem().predicates().hasRelativePath("pom.xml")), analysis);
}
private static void calculateMetrics(SensorContext context, InputComponent inputComponent, Analysis analysis) {
calculateDependencies(context, inputComponent, analysis);
calculatePatches(context, inputComponent, analysis);
calculatePatchesRatio(context, inputComponent, analysis);
calculatePatchesMissed(context, inputComponent, analysis);
calculateUpgrades(context, inputComponent, analysis);
calculateUpgradesRatio(context, inputComponent, analysis);
calculateUpgradesMissed(context, inputComponent, analysis);
calculateData(context, inputComponent, Metrics.DEPENDENCIES_DATA, analysis.all());
calculateData(context, inputComponent, Metrics.PATCHES_DATA, analysis.all().stream().filter(dependency -> dependency.getUpdateCount() > 0).collect(Collectors.toList()));
calculateData(context, inputComponent, Metrics.UPGRADES_DATA, analysis.all().stream().filter(dependency -> dependency.getUpgradeCount() > 0).collect(Collectors.toList()));
}
private static void calculateDependencies(SensorContext context, InputComponent inputComponent, Analysis analysis) {
context.newMeasure().forMetric(Metrics.DEPENDENCIES).on(inputComponent).withValue(analysis.all().size()).save();
}
private static void calculateData(SensorContext context, InputComponent inputComponent, Metric metric, List dependencies) {
String dependenciesList = dependencies.stream().map(Dependency::toDataString).collect(Collectors.joining(","));
context.newMeasure().forMetric(metric).on(inputComponent).withValue(dependenciesList).save();
}
private static void calculatePatches(SensorContext context, InputComponent inputComponent, Analysis analysis) {
int count = Math.toIntExact(analysis.all().stream().filter(dependency -> dependency.getIncrementals().size() > 0).count());
context.newMeasure().forMetric(Metrics.PATCHES).on(inputComponent).withValue(count).save();
}
private static void calculatePatchesRatio(SensorContext context, InputComponent inputComponent, Analysis analysis) {
double ratio = 0;
long totalDependenciesWithPatches = analysis.all().stream().filter(dependency -> dependency.getIncrementals().size() > 0).count();
if (analysis.all().size() > 0) {
ratio = 100.0 * totalDependenciesWithPatches / analysis.all().size();
}
context.newMeasure().forMetric(Metrics.PATCHES_RATIO).on(inputComponent).withValue(ratio).save();
context.newMeasure().forMetric(Metrics.PATCHES_RATING).on(inputComponent).withValue(
Math.toIntExact(calculateRating(Math.toIntExact(totalDependenciesWithPatches),analysis.all().size()))).save();
}
private static void calculatePatchesMissed(SensorContext context, InputComponent inputComponent, Analysis analysis) {
int sum = Math.toIntExact(analysis.all().stream().collect(Collectors.summarizingInt(Dependency::getUpdateCount)).getSum());
context.newMeasure().forMetric(Metrics.PATCHES_MISSED).on(inputComponent).withValue(sum).save();
}
private static void calculateUpgrades(SensorContext context, InputComponent inputComponent, Analysis analysis) {
int count = Math.toIntExact(analysis.all().stream().filter(dependency -> dependency.getUpgradeCount() > 0).count());
context.newMeasure().forMetric(Metrics.UPGRADES).on(inputComponent).withValue(count).save();
}
private static void calculateUpgradesRatio(SensorContext context, InputComponent inputComponent, Analysis analysis) {
double ratio = 0;
long totalDependenciesWithUpgrades = analysis.all().stream().filter(dependency -> dependency.getUpgradeCount() > 0).count();
if (analysis.all().size() > 0) {
ratio = 100.0 * totalDependenciesWithUpgrades / analysis.all().size();
}
context.newMeasure().forMetric(Metrics.UPGRADES_RATIO).on(inputComponent).withValue(ratio).save();
context.newMeasure().forMetric(Metrics.UPGRADES_RATING).on(inputComponent).withValue(
Math.toIntExact(calculateRating(Math.toIntExact(totalDependenciesWithUpgrades),analysis.all().size()))).save();
}
private static void calculateUpgradesMissed(SensorContext context, InputComponent inputComponent, Analysis analysis) {
int sum = Math.toIntExact(analysis.all().stream().collect(Collectors.summarizingInt(Dependency::getUpgradeCount)).getSum());
context.newMeasure().forMetric(Metrics.UPGRADES_MISSED).on(inputComponent).withValue(sum).save();
}
static int calculateRating(int withLater, int total) {
Range range = mapping.keySet().stream().filter(r -> r.contains(total)).findFirst().get();
Map, Integer> ratings = mapping.get(range);
return ratings.get(ratings.keySet().stream().filter(r -> r.contains(withLater)).findFirst().get());
}
@Override
public List getMetrics() {
return Arrays.asList(
Metrics.DEPENDENCIES,
Metrics.DEPENDENCIES_DATA,
Metrics.PATCHES,
Metrics.PATCHES_DATA,
Metrics.PATCHES_RATIO,
Metrics.PATCHES_MISSED,
Metrics.PATCHES_RATING,
Metrics.UPGRADES,
Metrics.UPGRADES_DATA,
Metrics.UPGRADES_RATIO,
Metrics.UPGRADES_MISSED,
Metrics.UPGRADES_RATING
);
}
}