From 165470ce4e447102186ff58860469feb93462bfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B6ren=20Henning?= <soeren.henning@email.uni-kiel.de>
Date: Wed, 7 Dec 2022 18:02:45 +0100
Subject: [PATCH] Allow for relative thresholds

---
 .../kubernetes/slo/AnalysisExecutor.kt        |  2 +-
 .../kubernetes/slo/SloCheckerFactory.kt       | 14 ++-
 .../kubernetes/slo/SloCheckerFactoryTest.kt   | 86 +++++++++++++++++++
 3 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt
index 96c5a43b8..b7cd32d73 100644
--- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt
@@ -60,7 +60,7 @@ class AnalysisExecutor(
                 sloType = slo.sloType,
                 properties = slo.properties,
                 load = load,
-                resource = resource,
+                resources = resource,
                 metric = metric
             )
 
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt
index a789050a1..1f37142ad 100644
--- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt
@@ -34,7 +34,9 @@ class SloCheckerFactory {
      *
      * @param sloType Type of the [SloChecker].
      * @param properties map of properties to use for the SLO checker creation.
-     * @param load that is executed in the experiment.
+     * @param load Load that is generated in the experiment.
+     * @param resources Resources that are used in the experiment.
+     * @param metric Metric used in the benchmark execution.
      *
      * @return A [SloChecker]
      * @throws IllegalArgumentException If [sloType] not supported.
@@ -43,7 +45,7 @@ class SloCheckerFactory {
         sloType: String,
         properties: Map<String, String>,
         load: Int,
-        resource: Int,
+        resources: Int,
         metric: Metric
     ): SloChecker {
         return when (SloTypes.from(sloType)) {
@@ -59,7 +61,9 @@ class SloCheckerFactory {
                         ?: throw IllegalArgumentException("repetitionAggregation expected")),
                     "operator" to (properties["operator"] ?: throw IllegalArgumentException("operator expected")),
                     "threshold" to (properties["threshold"]?.toDouble()
-                        ?: throw IllegalArgumentException("threshold expected"))
+                        ?: properties["thresholdRelToLoad"]?.toDouble()?.times(load)
+                        ?: properties["thresholdRelToResources"]?.toDouble()?.times(resources)
+                        ?: throw IllegalArgumentException("'threshold', 'thresholdRelToLoad' or 'thresholdRelToResources' expected"))
                 )
             )
             SloTypes.LAG_TREND, SloTypes.DROPPED_RECORDS -> ExternalSloChecker(
@@ -68,7 +72,9 @@ class SloCheckerFactory {
                 metadata = mapOf(
                     "warmup" to (properties["warmup"]?.toInt() ?: throw IllegalArgumentException("warmup expected")),
                     "threshold" to (properties["threshold"]?.toDouble()
-                        ?: throw IllegalArgumentException("threshold expected"))
+                        ?: properties["thresholdRelToLoad"]?.toDouble()?.times(load)
+                        ?: properties["thresholdRelToResources"]?.toDouble()?.times(resources)
+                        ?: throw IllegalArgumentException("'threshold', 'thresholdRelToLoad' or 'thresholdRelToResources' expected"))
                 )
             )
             SloTypes.LAG_TREND_RATIO, SloTypes.DROPPED_RECORDS_RATIO -> {
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactoryTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactoryTest.kt
index a61119bbe..ef018f1ec 100644
--- a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactoryTest.kt
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactoryTest.kt
@@ -129,6 +129,52 @@ internal class SloCheckerFactoryTest {
         }
     }
 
+    @Test
+    fun testCreateGenericSloWithThresholdRelToLoad() {
+        val factory = SloCheckerFactory()
+        val sloChecker = factory.create(
+            SloTypes.GENERIC.value,
+            mapOf(
+                "externalSloUrl" to "http://localhost:1234",
+                "warmup" to "60",
+                "queryAggregation" to "median",
+                "repetitionAggregation" to "median",
+                "operator" to "lte",
+                "thresholdRelToLoad" to "0.1"
+            ),
+            100,
+            5,
+            Metric.DEMAND
+        )
+        assertTrue(sloChecker is ExternalSloChecker)
+        val computedThreshold = (sloChecker as ExternalSloChecker).metadata["threshold"]
+        assertTrue(computedThreshold is Double)
+        assertEquals(10.0, computedThreshold as Double, 0.001)
+    }
+
+    @Test
+    fun testCreateGenericSloWithThresholdRelToResources() {
+        val factory = SloCheckerFactory()
+        val sloChecker = factory.create(
+            SloTypes.GENERIC.value,
+            mapOf(
+                "externalSloUrl" to "http://localhost:1234",
+                "warmup" to "60",
+                "queryAggregation" to "median",
+                "repetitionAggregation" to "median",
+                "operator" to "lte",
+                "thresholdRelToResources" to "0.1"
+            ),
+            100,
+            5,
+            Metric.DEMAND
+        )
+        assertTrue(sloChecker is ExternalSloChecker)
+        val computedThreshold = (sloChecker as ExternalSloChecker).metadata["threshold"]
+        assertTrue(computedThreshold is Double)
+        assertEquals(0.5, computedThreshold as Double, 0.001)
+    }
+
     @Test
     fun testCreateGenericSloFloatThreshold() {
         val factory = SloCheckerFactory()
@@ -224,6 +270,46 @@ internal class SloCheckerFactoryTest {
         assertEquals(12.34, threshold as Double, 0.01)
     }
 
+    @Test
+    fun testCreateLagTrendSloWithThresholdRelToLoad() {
+        val factory = SloCheckerFactory()
+        val sloChecker = factory.create(
+            SloTypes.LAG_TREND.value,
+            mapOf(
+                "externalSloUrl" to "http://localhost:1234",
+                "warmup" to "60",
+                "thresholdRelToLoad" to "0.1"
+            ),
+            100,
+            5,
+            Metric.DEMAND
+        )
+        assertTrue(sloChecker is ExternalSloChecker)
+        val computedThreshold = (sloChecker as ExternalSloChecker).metadata["threshold"]
+        assertTrue(computedThreshold is Double)
+        assertEquals(10.0, computedThreshold as Double, 0.001)
+    }
+
+    @Test
+    fun testCreateLagTrendSloWithThresholdRelToResources() {
+        val factory = SloCheckerFactory()
+        val sloChecker = factory.create(
+            SloTypes.LAG_TREND.value,
+            mapOf(
+                "externalSloUrl" to "http://localhost:1234",
+                "warmup" to "60",
+                "thresholdRelToResources" to "0.1"
+            ),
+            100,
+            5,
+            Metric.DEMAND
+        )
+        assertTrue(sloChecker is ExternalSloChecker)
+        val computedThreshold = (sloChecker as ExternalSloChecker).metadata["threshold"]
+        assertTrue(computedThreshold is Double)
+        assertEquals(0.5, computedThreshold as Double, 0.001)
+    }
+
     @Test
     fun testCreateLagTrendRatioSloWithoutUrl() {
         val factory = SloCheckerFactory()
-- 
GitLab