Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix: Downloading performance Metrics #1326

Merged
merged 8 commits into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions integration_tests/src/test/kotlin/utils/TestsConsts.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package utils

const val defaultAndroidOutputPattern = "AndroidArgs.*?" +
"gcloud:.*?" +
"flank:.*?" +
"RunTests.*?" +
"Matrices webLink.*?" +
"matrix-.*?" +
"FetchArtifacts.*?" +
"Updating matrix file.*?" +
"CostReport.*?MatrixResultsReport.*?" +
"1 test cases passed, 1 skipped.*?" +
"Uploading JUnitReport.xml ."
const val defaultAndroidOutputPattern = "AndroidArgs\\s*" +
"gcloud:[\\s\\S]*" +
"flank:[\\s\\S]*" +
"RunTests[\\s\\S]*" +
"Matrices webLink[\\s\\S]*" +
"matrix-[\\s\\S]*" +
"CostReport[\\s\\S]*" +
"MatrixResultsReport[\\s\\S]*" +
"1 test cases passed, 1 skipped[\\s\\S]*" +
"Uploading JUnitReport.xml[\\s\\S]*" +
"FetchArtifacts[\\s\\S]*" +
"Updating matrix file"

const val defaultIosOutputPattern = "IosArgs.*?" +
"gcloud:.*?" +
Expand Down
8 changes: 3 additions & 5 deletions test_runner/src/main/kotlin/ftl/gc/GcStorage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,10 @@ object GcStorage {
}
}

fun uploadPerformanceMetrics(perfMetricsSummary: PerfMetricsSummary, resultsBucket: String, resultDir: String) {
val performanceMetricsFileName = "performanceMetrics.json"
fun uploadPerformanceMetrics(perfMetricsSummary: PerfMetricsSummary, resultsBucket: String, resultDir: String) =
runCatching {
upload(
performanceMetricsFileName,
"performanceMetrics.json",
perfMetricsSummary.toPrettyString().toByteArray(),
resultsBucket,
resultDir
Expand All @@ -98,8 +97,7 @@ object GcStorage {
println("Cannot upload performance metrics ${it.message}")
}.onSuccess {
println("Performance metrics uploaded to https://console.developers.google.com/storage/browser/$resultsBucket/$resultDir")
}
}
}.getOrNull()

fun uploadReportResult(testResult: String, args: IArgs, fileName: String) {
if (args.resultsBucket.isBlank() || args.resultsDir.isBlank() || args.disableResultsUpload) return
Expand Down
18 changes: 16 additions & 2 deletions test_runner/src/main/kotlin/ftl/reports/api/PerformanceMetrics.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,39 @@ package ftl.reports.api
import com.google.api.services.testing.model.TestExecution
import com.google.api.services.toolresults.model.PerfMetricsSummary
import ftl.android.AndroidCatalog
import ftl.args.IArgs
import ftl.gc.GcStorage
import ftl.gc.GcToolResults
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import java.nio.file.Files
import java.nio.file.Paths

internal fun List<Pair<TestExecution, String>>.getAndUploadPerformanceMetrics(
resultBucket: String
args: IArgs
) = runBlocking {
filterAndroidPhysicalDevicesRuns()
.map { (testExecution, gcsStoragePath) ->
async(Dispatchers.IO) {
testExecution.getPerformanceMetric().upload(resultBucket = resultBucket, resultDir = gcsStoragePath)
val performanceMetrics = testExecution.getPerformanceMetric()
performanceMetrics.save(gcsStoragePath, args)
performanceMetrics.upload(resultBucket = args.resultsBucket, resultDir = gcsStoragePath)
}
}
.awaitAll()
}

private fun PerfMetricsSummary.save(resultsDir: String, args: IArgs) {
val configFilePath =
if (args.useLocalResultDir()) Paths.get(args.localResultDir, "performanceMetrics.json")
else Paths.get(args.localResultDir, resultsDir, "performanceMetrics.json")

configFilePath.parent.toFile().mkdirs()
Files.write(configFilePath, toPrettyString().toByteArray())
}

private fun List<Pair<TestExecution, String>>.filterAndroidPhysicalDevicesRuns() = filterNot { (testExecution, _) ->
AndroidCatalog.isVirtualDevice(testExecution.environment.androidDevice, testExecution.projectId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,7 @@ object ReportManager {
) {
testExecutions
.takeIf { args is AndroidArgs }
?.run {
withGcsStoragePath(matrices, args.resultsDir).getAndUploadPerformanceMetrics(args.resultsBucket)
}
?.run { withGcsStoragePath(matrices, args.resultsDir).getAndUploadPerformanceMetrics(args) }
}

private fun List<TestExecution>.withGcsStoragePath(
Expand Down
3 changes: 1 addition & 2 deletions test_runner/src/main/kotlin/ftl/run/NewTestRun.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ suspend fun newTestRun(args: IArgs) = withTimeoutOrNull(args.parsedTimeout) {

if (!args.async) {
cancelTestsOnTimeout(args.project, matrixMap.map) { pollMatrices(matrixMap.map.keys, args).updateMatrixMap(matrixMap) }
cancelTestsOnTimeout(args.project, matrixMap.map) { fetchArtifacts(matrixMap, args) }

ReportManager.generate(matrixMap, args, testShardChunks, ignoredTests)
cancelTestsOnTimeout(args.project, matrixMap.map) { fetchArtifacts(matrixMap, args) }

println()
matrixMap.printMatricesWebLinks(args.project)
Expand Down
4 changes: 2 additions & 2 deletions test_runner/src/main/kotlin/ftl/run/common/FetchArtifacts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ internal fun getDownloadPath(args: IArgs, blobPath: String): Path {
val objName = if (args.useLocalResultDir()) "" else parsed.getName(0).toString()
// for iOS it is shardName, remove this comment after FTL introduce server side sharding for iOS
val matrixName = parsed.getName(1).toString()
val deviceName = parsed.getName(2).toString()
val filePathName = if (args.keepFilePath) parsed.parent.drop(3).joinToString("/") else ""
val fileName = parsed.fileName.toString()
val deviceName = parsed.getName(2).toString().takeUnless { it == fileName }.orEmpty()
val filePathName = if (args.keepFilePath) parsed.parent.drop(3).joinToString("/") else ""

return Paths.get("$localDir/$objName/$matrixName/$deviceName/$filePathName/$fileName")
}
4 changes: 2 additions & 2 deletions test_runner/src/test/kotlin/ftl/gc/GcStorageTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ class GcStorageTest {
.setAppStartTime(AppStartTime().setInitialDisplayTime(Duration().setSeconds(5)))

// when
GcStorage.uploadPerformanceMetrics(expectedPerformanceMetrics, "bucket", "path/test")
val filePath = GcStorage.uploadPerformanceMetrics(expectedPerformanceMetrics, "bucket", "path/test")

// then
assertTrue(GcStorage.exist("gs://bucket/path/test/performanceMetrics.json"))
assertTrue(GcStorage.exist(filePath.orEmpty()))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.google.api.services.testing.model.TestExecution
import com.google.api.services.testing.model.ToolResultsStep
import com.google.common.truth.Truth.assertThat
import ftl.android.AndroidCatalog
import ftl.args.IArgs
import ftl.gc.GcStorage
import ftl.gc.GcToolResults
import ftl.test.util.FlankTestRunner
Expand All @@ -27,8 +28,11 @@ class PerformanceMetricsTest {
fun `should not get and upload performance metrics for virtual devices`() {
mockkObject(AndroidCatalog) {
every { AndroidCatalog.isVirtualDevice(any<AndroidDevice>(), any()) } returns true
val args = mockk<IArgs> {
every { resultsBucket } returns "b8ce"
}

assertThat(testExecutions.map { it to "path" }.getAndUploadPerformanceMetrics("b8ce")).isEmpty()
assertThat(testExecutions.map { it to "path" }.getAndUploadPerformanceMetrics(args)).isEmpty()
}
}

Expand All @@ -44,7 +48,12 @@ class PerformanceMetricsTest {
}

mockkObject(GcStorage) {
testExecutions.map { it to expectedPath }.getAndUploadPerformanceMetrics(expectedBucket)
val args = mockk<IArgs> {
every { resultsBucket } returns expectedBucket
every { useLocalResultDir() } returns false
every { localResultDir } returns "local"
}
testExecutions.map { it to expectedPath }.getAndUploadPerformanceMetrics(args)
performanceMetrics.forEach {
verify { GcStorage.uploadPerformanceMetrics(it, expectedBucket, expectedPath) }
}
Expand Down