From 117c99aee6d5b6d24e25346d449c0a1299d2d369 Mon Sep 17 00:00:00 2001 From: "nataliya.valtman" Date: Tue, 25 May 2021 13:09:00 +0300 Subject: [PATCH] send build stat to ES --- .../jetbrains/kotlin/cli/common/Properties.kt | 6 ++ .../plugin/KotlinGradleBuildServices.kt | 6 ++ .../statistics/KotlinBuildEsStatListener.kt | 46 +++++++++++++++ .../plugin/statistics/ReportStatistics.kt | 20 +++++++ .../ReportStatisticsToElasticSearch.kt | 58 +++++++++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildEsStatListener.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatistics.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatisticsToElasticSearch.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt index 71bb2eeca62..987a897933c 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/Properties.kt @@ -36,6 +36,12 @@ enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY("kotlin.environment.keepalive"), COMPILE_DAEMON_CUSTOM_RUN_FILES_PATH_FOR_TESTS("kotlin.daemon.custom.run.files.path.for.tests"), KOTLIN_COLORS_ENABLED_PROPERTY("kotlin.colors.enabled"), + + KOTLIN_STAT_ENABLED_PROPERTY("kotlin.plugin.stat.enabled"), + KOTLIN_STAT_ENDPOINT_PROPERTY("kotlin.plugin.stat.endpoint"), + KOTLIN_STAT_USER_PROPERTY("kotlin.plugin.stat.user"), + KOTLIN_STAT_PASSWORD_PROPERTY("kotlin.plugin.stat.password"), + OS_NAME("os.name", alwaysDirectAccess = true), TMP_DIR("java.io.tmpdir"), USER_HOME("user.home", alwaysDirectAccess = true), diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt index 1d876744701..f855f14b76b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt @@ -13,6 +13,7 @@ import org.gradle.api.logging.Logging import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers +import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildEsStatListener import org.jetbrains.kotlin.gradle.report.configureReporting import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable @@ -64,6 +65,9 @@ internal class KotlinGradleBuildServices private constructor( val kotlinGradleListenerProvider: org.gradle.api.provider.Provider = project.provider { KotlinGradleBuildListener(KotlinGradleFinishBuildHandler()) } + val kotlinGradleEsListenerProvider = project.provider { + KotlinBuildEsStatListener(project.name) + } if (instance != null) { log.kotlinDebug(ALREADY_INITIALIZED_MESSAGE) @@ -74,6 +78,7 @@ internal class KotlinGradleBuildServices private constructor( val services = KotlinGradleBuildServices(gradle) if (isConfigurationCacheAvailable(gradle)) { listenerRegistryHolder.listenerRegistry!!.onTaskCompletion(kotlinGradleListenerProvider) + listenerRegistryHolder.listenerRegistry.onTaskCompletion(kotlinGradleEsListenerProvider) } else { gradle.addBuildListener(services) log.kotlinDebug(INIT_MESSAGE) @@ -103,6 +108,7 @@ internal class KotlinGradleBuildServices private constructor( override fun buildFinished(result: BuildResult) { buildHandler!!.buildFinished(result.gradle!!) + KotlinBuildEsStatListener(result.gradle!!.rootProject.name).onFinish(result) instance = null log.kotlinDebug(DISPOSE_MESSAGE) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildEsStatListener.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildEsStatListener.kt new file mode 100644 index 00000000000..a404310ee9a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildEsStatListener.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.plugin.statistics + +import org.gradle.BuildResult +import org.gradle.tooling.events.FinishEvent +import org.gradle.tooling.events.OperationCompletionListener +import org.gradle.tooling.events.task.* +import org.jetbrains.kotlin.gradle.plugin.stat.CompileStatData +import org.jetbrains.kotlin.gradle.plugin.stat.ReportStatistics + +class KotlinBuildEsStatListener(val projectName: String) : OperationCompletionListener, AutoCloseable { + val reportStatistics: ReportStatistics = ReportStatisticsToElasticSearch + + override fun onFinish(event: FinishEvent?) { + if (event is TaskFinishEvent) { + val result = event.result + val taskPath = event.descriptor.taskPath + val taskResult = when (result) { + is TaskSuccessResult -> if (result.isFromCache) "FROM CACHE" else if (result.isUpToDate) "UP TO DATE" else "SUCCESS" + is TaskSkippedResult -> "SKIPPED" + is TaskFailureResult -> "FAILED" + else -> "UNKNOWN" + } + +// BuildTime.children.forEach() + + val compileStatData = CompileStatData( + duration = event.result.endTime - event.result.startTime, taskResult = taskResult, + statData = emptyMap(), projectName = projectName, taskName = taskPath + ) + reportStatistics.report(compileStatData) + } + } + + fun onFinish(result: BuildResult) { +// onFinish(result) + } + + + override fun close() { + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatistics.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatistics.kt new file mode 100644 index 00000000000..290ed05e027 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatistics.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.plugin.stat + +data class CompileStatData( + val version: Int = 1, + val projectName: String?, + val taskName: String?, + val taskResult: String, + val duration: Long, + val statData: Map +) + +interface ReportStatistics { + fun report(data: CompileStatData) +} + diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatisticsToElasticSearch.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatisticsToElasticSearch.kt new file mode 100644 index 00000000000..b696c8dea84 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/ReportStatisticsToElasticSearch.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.plugin.statistics + +import com.google.gson.Gson +import org.jetbrains.kotlin.cli.common.CompilerSystemProperties +import org.jetbrains.kotlin.cli.common.toBooleanLenient +import org.jetbrains.kotlin.gradle.plugin.stat.ReportStatistics +import org.jetbrains.kotlin.gradle.plugin.stat.CompileStatData +import java.net.HttpURLConnection +import java.net.URL +import java.util.* + +object ReportStatisticsToElasticSearch : ReportStatistics { + val url = CompilerSystemProperties.KOTLIN_STAT_ENDPOINT_PROPERTY.value + val user = CompilerSystemProperties.KOTLIN_STAT_USER_PROPERTY.value + val enable: Boolean = CompilerSystemProperties.KOTLIN_STAT_ENABLED_PROPERTY.value?.toBooleanLenient() ?: false + + //TODO Do not store password as string + val password = CompilerSystemProperties.KOTLIN_STAT_PASSWORD_PROPERTY.value + + override fun report(data: CompileStatData) { + if (!enable) { + return; + } + val connection = URL(url).openConnection() as HttpURLConnection + try { + if (user != null && password != null) { + val auth = Base64.getEncoder() + .encode("$user:$password".toByteArray()).toString(Charsets.UTF_8) + connection.addRequestProperty("Authorization", "Basic $auth") + } + connection.addRequestProperty("Content-Type", "application/json") + connection.requestMethod = "POST" + connection.doOutput = true + connection.outputStream.use { + it.write(Gson().toJson(data).toByteArray()) + } + connection.connect(); + checkResponseAndLog(connection) + connection.inputStream.use { it.reader().use { reader -> reader.readText() } } + } finally { + connection.disconnect() + } + } + + private fun checkResponseAndLog(connection: HttpURLConnection) { + val isResponseBad = connection.responseCode !in 200..299 + if (isResponseBad) { + throw Exception( + "Failed to send statistic to ${connection.url}: ${connection.responseMessage}" + ) + } + } +}