Skip to content

Commit

Permalink
fix(scorer): Add test suite for WeightedSumScorer; calculate the scor…
Browse files Browse the repository at this point in the history
…e as a cumulative sum. (#150)
  • Loading branch information
csanden authored and Michael Graff committed Dec 11, 2017
1 parent 15110a9 commit 9ef083f
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
package com.netflix.kayenta.judge.scorers

import com.netflix.kayenta.canary.results.CanaryAnalysisResult
import com.netflix.kayenta.judge.classifiers.metric.{Pass, High, Low}

import scala.collection.JavaConverters._

class WeightedSumScorer(groupWeights: Map[String, Double]) extends BaseScorer{
//Todo (csanden) Use the Classification Label not the String value

/**
*
Expand All @@ -34,9 +34,9 @@ class WeightedSumScorer(groupWeights: Map[String, Double]) extends BaseScorer{
val labelCounts = classificationLabels.groupBy(identity).mapValues(_.size)
val numMetrics = classificationLabels.size

val numPass = labelCounts.getOrElse("Pass", 0)
val numHigh = labelCounts.getOrElse("High", 0)
val numLow = labelCounts.getOrElse("Low", 0)
val numPass = labelCounts.getOrElse(Pass.toString, 0)
val numHigh = labelCounts.getOrElse(High.toString, 0)
val numLow = labelCounts.getOrElse(Low.toString, 0)
val numTotal = numHigh + numLow + numPass

val hasNoData = if(numTotal == 0) true else false
Expand All @@ -59,9 +59,12 @@ class WeightedSumScorer(groupWeights: Map[String, Double]) extends BaseScorer{
groupLabels.map{ case (groupName, labels) => calculateGroupScore(groupName, labels)}.toList
}


/**
*
* @param groupResults
* @return
*/
private def calculateSummaryScore(groupResults: List[GroupScore]): Double ={
//Todo (csanden) throw exception if the group weights exceed 100%

val groupWeightSum = groupWeights.values.sum
val groupWeightSet = groupWeights.keySet
Expand All @@ -74,10 +77,10 @@ class WeightedSumScorer(groupWeights: Map[String, Double]) extends BaseScorer{
val calculatedWeight = if(groupDifference.nonEmpty) (100-groupWeightSum)/groupDifference.size else 0.0

//Compute the summary score based on the group score and weights
var summaryScore: Double = 100
var summaryScore: Double = 0.0
groupResults.filter(!_.noData).foreach{ group =>
val weight:Double = groupWeights.getOrElse(group.name, calculatedWeight)
summaryScore -= (100-group.score)*weight/100
summaryScore += group.score*(weight/100)
}

summaryScore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Copyright 2017 Netflix, Inc.
*
* 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 com.netflix.kayenta.judge

import com.netflix.kayenta.canary.results.CanaryAnalysisResult
import com.netflix.kayenta.judge.scorers.WeightedSumScorer
import com.netflix.kayenta.judge.classifiers.metric.{Pass, High, Low, Nodata}
import org.scalatest.FunSuite
import org.scalatest.Matchers._

import scala.collection.JavaConverters._

class ScorerSuite extends FunSuite{

test("Weighted Sum Group Scorer: Single Metric Pass"){
val groupWeights = Map[String, Double]()
val weightedSumScorer = new WeightedSumScorer(groupWeights)

val passMetric = CanaryAnalysisResult.builder()
.name("test-metric-pass")
.classification(Pass.toString)
.groups(List[String]("test-group").asJava)
.build()

val scores = weightedSumScorer.score(List(passMetric))
assert(scores.summaryScore == 100.0)
}

test("Weighted Sum Group Scorer: Single Metric Fail"){
val groupWeights = Map[String, Double]()
val weightedSumScorer = new WeightedSumScorer(groupWeights)

val passMetric = CanaryAnalysisResult.builder()
.name("test-metric-high")
.classification(High.toString)
.groups(List[String]("test-group").asJava)
.build()

val scores = weightedSumScorer.score(List(passMetric))
assert(scores.summaryScore == 0.0)
}

test("Weighted Sum Group Scorer: One Group, Two Metrics"){
val groupWeights = Map[String, Double]()
val weightedSumScorer = new WeightedSumScorer(groupWeights)

val passMetric = CanaryAnalysisResult.builder()
.name("test-metric-pass")
.classification(Pass.toString)
.groups(List[String]("test-group").asJava)
.build()

val highMetric = CanaryAnalysisResult.builder()
.name("test-metric-high")
.classification(High.toString)
.groups(List[String]("test-group").asJava)
.build()

val scores = weightedSumScorer.score(List(passMetric, highMetric))
assert(scores.summaryScore == 50.0)
}

test("Weighted Sum Group Scorer: One Group, Three Metrics"){
val groupWeights = Map[String, Double]()
val weightedSumScorer = new WeightedSumScorer(groupWeights)

val passMetric = CanaryAnalysisResult.builder()
.name("test-metric-pass")
.classification(Pass.toString)
.groups(List[String]("test-group").asJava)
.build()

val highMetric = CanaryAnalysisResult.builder()
.name("test-metric-high")
.classification(High.toString)
.groups(List[String]("test-group").asJava)
.build()

val lowMetric = CanaryAnalysisResult.builder()
.name("test-metric-low")
.classification(Low.toString)
.groups(List[String]("test-group").asJava)
.build()

val scores = weightedSumScorer.score(List(passMetric, highMetric, lowMetric))
assert(scores.summaryScore === (33.33 +- 1.0e-2))
}

test("Weighted Sum Group Scorer: Two Groups, Three Metrics"){
val groupWeights = Map[String, Double]("group-1" -> 75.0, "group-2" -> 25.0)
val weightedSumScorer = new WeightedSumScorer(groupWeights)

val passMetric1 = CanaryAnalysisResult.builder()
.name("test-metric-pass-1")
.classification(Pass.toString)
.groups(List[String]("group-1").asJava)
.build()

val passMetric2 = CanaryAnalysisResult.builder()
.name("test-metric-pass-2")
.classification(Pass.toString)
.groups(List[String]("group-1").asJava)
.build()

val failMetric = CanaryAnalysisResult.builder()
.name("test-metric-fail")
.classification(High.toString)
.groups(List[String]("group-2").asJava)
.build()

val scores = weightedSumScorer.score(List(passMetric1, passMetric2, failMetric))
assert(scores.summaryScore == 75.0)
}

test("Weighted Sum Group Scorer: Two Groups, Three Metrics (Equal Weight)"){
val groupWeights = Map[String, Double]("group-1" -> 50.0, "group-2" -> 50.0)
val weightedSumScorer = new WeightedSumScorer(groupWeights)

val passMetric = CanaryAnalysisResult.builder()
.name("test-metric-pass")
.classification(Pass.toString)
.groups(List[String]("group-1").asJava)
.build()

val failMetric1 = CanaryAnalysisResult.builder()
.name("test-metric-fail-1")
.classification(High.toString)
.groups(List[String]("group-1").asJava)
.build()

val failMetric2 = CanaryAnalysisResult.builder()
.name("test-metric-fail-2")
.classification(High.toString)
.groups(List[String]("group-2").asJava)
.build()

val scores = weightedSumScorer.score(List(passMetric, failMetric1, failMetric2))
assert(scores.summaryScore == 25.0)
}

test("Weighted Sum Group Scorer: No Data"){
val groupWeights = Map[String, Double]()
val weightedSumScorer = new WeightedSumScorer(groupWeights)

val metricClassification = CanaryAnalysisResult.builder()
.name("test-metric-nodata")
.classification(Nodata.toString)
.groups(List[String]("test-group").asJava)
.build()

val scores = weightedSumScorer.score(List(metricClassification))
assert(scores.summaryScore == 0.0)
}

}

0 comments on commit 9ef083f

Please sign in to comment.