Use camelCase propNames in ide perf tests json stats; report hasError

This commit is contained in:
Vladimir Dolzhenko
2020-10-13 15:16:23 +02:00
parent bc6693fa6e
commit 5ca4c2ce1a
2 changed files with 70 additions and 44 deletions
@@ -43,20 +43,25 @@ class Stats(
val calcMean = calcMean(timingsMs) val calcMean = calcMean(timingsMs)
val metricChildren = mutableListOf<Metric>() val metricChildren = mutableListOf<Metric>()
val metric = Metric(id, calcMean.mean.toLong(), measurementError = calcMean.stdDev.toLong(), children = metricChildren) val hasError = rawMetricChildren.any { it.hasError }
val metric = Metric(
id, value = calcMean.mean.toLong(), measurementError = calcMean.stdDev.toLong(),
hasError = hasError, children = metricChildren
)
metrics.add(metric) metrics.add(metric)
metricChildren.add( metricChildren.add(
Metric( Metric(
"", calcMean.mean.toLong(), "", calcMean.mean.toLong(),
hasError = hasError,
measurementError = calcMean.stdDev.toLong(), measurementError = calcMean.stdDev.toLong(),
childrenName = "raw_metrics", children = rawMetricChildren childrenName = "rawMetrics", children = rawMetricChildren
) )
) )
metricChildren.add(Metric("mean", calcMean.mean.toLong())) metricChildren.add(Metric("mean", calcMean.mean.toLong()))
// keep geomMean for bwc // keep geomMean for bwc
metricChildren.add(Metric(GEOM_MEAN, calcMean.geomMean.toLong())) metricChildren.add(Metric(GEOM_MEAN, calcMean.geomMean.toLong()))
metricChildren.add(Metric("std_dev", calcMean.stdDev.toLong())) metricChildren.add(Metric("stdDev", calcMean.stdDev.toLong()))
statInfosArray.filterNotNull() statInfosArray.filterNotNull()
.map { it.keys } .map { it.keys }
@@ -128,34 +133,43 @@ class Stats(
) )
val block = { val block = {
val metricChildren = mutableListOf<Metric>() val metricChildren = mutableListOf<Metric>()
warmUpPhase(warmPhaseData, metricChildren) try {
val statInfoArray = mainPhase(mainPhaseData, metricChildren) warmUpPhase(warmPhaseData, metricChildren)
val statInfoArray = mainPhase(mainPhaseData, metricChildren)
assertEquals(iterations, statInfoArray.size) assertEquals(iterations, statInfoArray.size)
if (testName != WARM_UP) { if (testName != WARM_UP) {
// do not estimate stability for warm-up // do not estimate stability for warm-up
if (!testName.contains(WARM_UP)) { if (!testName.contains(WARM_UP)) {
val calcMean = calcMean(statInfoArray) val calcMean = calcMean(statInfoArray)
val stabilityPercentage = round(calcMean.stdDev * 100.0 / calcMean.mean).toInt() val stabilityPercentage = round(calcMean.stdDev * 100.0 / calcMean.mean).toInt()
logMessage { "$testName stability is $stabilityPercentage %" } logMessage { "$testName stability is $stabilityPercentage %" }
val stabilityName = "$name: $testName stability" val stabilityName = "$name: $testName stability"
val stable = stabilityPercentage <= acceptanceStabilityLevel val stable = stabilityPercentage <= acceptanceStabilityLevel
val error = if (stable or !checkStability) { val error = if (stable or !checkStability) {
null null
} else { } else {
"$testName stability is $stabilityPercentage %, above accepted level of $acceptanceStabilityLevel %" "$testName stability is $stabilityPercentage %, above accepted level of $acceptanceStabilityLevel %"
}
TeamCity.test(stabilityName, errorDetails = error, includeStats = false) {
metricChildren.add(Metric("stability", stabilityPercentage))
}
} }
TeamCity.test(stabilityName, errorDetails = error, includeStats = false) { processTimings(testName, statInfoArray, metricChildren)
metricChildren.add(Metric("stability", stabilityPercentage)) } else {
} convertStatInfoIntoMetrics(
testName,
printOnlyErrors = true,
statInfoArray = statInfoArray,
metricChildren = metricChildren
)
} }
} catch (e: Exception) {
processTimings(testName, statInfoArray, metricChildren) processTimings(testName, emptyArray(), metricChildren)
} else {
convertStatInfoIntoMetrics(testName, printOnlyErrors = true, statInfoArray = statInfoArray, metricChildren = metricChildren)
} }
} }
@@ -184,6 +198,7 @@ class Stats(
val t = statInfo[ERROR_KEY] as? Throwable val t = statInfo[ERROR_KEY] as? Throwable
if (t != null) { if (t != null) {
TeamCity.test(n, errors = listOf(t)) {} TeamCity.test(n, errors = listOf(t)) {}
metricChildren.add(Metric(attemptString, value = null, hasError = true))
} else if (!printOnlyErrors) { } else if (!printOnlyErrors) {
val durationMs = (statInfo[TEST_KEY] as Long).nsToMs val durationMs = (statInfo[TEST_KEY] as Long).nsToMs
TeamCity.test(n, durationMs = durationMs, includeStats = false) { TeamCity.test(n, durationMs = durationMs, includeStats = false) {
@@ -211,8 +226,11 @@ class Stats(
statInfosArray: Array<StatInfos>, statInfosArray: Array<StatInfos>,
metricChildren: MutableList<Metric> metricChildren: MutableList<Metric>
) { ) {
convertStatInfoIntoMetrics(prefix, statInfosArray, metricChildren = metricChildren) try {
calcAndProcessMetrics(prefix, statInfosArray, metricChildren) convertStatInfoIntoMetrics(prefix, statInfosArray, metricChildren = metricChildren)
} finally {
calcAndProcessMetrics(prefix, statInfosArray, metricChildren)
}
} }
private fun <SV, TV> warmUpPhase(phaseData: PhaseData<SV, TV>, metricChildren: MutableList<Metric>) { private fun <SV, TV> warmUpPhase(phaseData: PhaseData<SV, TV>, metricChildren: MutableList<Metric>) {
@@ -347,24 +365,24 @@ class Stats(
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
simpleDateFormat.timeZone = TimeZone.getTimeZone("UTC") simpleDateFormat.timeZone = TimeZone.getTimeZone("UTC")
// properties["build_timestamp"] = simpleDateFormat.format(Date()) // properties["buildTimestamp"] = simpleDateFormat.format(Date())
// properties["build_id"] = 87015694 // properties["buildId"] = 87015694
// properties["build_branch"] = "rr/perf/json-output" // properties["buildBranch"] = "rr/perf/json-output"
// properties["agent_name"] = "kotlin-linux-perf-unit879" // properties["agentName"] = "kotlin-linux-perf-unit879"
System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE")?.let { teamcityConfig -> System.getenv("TEAMCITY_BUILD_PROPERTIES_FILE")?.let { teamcityConfig ->
val buildProperties = Properties() val buildProperties = Properties()
buildProperties.load(FileInputStream(teamcityConfig)) buildProperties.load(FileInputStream(teamcityConfig))
properties["build.timestamp"] = simpleDateFormat.format(Date()) properties["buildTimestamp"] = simpleDateFormat.format(Date())
for ((name, key) in for ((name, key) in
mapOf( mapOf(
"build_id" to "teamcity.build.id", "buildId" to "teamcity.build.id",
"build_branch" to "teamcity.build.branch", "buildBranch" to "teamcity.build.branch",
"agent_name" to "agent.name", "agentName" to "agent.name",
)) { )) {
val property = buildProperties.getProperty(key) val property = buildProperties.getProperty(key)
properties[name] = if (name == "build_id") property.toLong() else property properties[name] = if (name == "buildId") property.toLong() else property
} }
} }
if (perfTestRawDataMs.isNotEmpty()) { if (perfTestRawDataMs.isNotEmpty()) {
@@ -400,6 +418,7 @@ class Stats(
data class Metric( data class Metric(
val name: String, val name: String,
val value: Number?, val value: Number?,
val hasError: Boolean = false,
val measurementError: Number? = null, val measurementError: Number? = null,
val childrenName: String = "metrics", val childrenName: String = "metrics",
val children: MutableList<Metric> = mutableListOf(), val children: MutableList<Metric> = mutableListOf(),
@@ -27,7 +27,7 @@ internal fun List<Metric>.writeCSV(name: String, header: Array<String>) {
} }
} }
internal fun Metric.writeTeamCityStats(name: String, rawMeasurementName: String = "raw_metrics", rawMetrics: Boolean = false) { internal fun Metric.writeTeamCityStats(name: String, rawMeasurementName: String = "rawMetrics", rawMetrics: Boolean = false) {
fun Metric.append(prefix: String, depth: Int) { fun Metric.append(prefix: String, depth: Int) {
val s = if (this.name.isEmpty()) { val s = if (this.name.isEmpty()) {
prefix prefix
@@ -74,17 +74,24 @@ private fun Metric.toJson(prefix: String): String =
"$prefix $name${if (prefix.isEmpty()) ":" else ""}".trim() "$prefix $name${if (prefix.isEmpty()) ":" else ""}".trim()
} }
var commaRequired = false var commaRequired = false
if (value != null) { if (value != null || hasError) {
append("\"metric_name\":\"").append(nm).append("\"") append("\"metricName\":\"").append(nm).append("\"")
append(",\"metric_value\":").append(value)
measurementError?.let {
append(",\"metric_error\":").append(it)
}
//append(",\"legacy_name\":").append("\"${s.jsonValue()}\"")
commaRequired = true commaRequired = true
} }
if (value != null) {
append(",\"metricValue\":").append(value)
measurementError?.let {
append(",\"metricError\":").append(it)
}
//append(",\"legacyName\":").append("\"${s.jsonValue()}\"")
}
if (hasError) {
append(",\"hasError\": $hasError")
}
if (properties != null) { if (properties != null) {
for ((k, v) in properties) { for ((k, v) in properties) {
if (commaRequired) append(",") if (commaRequired) append(",")