Skip to content
Snippets Groups Projects
Commit cbae6dfe authored by Benedikt Wetzel's avatar Benedikt Wetzel Committed by Sören Henning
Browse files

Load executionID from file

parent e82c7d04
No related branches found
No related tags found
4 merge requests!159Re-implementation of Theodolite with Kotlin/Quarkus,!157Update Graal Image in CI pipeline,!138Load execution ID from file,!83WIP: Re-implementation of Theodolite with Kotlin/Quarkus
...@@ -2,6 +2,7 @@ package theodolite.evaluation ...@@ -2,6 +2,7 @@ package theodolite.evaluation
import mu.KotlinLogging import mu.KotlinLogging
import theodolite.benchmark.BenchmarkExecution import theodolite.benchmark.BenchmarkExecution
import theodolite.util.IOHandler
import theodolite.util.LoadDimension import theodolite.util.LoadDimension
import theodolite.util.Resource import theodolite.util.Resource
import java.text.Normalizer import java.text.Normalizer
...@@ -44,15 +45,14 @@ class AnalysisExecutor( ...@@ -44,15 +45,14 @@ class AnalysisExecutor(
query = "sum by(group)(kafka_consumergroup_group_lag >= 0)" query = "sum by(group)(kafka_consumergroup_group_lag >= 0)"
) )
var resultsFolder: String = System.getenv("RESULTS_FOLDER") val ioHandler = IOHandler()
if (resultsFolder.isNotEmpty()){ val resultsFolder: String = ioHandler.getResultFolderURL()
resultsFolder += "/" val fileURL = "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}"
} ioHandler.writeToCSVFile(
fileURL = fileURL,
data = prometheusData.getResultAsList(),
columns = listOf("group", "timestamp", "value"))
CsvExporter().toCsv(
name = "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}",
prom = prometheusData
)
val sloChecker = SloCheckerFactory().create( val sloChecker = SloCheckerFactory().create(
sloType = slo.sloType, sloType = slo.sloType,
externalSlopeURL = slo.externalSloUrl, externalSlopeURL = slo.externalSloUrl,
......
package theodolite.evaluation
import mu.KotlinLogging
import theodolite.util.PrometheusResponse
import java.io.File
import java.io.PrintWriter
import java.util.*
private val logger = KotlinLogging.logger {}
/**
* Used to document the data received from prometheus for additional offline analysis.
*/
class CsvExporter {
/**
* Uses the [PrintWriter] to transform a [PrometheusResponse] to a CSV file.
* @param name of the file.
* @param prom Response that is documented.
*
*/
fun toCsv(name: String, prom: PrometheusResponse) {
val responseArray = promResponseToList(prom)
val csvOutputFile = File("$name.csv")
PrintWriter(csvOutputFile).use { pw ->
pw.println(listOf("group", "timestamp", "value").joinToString(separator=","))
responseArray.forEach {
pw.println(it.joinToString(separator=","))
}
}
logger.info { "Wrote CSV file: $name to ${csvOutputFile.absolutePath}." }
}
/**
* Converts a [PrometheusResponse] into a [List] of [List]s of [String]s
*/
private fun promResponseToList(prom: PrometheusResponse): List<List<String>> {
val name = prom.data?.result?.get(0)?.metric?.group.toString()
val values = prom.data?.result?.get(0)?.values
val dataList = mutableListOf<List<String>>()
if (values != null) {
for (maybeValuePair in values) {
val valuePair = maybeValuePair as List<*>
val timestamp = (valuePair[0] as Double).toLong().toString()
val value = valuePair[1].toString()
dataList.add(listOf(name, timestamp, value))
}
}
return Collections.unmodifiableList(dataList)
}
}
...@@ -7,10 +7,7 @@ import theodolite.benchmark.KubernetesBenchmark ...@@ -7,10 +7,7 @@ import theodolite.benchmark.KubernetesBenchmark
import theodolite.patcher.PatcherDefinitionFactory import theodolite.patcher.PatcherDefinitionFactory
import theodolite.strategies.StrategyFactory import theodolite.strategies.StrategyFactory
import theodolite.strategies.searchstrategy.CompositeStrategy import theodolite.strategies.searchstrategy.CompositeStrategy
import theodolite.util.Config import theodolite.util.*
import theodolite.util.LoadDimension
import theodolite.util.Resource
import theodolite.util.Results
import java.io.File import java.io.File
import java.io.PrintWriter import java.io.PrintWriter
import java.lang.IllegalArgumentException import java.lang.IllegalArgumentException
...@@ -102,34 +99,17 @@ class TheodoliteExecutor( ...@@ -102,34 +99,17 @@ class TheodoliteExecutor(
return this.kubernetesBenchmark return this.kubernetesBenchmark
} }
private fun getResultFolderString(): String {
var resultsFolder: String = System.getenv("RESULTS_FOLDER") ?: ""
val createResultsFolder = System.getenv("CREATE_RESULTS_FOLDER") ?: "false"
if (resultsFolder != ""){
logger.info { "RESULT_FOLDER: $resultsFolder" }
val directory = File(resultsFolder)
if (!directory.exists()) {
logger.error { "Folder $resultsFolder does not exist" }
if (createResultsFolder.toBoolean()) {
directory.mkdirs()
} else {
throw IllegalArgumentException("Result folder not found")
}
}
resultsFolder += "/"
}
return resultsFolder
}
/** /**
* Run all experiments which are specified in the corresponding * Run all experiments which are specified in the corresponding
* execution and benchmark objects. * execution and benchmark objects.
*/ */
fun run() { fun run() {
val resultsFolder = getResultFolderString() val ioHandler = IOHandler()
storeAsFile(this.config, "$resultsFolder${this.config.executionId}-execution-configuration") val resultsFolder = ioHandler.getResultFolderURL()
storeAsFile(kubernetesBenchmark, "$resultsFolder${this.config.executionId}-benchmark-configuration") this.config.executionId = getAndIncrementExecutionID(resultsFolder+"expID.txt")
ioHandler.writeToJSONFile(this.config, "$resultsFolder${this.config.executionId}-execution-configuration")
ioHandler.writeToJSONFile(kubernetesBenchmark, "$resultsFolder${this.config.executionId}-benchmark-configuration")
val config = buildConfig() val config = buildConfig()
// execute benchmarks for each load // execute benchmarks for each load
...@@ -138,14 +118,17 @@ class TheodoliteExecutor( ...@@ -138,14 +118,17 @@ class TheodoliteExecutor(
config.compositeStrategy.findSuitableResource(load, config.resources) config.compositeStrategy.findSuitableResource(load, config.resources)
} }
} }
storeAsFile(config.compositeStrategy.benchmarkExecutor.results, "$resultsFolder${this.config.executionId}-result") ioHandler.writeToJSONFile(config.compositeStrategy.benchmarkExecutor.results, "$resultsFolder${this.config.executionId}-result")
} }
private fun <T> storeAsFile(saveObject: T, filename: String) { private fun getAndIncrementExecutionID(fileURL: String): Int {
val gson = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create() val ioHandler = IOHandler()
var executionID = 0
PrintWriter(filename).use { pw -> if (File(fileURL).exists()) {
pw.println(gson.toJson(saveObject)) executionID = ioHandler.readFileAsString(fileURL).toInt() + 1
} }
ioHandler.writeStringToTextFile(fileURL, (executionID).toString())
return executionID
} }
} }
...@@ -37,7 +37,6 @@ class TheodoliteController( ...@@ -37,7 +37,6 @@ class TheodoliteController(
val executionsQueue: ConcurrentLinkedDeque<BenchmarkExecution> = ConcurrentLinkedDeque() val executionsQueue: ConcurrentLinkedDeque<BenchmarkExecution> = ConcurrentLinkedDeque()
val benchmarks: ConcurrentHashMap<String, KubernetesBenchmark> = ConcurrentHashMap() val benchmarks: ConcurrentHashMap<String, KubernetesBenchmark> = ConcurrentHashMap()
var isUpdated = AtomicBoolean(false) var isUpdated = AtomicBoolean(false)
var executionID = AtomicInteger(0)
/** /**
* Runs the TheodoliteController forever. * Runs the TheodoliteController forever.
...@@ -91,7 +90,6 @@ class TheodoliteController( ...@@ -91,7 +90,6 @@ class TheodoliteController(
*/ */
@Synchronized @Synchronized
fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) { fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) {
execution.executionId = executionID.getAndSet(executionID.get() + 1)
isUpdated.set(false) isUpdated.set(false)
benchmark.path = path benchmark.path = path
logger.info { "Start execution ${execution.name} with benchmark ${benchmark.name}." } logger.info { "Start execution ${execution.name} with benchmark ${benchmark.name}." }
......
package theodolite.util
import com.google.gson.GsonBuilder
import mu.KotlinLogging
import java.io.File
import java.io.PrintWriter
import java.lang.IllegalArgumentException
private val logger = KotlinLogging.logger {}
/**
* The IOHandler handles most common I/O operations within the Theodolite framework
*/
class IOHandler {
/**
* The location in which Theodolite store result and configuration file are depends on
* the values of the environment variables `RESULT_FOLDER` and `CREATE_RESULTS_FOLDER`
*
* @return the URL of the result folder
*/
fun getResultFolderURL(): String {
var resultsFolder: String = System.getenv("RESULTS_FOLDER") ?: ""
val createResultsFolder = System.getenv("CREATE_RESULTS_FOLDER") ?: "false"
if (resultsFolder != ""){
logger.info { "RESULT_FOLDER: $resultsFolder" }
val directory = File(resultsFolder)
if (!directory.exists()) {
logger.error { "Folder $resultsFolder does not exist" }
if (createResultsFolder.toBoolean()) {
directory.mkdirs()
} else {
throw IllegalArgumentException("Result folder not found")
}
}
resultsFolder += "/"
}
return resultsFolder
}
/**
* Read a file as String
*
* @param fileURL the URL of the file
* @return The content of the file as String
*/
fun readFileAsString(fileURL: String): String {
return File(fileURL).inputStream().readBytes().toString(Charsets.UTF_8).trim()
}
/**
* Creates a JSON string of the given object and store them to file
*
* @param T class of the object to save
* @param objectToSave object which should be saved as file
* @param fileURL the URL of the file
*/
fun <T> writeToJSONFile(objectToSave: T, fileURL: String) {
val gson = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create()
writeStringToTextFile(fileURL, gson.toJson(objectToSave))
}
/**
* Write to CSV file
*
* @param fileURL the URL of the file
* @param data the data to write in the file, as list of list, each subList corresponds to a row in the CSV file
* @param columns columns of the CSV file
*/
fun writeToCSVFile(fileURL: String, data: List<List<String>>, columns: List<String>) {
val outputFile = File("$fileURL.csv")
PrintWriter(outputFile).use { pw ->
pw.println(columns.joinToString(separator=","))
data.forEach {
pw.println(it.joinToString(separator=","))
}
}
logger.info { "Wrote CSV file: $fileURL to ${outputFile.absolutePath}." }
}
/**
* Write to text file
*
* @param fileURL the URL of the file
* @param data the data to write in the file as String
*/
fun writeStringToTextFile(fileURL: String, data: String) {
val outputFile = File("$fileURL")
outputFile.printWriter().use {
it.println(data)
}
logger.info { "Wrote txt file: $fileURL to ${outputFile.absolutePath}." }
}
}
\ No newline at end of file
package theodolite.util package theodolite.util
import io.quarkus.runtime.annotations.RegisterForReflection import io.quarkus.runtime.annotations.RegisterForReflection
import java.util.*
/** /**
* This class corresponds to the JSON response format of a Prometheus * This class corresponds to the JSON response format of a Prometheus
...@@ -17,6 +18,27 @@ data class PrometheusResponse( ...@@ -17,6 +18,27 @@ data class PrometheusResponse(
*/ */
var data: PromData? = null var data: PromData? = null
) )
{
/**
* Return the data of the PrometheusResponse as [List] of [List]s of [String]s
* The format of the returned list is: `[[ group, timestamp, value ], [ group, timestamp, value ], ... ]`
*/
fun getResultAsList(): List<List<String>> {
val group = data?.result?.get(0)?.metric?.group.toString()
val values = data?.result?.get(0)?.values
val result = mutableListOf<List<String>>()
if (values != null) {
for (value in values) {
val valueList = value as List<*>
val timestamp = (valueList[0] as Double).toLong().toString()
val value = valueList[1].toString()
result.add(listOf(group, timestamp, value))
}
}
return Collections.unmodifiableList(result)
}
}
/** /**
* Description of Prometheus data. * Description of Prometheus data.
...@@ -56,4 +78,5 @@ data class PromResult( ...@@ -56,4 +78,5 @@ data class PromResult(
@RegisterForReflection @RegisterForReflection
data class PromMetric( data class PromMetric(
var group: String? = null var group: String? = null
) )
\ No newline at end of file
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