Update statistics that should be sent to ES

Next properties should be set in gradle.properties or via -D option:
systemProp.kotlin.plugin.stat.password
systemProp.kotlin.plugin.stat.user
systemProp.kotlin.plugin.stat.enabled=true
systemProp.kotlin.plugin.stat.label
systemProp.kotlin.plugin.stat.endpoint=es_endpoint/index/_doc
kotlin.build.report.verbose=true
kotlin.build.report.enable=true
This commit is contained in:
nataliya.valtman
2021-06-11 14:43:16 +03:00
parent bf077b893c
commit d42a6771b0
5 changed files with 67 additions and 23 deletions
@@ -41,6 +41,7 @@ enum class CompilerSystemProperties(val property: String, val alwaysDirectAccess
KOTLIN_STAT_ENDPOINT_PROPERTY("kotlin.plugin.stat.endpoint"), KOTLIN_STAT_ENDPOINT_PROPERTY("kotlin.plugin.stat.endpoint"),
KOTLIN_STAT_USER_PROPERTY("kotlin.plugin.stat.user"), KOTLIN_STAT_USER_PROPERTY("kotlin.plugin.stat.user"),
KOTLIN_STAT_PASSWORD_PROPERTY("kotlin.plugin.stat.password"), KOTLIN_STAT_PASSWORD_PROPERTY("kotlin.plugin.stat.password"),
KOTLIN_STAT_LABEl_PROPERTY("kotlin.plugin.stat.label"),
OS_NAME("os.name", alwaysDirectAccess = true), OS_NAME("os.name", alwaysDirectAccess = true),
TMP_DIR("java.io.tmpdir"), TMP_DIR("java.io.tmpdir"),
@@ -66,7 +66,7 @@ internal class KotlinGradleBuildServices private constructor(
KotlinGradleBuildListener(KotlinGradleFinishBuildHandler()) KotlinGradleBuildListener(KotlinGradleFinishBuildHandler())
} }
val kotlinGradleEsListenerProvider = project.provider { val kotlinGradleEsListenerProvider = project.provider {
KotlinBuildEsStatListener(project.name) KotlinBuildEsStatListener(project.rootProject.name)
} }
if (instance != null) { if (instance != null) {
@@ -81,6 +81,7 @@ internal class KotlinGradleBuildServices private constructor(
listenerRegistryHolder.listenerRegistry.onTaskCompletion(kotlinGradleEsListenerProvider) listenerRegistryHolder.listenerRegistry.onTaskCompletion(kotlinGradleEsListenerProvider)
} else { } else {
gradle.addBuildListener(services) gradle.addBuildListener(services)
gradle.taskGraph.addTaskExecutionListener(kotlinGradleEsListenerProvider.get())
log.kotlinDebug(INIT_MESSAGE) log.kotlinDebug(INIT_MESSAGE)
} }
instance = services instance = services
@@ -108,7 +109,6 @@ internal class KotlinGradleBuildServices private constructor(
override fun buildFinished(result: BuildResult) { override fun buildFinished(result: BuildResult) {
buildHandler!!.buildFinished(result.gradle!!) buildHandler!!.buildFinished(result.gradle!!)
KotlinBuildEsStatListener(result.gradle!!.rootProject.name).onFinish(result)
instance = null instance = null
log.kotlinDebug(DISPOSE_MESSAGE) log.kotlinDebug(DISPOSE_MESSAGE)
} }
@@ -5,42 +5,80 @@
package org.jetbrains.kotlin.gradle.plugin.statistics package org.jetbrains.kotlin.gradle.plugin.statistics
import org.gradle.BuildResult import org.gradle.api.Task
import org.gradle.api.execution.TaskExecutionListener
import org.gradle.api.tasks.TaskState
import org.gradle.tooling.events.FinishEvent import org.gradle.tooling.events.FinishEvent
import org.gradle.tooling.events.OperationCompletionListener import org.gradle.tooling.events.OperationCompletionListener
import org.gradle.tooling.events.task.* import org.gradle.tooling.events.task.*
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
import org.jetbrains.kotlin.gradle.plugin.stat.CompileStatData import org.jetbrains.kotlin.gradle.plugin.stat.CompileStatData
import org.jetbrains.kotlin.gradle.plugin.stat.ReportStatistics import org.jetbrains.kotlin.gradle.plugin.stat.ReportStatistics
class KotlinBuildEsStatListener(val projectName: String) : OperationCompletionListener, AutoCloseable { enum class TaskExecutionState {
SKIPPED,
FAILED,
UNKNOWN,
SUCCESS,
FROM_CACHE,
UP_TO_DATE
;
}
class KotlinBuildEsStatListener(val projectName: String) : OperationCompletionListener, AutoCloseable, TaskExecutionListener {
val reportStatistics: ReportStatistics = ReportStatisticsToElasticSearch val reportStatistics: ReportStatistics = ReportStatisticsToElasticSearch
val label by lazy { CompilerSystemProperties.KOTLIN_STAT_LABEl_PROPERTY.value }
override fun onFinish(event: FinishEvent?) { override fun onFinish(event: FinishEvent?) {
if (event is TaskFinishEvent) { if (event is TaskFinishEvent) {
val result = event.result val result = event.result
val taskPath = event.descriptor.taskPath val taskPath = event.descriptor.taskPath
val duration = event.result.endTime - event.result.startTime
val taskResult = when (result) { val taskResult = when (result) {
is TaskSuccessResult -> if (result.isFromCache) "FROM CACHE" else if (result.isUpToDate) "UP TO DATE" else "SUCCESS" is TaskSuccessResult -> if (result.isFromCache) TaskExecutionState.FROM_CACHE
is TaskSkippedResult -> "SKIPPED" else if (result.isUpToDate) TaskExecutionState.UP_TO_DATE
is TaskFailureResult -> "FAILED" else TaskExecutionState.SUCCESS
else -> "UNKNOWN"
is TaskSkippedResult -> TaskExecutionState.SKIPPED
is TaskFailureResult -> TaskExecutionState.FAILED
else -> TaskExecutionState.UNKNOWN
} }
// BuildTime.children.forEach() reportData(taskPath, duration, taskResult)
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) { private fun reportData(taskPath: String, duration: Long, taskResult: TaskExecutionState) {
// onFinish(result) val statData = TaskExecutionResults[taskPath]?.buildMetrics?.buildTimes?.asMap()?.mapKeys { (key, _) -> key.name } ?: emptyMap()
val compileStatData = CompileStatData(
duration = duration, taskResult = taskResult.name, label = label,
statData = statData, projectName = projectName, taskName = taskPath
)
reportStatistics.report(compileStatData)
} }
override fun afterExecute(task: Task, taskState: TaskState) {
val taskResult = when {
taskState.skipped -> TaskExecutionState.SKIPPED
taskState.failure != null -> TaskExecutionState.FAILED
taskState.upToDate -> TaskExecutionState.UP_TO_DATE
taskState.didWork -> TaskExecutionState.SUCCESS
taskState.executed -> TaskExecutionState.FROM_CACHE
else -> TaskExecutionState.UNKNOWN
}
val taskPath = task.path
reportData(taskPath, 0L, taskResult)
}
override fun close() { override fun close() {
} }
override fun beforeExecute(p0: Task) {
//Do nothing
}
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.stat
data class CompileStatData( data class CompileStatData(
val version: Int = 1, val version: Int = 1,
val projectName: String?, val projectName: String?,
val label: String?,
val taskName: String?, val taskName: String?,
val taskResult: String, val taskResult: String,
val duration: Long, val duration: Long,
@@ -15,18 +15,20 @@ import java.net.URL
import java.util.* import java.util.*
object ReportStatisticsToElasticSearch : ReportStatistics { object ReportStatisticsToElasticSearch : ReportStatistics {
val url = CompilerSystemProperties.KOTLIN_STAT_ENDPOINT_PROPERTY.value val url by lazy { CompilerSystemProperties.KOTLIN_STAT_ENDPOINT_PROPERTY.value }
val user = CompilerSystemProperties.KOTLIN_STAT_USER_PROPERTY.value val user by lazy { CompilerSystemProperties.KOTLIN_STAT_USER_PROPERTY.value }
val enable: Boolean = CompilerSystemProperties.KOTLIN_STAT_ENABLED_PROPERTY.value?.toBooleanLenient() ?: false val enable: Boolean by lazy { CompilerSystemProperties.KOTLIN_STAT_ENABLED_PROPERTY.value?.toBooleanLenient() ?: false }
//TODO Do not store password as string //TODO Do not store password as string
val password = CompilerSystemProperties.KOTLIN_STAT_PASSWORD_PROPERTY.value val password by lazy { CompilerSystemProperties.KOTLIN_STAT_PASSWORD_PROPERTY.value }
override fun report(data: CompileStatData) { override fun report(data: CompileStatData) {
if (!enable) { if (!enable) {
return; return;
} }
val connection = URL(url).openConnection() as HttpURLConnection val connection = URL(url).openConnection() as HttpURLConnection
try { try {
if (user != null && password != null) { if (user != null && password != null) {
val auth = Base64.getEncoder() val auth = Base64.getEncoder()
@@ -39,9 +41,11 @@ object ReportStatisticsToElasticSearch : ReportStatistics {
connection.outputStream.use { connection.outputStream.use {
it.write(Gson().toJson(data).toByteArray()) it.write(Gson().toJson(data).toByteArray())
} }
connection.connect(); connection.connect()
checkResponseAndLog(connection) checkResponseAndLog(connection)
connection.inputStream.use { it.reader().use { reader -> reader.readText() } } connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
} catch (e: Exception) {
checkResponseAndLog(connection)
} finally { } finally {
connection.disconnect() connection.disconnect()
} }