@Override public Set<String> getMetricKeys(QualityGate gate) { Set<String> metricKeys = new HashSet<>(); metricKeys.add(CoreMetrics.NEW_LINES_KEY); for (Condition condition : gate.getConditions()) { metricKeys.add(condition.getMetricKey()); } return metricKeys; }
private static Comparable getThreshold(Condition condition, ValueType valueType) { String valString = condition.getErrorThreshold(); try { switch (valueType) { case INT: case RATING: return parseInteger(valString); case MILLISEC: case WORK_DUR: return Long.parseLong(valString); case FLOAT: case PERCENT: return Double.parseDouble(valString); case LEVEL: return valueType; default: throw new IllegalArgumentException(format("Unsupported value type %s. Cannot convert condition value", valueType)); } } catch (NumberFormatException badValueFormat) { throw new IllegalArgumentException(format( "Quality Gate: unable to parse threshold '%s' to compare against %s", valString, condition.getMetricKey())); } }
/** * Evaluates the condition for the specified measure */ static EvaluatedCondition evaluate(Condition condition, QualityGateEvaluator.Measures measures) { Optional<QualityGateEvaluator.Measure> measure = measures.get(condition.getMetricKey()); if (!measure.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } Optional<Comparable> value = getMeasureValue(condition, measure.get()); if (!value.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } ValueType type = measure.get().getType(); return evaluateCondition(condition, type, value.get()) .orElseGet(() -> new EvaluatedCondition(condition, EvaluationStatus.OK, value.get().toString())); }
private static JsonObject toJson(EvaluatedCondition evaluatedCondition) { Condition condition = evaluatedCondition.getCondition(); JsonObject result = new JsonObject(); result.addProperty("metric", condition.getMetricKey()); result.addProperty("op", condition.getOperator().getDbValue()); if (condition.isOnLeakPeriod()) { result.addProperty("period", 1); } result.addProperty("error", condition.getErrorThreshold()); evaluatedCondition.getValue().ifPresent(v -> result.addProperty("actual", v)); result.addProperty(FIELD_LEVEL, evaluatedCondition.getStatus().name()); return result; } }
@Test public void getMetricKeys_includes_metrics_from_qgate() { Set<String> metricKeys = ImmutableSet.of("foo", "bar", "baz"); Set<Condition> conditions = metricKeys.stream().map(key -> { Condition condition = mock(Condition.class); when(condition.getMetricKey()).thenReturn(key); return condition; }).collect(Collectors.toSet()); QualityGate gate = mock(QualityGate.class); when(gate.getConditions()).thenReturn(conditions); assertThat(underTest.getMetricKeys(gate)).containsAll(metricKeys); }
@Test public void verify_getters() { assertThat(underTest.getMetricKey()).isEqualTo(METRIC_KEY); assertThat(underTest.getOperator()).isEqualTo(OPERATOR); assertThat(underTest.getErrorThreshold()).contains(ERROR_THRESHOLD); }
@Test public void getMetricsRelatedTo() { Condition condition = new Condition("metric1", Condition.Operator.GREATER_THAN, "10"); QualityGate gate = new QualityGate("1", "foo", ImmutableSet.of(condition)); Set<String> result = underTest.getMetricsRelatedTo(gate); assertThat(result).containsExactlyInAnyOrder( // the metrics needed to compute the status of gate condition.getMetricKey(), // generated metrics CoreMetrics.ALERT_STATUS_KEY, CoreMetrics.QUALITY_GATE_DETAILS_KEY); }
@Override public EvaluatedQualityGate evaluate(QualityGate gate, Measures measures) { EvaluatedQualityGate.Builder result = EvaluatedQualityGate.newBuilder() .setQualityGate(gate); boolean isSmallChangeset = isSmallChangeset(measures); gate.getConditions().forEach(condition -> { String metricKey = condition.getMetricKey(); EvaluatedCondition evaluation = ConditionEvaluator.evaluate(condition, measures); if (isSmallChangeset && evaluation.getStatus() != EvaluationStatus.OK && METRICS_TO_IGNORE_ON_SMALL_CHANGESETS.contains(metricKey)) { result.addCondition(new EvaluatedCondition(evaluation.getCondition(), EvaluationStatus.OK, evaluation.getValue().orElse(null))); result.setIgnoredConditionsOnSmallChangeset(true); } else { result.addCondition(evaluation); } }); result.setStatus(overallStatusOf(result.getEvaluatedConditions())); return result.build(); }
private static void writeQualityGate(JsonWriter writer, EvaluatedQualityGate gate) { writer .name("qualityGate") .beginObject() .prop("name", gate.getQualityGate().getName()) .prop(PROPERTY_STATUS, gate.getStatus().toString()) .name("conditions") .beginArray(); for (EvaluatedCondition evaluatedCondition : gate.getEvaluatedConditions()) { Condition condition = evaluatedCondition.getCondition(); writer .beginObject() .prop("metric", condition.getMetricKey()) .prop("operator", condition.getOperator().name()); evaluatedCondition.getValue().ifPresent(t -> writer.prop("value", t)); writer .prop(PROPERTY_STATUS, evaluatedCondition.getStatus().name()) .prop("errorThreshold", condition.getErrorThreshold()) .endObject(); } writer .endArray() .endObject(); }
@Override public Set<String> getMetricKeys(QualityGate gate) { Set<String> metricKeys = new HashSet<>(); metricKeys.add(CoreMetrics.NEW_LINES_KEY); for (Condition condition : gate.getConditions()) { metricKeys.add(condition.getMetricKey()); } return metricKeys; }
/** * Evaluates the condition for the specified measure */ static EvaluatedCondition evaluate(Condition condition, QualityGateEvaluator.Measures measures) { Optional<QualityGateEvaluator.Measure> measure = measures.get(condition.getMetricKey()); if (!measure.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } Optional<Comparable> value = getMeasureValue(condition, measure.get()); if (!value.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } ValueType type = measure.get().getType(); return evaluateCondition(condition, type, value.get(), true) .orElseGet(() -> evaluateCondition(condition, type, value.get(), false) .orElseGet(() -> new EvaluatedCondition(condition, EvaluationStatus.OK, value.get().toString()))); }
private static JsonObject toJson(EvaluatedCondition evaluatedCondition) { Condition condition = evaluatedCondition.getCondition(); JsonObject result = new JsonObject(); result.addProperty("metric", condition.getMetricKey()); result.addProperty("op", condition.getOperator().getDbValue()); if (condition.isOnLeakPeriod()) { result.addProperty("period", 1); } condition.getWarningThreshold().ifPresent(t -> result.addProperty("warning", t)); condition.getErrorThreshold().ifPresent(t -> result.addProperty("error", t)); evaluatedCondition.getValue().ifPresent(v -> result.addProperty("actual", v)); result.addProperty(FIELD_LEVEL, evaluatedCondition.getStatus().name()); return result; } }
private static Optional<Comparable> getThreshold(Condition condition, ValueType valueType, boolean error) { Optional<String> valString = error ? condition.getErrorThreshold() : condition.getWarningThreshold(); return valString.map(s -> { try { switch (valueType) { case BOOL: return parseInteger(s) == 1; case INT: case RATING: return parseInteger(s); case MILLISEC: case WORK_DUR: return Long.parseLong(s); case FLOAT: case PERCENT: return Double.parseDouble(s); case STRING: case LEVEL: return s; default: throw new IllegalArgumentException(String.format("Unsupported value type %s. Cannot convert condition value", valueType)); } } catch (NumberFormatException badValueFormat) { throw new IllegalArgumentException(String.format( "Quality Gate: unable to parse threshold '%s' to compare against %s", s, condition.getMetricKey())); } }); }
private static void writeQualityGate(JsonWriter writer, EvaluatedQualityGate gate) { writer .name("qualityGate") .beginObject() .prop("name", gate.getQualityGate().getName()) .prop(PROPERTY_STATUS, gate.getStatus().toString()) .name("conditions") .beginArray(); for (EvaluatedCondition evaluatedCondition : gate.getEvaluatedConditions()) { Condition condition = evaluatedCondition.getCondition(); writer .beginObject() .prop("metric", condition.getMetricKey()) .prop("operator", condition.getOperator().name()); evaluatedCondition.getValue().ifPresent(t -> writer.prop("value", t)); writer .prop(PROPERTY_STATUS, evaluatedCondition.getStatus().name()) .prop("onLeakPeriod", condition.isOnLeakPeriod()) .prop("errorThreshold", condition.getErrorThreshold().orElse(null)) .prop("warningThreshold", condition.getWarningThreshold().orElse(null)) .endObject(); } writer .endArray() .endObject(); }