Skip to content
Snippets Groups Projects
Commit 0d2bbce8 authored by Benedikt Wetzel's avatar Benedikt Wetzel
Browse files

Add basic support for execution multiple repititions

not tested so far
parent e2360a94
No related branches found
No related tags found
4 merge requests!159Re-implementation of Theodolite with Kotlin/Quarkus,!157Update Graal Image in CI pipeline,!137Allow multiple repititions of an experiment,!83WIP: Re-implementation of Theodolite with Kotlin/Quarkus
...@@ -16,17 +16,13 @@ class AnalysisExecutor(private val slo: BenchmarkExecution.Slo) { ...@@ -16,17 +16,13 @@ class AnalysisExecutor(private val slo: BenchmarkExecution.Slo) {
offset = Duration.ofHours(slo.offset.toLong()) offset = Duration.ofHours(slo.offset.toLong())
) )
fun analyze(load: LoadDimension, res: Resource, executionDuration: Duration): Boolean { fun analyze(load: LoadDimension, res: Resource, executionIntervals: List<Pair<Instant, Instant>>): Boolean {
var result = false var result = false
val exporter = CsvExporter()
val prometheusData = executionIntervals.map { interval -> fetcher.fetchMetric( start = interval.first, end = interval.second, query = "sum by(group)(kafka_consumergroup_group_lag >= 0)") }
var repetitionCounter = 0
prometheusData.forEach{ data -> exporter.toCsv(name = "${load.get()}_${res.get()}_${slo.sloType}_rep_${repetitionCounter++}", prom = data) }
try { try {
val prometheusData = fetcher.fetchMetric(
start = Instant.now().minus(executionDuration),
end = Instant.now(),
query = "sum by(group)(kafka_consumergroup_group_lag >= 0)"
)
CsvExporter().toCsv(name = "${load.get()}_${res.get()}_${slo.sloType}", prom = prometheusData)
val sloChecker = SloCheckerFactory().create( val sloChecker = SloCheckerFactory().create(
slotype = slo.sloType, slotype = slo.sloType,
...@@ -35,10 +31,7 @@ class AnalysisExecutor(private val slo: BenchmarkExecution.Slo) { ...@@ -35,10 +31,7 @@ class AnalysisExecutor(private val slo: BenchmarkExecution.Slo) {
warmup = slo.warmup warmup = slo.warmup
) )
result = sloChecker.evaluate( result = sloChecker.evaluate(prometheusData)
start = Instant.now().minus(executionDuration),
end = Instant.now(), fetchedData = prometheusData
)
} catch (e: Exception) { } catch (e: Exception) {
logger.error { "Evaluation failed for resource: ${res.get()} and load: ${load.get()} error: $e" } logger.error { "Evaluation failed for resource: ${res.get()} and load: ${load.get()} error: $e" }
......
...@@ -19,13 +19,15 @@ class ExternalSloChecker( ...@@ -19,13 +19,15 @@ class ExternalSloChecker(
private val logger = KotlinLogging.logger {} private val logger = KotlinLogging.logger {}
override fun evaluate(start: Instant, end: Instant, fetchedData: PrometheusResponse): Boolean { override fun evaluate(fetchedData: List<PrometheusResponse>): Boolean {
var counter = 0 var counter = 0
val data = var requestData = fetchedData.map { entry -> Gson().toJson(mapOf("total_lag" to entry.data?.result)) }.toMutableList()
Gson().toJson(mapOf("total_lag" to fetchedData.data?.result, "threshold" to threshold, "warmup" to warmup)) requestData.add(mapOf("threshold" to threshold).toString())
requestData.add(mapOf("warmup" to warmup).toString())
while (counter < RETRIES) { while (counter < RETRIES) {
val result = post(externalSlopeURL, data = data, timeout = TIMEOUT) val result = post(externalSlopeURL, data = requestData, timeout = TIMEOUT)
if (result.statusCode != 200) { if (result.statusCode != 200) {
counter++ counter++
logger.error { "Could not reach external slope analysis" } logger.error { "Could not reach external slope analysis" }
......
...@@ -4,5 +4,5 @@ import theodolite.util.PrometheusResponse ...@@ -4,5 +4,5 @@ import theodolite.util.PrometheusResponse
import java.time.Instant import java.time.Instant
interface SloChecker { interface SloChecker {
fun evaluate(start: Instant, end: Instant, fetchedData: PrometheusResponse): Boolean fun evaluate(fetchedData: List<PrometheusResponse>): Boolean
} }
...@@ -25,7 +25,8 @@ abstract class BenchmarkExecutor( ...@@ -25,7 +25,8 @@ abstract class BenchmarkExecutor(
val results: Results, val results: Results,
val executionDuration: Duration, val executionDuration: Duration,
configurationOverrides: List<ConfigurationOverride?>, configurationOverrides: List<ConfigurationOverride?>,
val slo: BenchmarkExecution.Slo val slo: BenchmarkExecution.Slo,
val repetitions: Int
) { ) {
var run: AtomicBoolean = AtomicBoolean(true) var run: AtomicBoolean = AtomicBoolean(true)
......
...@@ -5,11 +5,9 @@ import mu.KotlinLogging ...@@ -5,11 +5,9 @@ import mu.KotlinLogging
import theodolite.benchmark.Benchmark import theodolite.benchmark.Benchmark
import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.BenchmarkExecution
import theodolite.evaluation.AnalysisExecutor import theodolite.evaluation.AnalysisExecutor
import theodolite.util.ConfigurationOverride import theodolite.util.*
import theodolite.util.LoadDimension
import theodolite.util.Resource
import theodolite.util.Results
import java.time.Duration import java.time.Duration
import java.time.Instant
private val logger = KotlinLogging.logger {} private val logger = KotlinLogging.logger {}
...@@ -19,27 +17,40 @@ class BenchmarkExecutorImpl( ...@@ -19,27 +17,40 @@ class BenchmarkExecutorImpl(
results: Results, results: Results,
executionDuration: Duration, executionDuration: Duration,
private val configurationOverrides: List<ConfigurationOverride?>, private val configurationOverrides: List<ConfigurationOverride?>,
slo: BenchmarkExecution.Slo slo: BenchmarkExecution.Slo,
) : BenchmarkExecutor(benchmark, results, executionDuration, configurationOverrides, slo) { repetitions: Int
) : BenchmarkExecutor(benchmark, results, executionDuration, configurationOverrides, slo, repetitions) {
override fun runExperiment(load: LoadDimension, res: Resource): Boolean { override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
var result = false var result = false
val benchmarkDeployment = benchmark.buildDeployment(load, res, this.configurationOverrides) val executionIntervals: MutableList<Pair<Instant, Instant>> = ArrayList(repetitions)
executionIntervals
for (i in 1.rangeTo(repetitions)) {
if (this.run.get()) {
executionIntervals.add(runSingleExperiment(load,res))
}
}
if (this.run.get()) {
result =
AnalysisExecutor(slo = slo).analyze(load = load, res = res, executionIntervals = executionIntervals)
this.results.setResult(Pair(load, res), result)
}
return result
}
private fun runSingleExperiment(load: LoadDimension, res: Resource): Pair<Instant, Instant> {
val benchmarkDeployment = benchmark.buildDeployment(load, res, this.configurationOverrides)
val from = Instant.now()
try { try {
benchmarkDeployment.setup() benchmarkDeployment.setup()
this.waitAndLog() this.waitAndLog()
} catch(e: Exception) { } catch (e: Exception) {
logger.error { "Error while setup experiment." } logger.error { "Error while setup experiment." }
logger.error { "Error is: $e" } logger.error { "Error is: $e" }
this.run.set(false) this.run.set(false)
} }
val to = Instant.now()
if (this.run.get()) {
result =
AnalysisExecutor(slo = slo).analyze(load = load, res = res, executionDuration = executionDuration)
this.results.setResult(Pair(load, res), result)
}
benchmarkDeployment.teardown() benchmarkDeployment.teardown()
return result return Pair(from,to)
} }
} }
...@@ -41,7 +41,8 @@ class TheodoliteExecutor( ...@@ -41,7 +41,8 @@ class TheodoliteExecutor(
results, results,
executionDuration, executionDuration,
config.configOverrides, config.configOverrides,
config.slos[0] config.slos[0],
config.execution.repetitions
) )
return Config( return Config(
......
...@@ -19,7 +19,8 @@ class TestBenchmarkExecutorImpl( ...@@ -19,7 +19,8 @@ class TestBenchmarkExecutorImpl(
results, results,
executionDuration = Duration.ofSeconds(1), executionDuration = Duration.ofSeconds(1),
configurationOverrides = emptyList(), configurationOverrides = emptyList(),
slo = slo slo = slo,
repetitions = 1
) { ) {
override fun runExperiment(load: LoadDimension, res: Resource): Boolean { override fun runExperiment(load: LoadDimension, res: Resource): Boolean {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment