Add custom_values_limit property to configure build scan report
#KT-53732 Fixed
This commit is contained in:
+32
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.logging.LogLevel
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.internal.build.metrics.GradleBuildMetricsData
|
import org.jetbrains.kotlin.gradle.internal.build.metrics.GradleBuildMetricsData
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildReportType
|
import org.jetbrains.kotlin.gradle.report.BuildReportType
|
||||||
@@ -99,7 +100,8 @@ class BuildReportsIT : KGPBaseTest() {
|
|||||||
val metricsFile = projectPath.resolve("metrics.bin").toFile()
|
val metricsFile = projectPath.resolve("metrics.bin").toFile()
|
||||||
build(
|
build(
|
||||||
"compileKotlin",
|
"compileKotlin",
|
||||||
"-Pkotlin.internal.single.build.metrics.file=${metricsFile.absolutePath}"
|
"-Pkotlin.build.report.output=SINGLE_FILE",
|
||||||
|
"-Pkotlin.build.report.single_file=${metricsFile.absolutePath}"
|
||||||
)
|
)
|
||||||
|
|
||||||
assertTrue { metricsFile.exists() }
|
assertTrue { metricsFile.exists() }
|
||||||
@@ -109,4 +111,33 @@ class BuildReportsIT : KGPBaseTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DisplayName("custom value limit")
|
||||||
|
@GradleTest
|
||||||
|
fun testCustomValueLimitForBuildScan(gradleVersion: GradleVersion) {
|
||||||
|
project("simpleProject", gradleVersion, buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
|
||||||
|
build(
|
||||||
|
"compileKotlin",
|
||||||
|
"-Pkotlin.build.report.output=BUILD_SCAN",
|
||||||
|
"-Pkotlin.build.report.build_scan.custom_values_limit=0",
|
||||||
|
"--scan"
|
||||||
|
) {
|
||||||
|
assertOutputContains("Can't add any more custom values into build scan")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("build scan listener lazy initialisation")
|
||||||
|
@GradleTest
|
||||||
|
fun testBuildScanListenerLazyInitialisation(gradleVersion: GradleVersion) {
|
||||||
|
project("simpleProject", gradleVersion, buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
|
||||||
|
build(
|
||||||
|
"compileKotlin",
|
||||||
|
"-Pkotlin.build.report.output=BUILD_SCAN",
|
||||||
|
"-Pkotlin.build.report.build_scan.custom_values_limit=0",
|
||||||
|
) {
|
||||||
|
assertOutputDoesNotContain("Can't add any more custom values into build scan")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.logging.LogLevel
|
||||||
import org.gradle.api.logging.configuration.WarningMode
|
import org.gradle.api.logging.configuration.WarningMode
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildReportType
|
import org.jetbrains.kotlin.gradle.report.BuildReportType
|
||||||
@@ -252,6 +253,22 @@ class ConfigurationCacheIT : AbstractConfigurationCacheIT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmGradlePluginTests
|
||||||
|
@DisplayName("with build build scan report")
|
||||||
|
@GradleTest
|
||||||
|
fun testBuildScanReportSmokeTestForConfigurationCache(gradleVersion: GradleVersion) {
|
||||||
|
project("simpleProject", gradleVersion) {
|
||||||
|
val buildOptions = defaultBuildOptions.copy(buildReport = listOf(BuildReportType.BUILD_SCAN), logLevel = LogLevel.DEBUG)
|
||||||
|
build("clean", "assemble", "-Pkotlin.build.report.build_scan.custom_values_limit=0", "--scan", buildOptions = buildOptions) {
|
||||||
|
assertOutputContains("Can't add any more custom values into build scan")
|
||||||
|
}
|
||||||
|
|
||||||
|
build("clean", "assemble", "-Pkotlin.build.report.build_scan.custom_values_limit=0", "--scan", buildOptions = buildOptions) {
|
||||||
|
assertOutputContains("Can't add any more custom values into build scan")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class AbstractConfigurationCacheIT : KGPBaseTest() {
|
abstract class AbstractConfigurationCacheIT : KGPBaseTest() {
|
||||||
|
|||||||
-5
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.plugin
|
package org.jetbrains.kotlin.gradle.plugin
|
||||||
|
|
||||||
import com.gradle.scan.plugin.BuildScanExtension
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
@@ -14,10 +13,6 @@ import org.gradle.api.services.BuildServiceParameters
|
|||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.BuildScanStatisticsListener
|
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildReportType
|
|
||||||
import org.jetbrains.kotlin.gradle.report.ReportingSettings
|
|
||||||
import org.jetbrains.kotlin.gradle.report.reportingSettings
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal abstract class KotlinGradleBuildServices : BuildService<KotlinGradleBuildServices.Parameters>, AutoCloseable {
|
internal abstract class KotlinGradleBuildServices : BuildService<KotlinGradleBuildServices.Parameters>, AutoCloseable {
|
||||||
|
|||||||
-1
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.gradle.dsl.*
|
|||||||
import org.jetbrains.kotlin.gradle.internal.KOTLIN_COMPILER_EMBEDDABLE
|
import org.jetbrains.kotlin.gradle.internal.KOTLIN_COMPILER_EMBEDDABLE
|
||||||
import org.jetbrains.kotlin.gradle.internal.KOTLIN_MODULE_GROUP
|
import org.jetbrains.kotlin.gradle.internal.KOTLIN_MODULE_GROUP
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformAndroidGradlePluginCompatibilityHealthCheck.runMultiplatformAndroidGradlePluginCompatibilityHealthCheck
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformAndroidGradlePluginCompatibilityHealthCheck.runMultiplatformAndroidGradlePluginCompatibilityHealthCheckWhenAndroidIsApplied
|
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformAndroidGradlePluginCompatibilityHealthCheck.runMultiplatformAndroidGradlePluginCompatibilityHealthCheckWhenAndroidIsApplied
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.*
|
import org.jetbrains.kotlin.gradle.plugin.internal.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.BasePluginConfiguration
|
import org.jetbrains.kotlin.gradle.plugin.internal.BasePluginConfiguration
|
||||||
|
|||||||
+3
@@ -97,6 +97,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
|||||||
val buildReportHttpPassword: String?
|
val buildReportHttpPassword: String?
|
||||||
get() = this.property("kotlin.build.report.http.password")
|
get() = this.property("kotlin.build.report.http.password")
|
||||||
|
|
||||||
|
val buildReportBuildScanCustomValuesLimit: Int
|
||||||
|
get() = property("kotlin.build.report.build_scan.custom_values_limit")?.toInt() ?: 1000
|
||||||
|
|
||||||
val buildReportMetrics: Boolean
|
val buildReportMetrics: Boolean
|
||||||
get() = booleanProperty("kotlin.build.report.metrics") ?: false
|
get() = booleanProperty("kotlin.build.report.metrics") ?: false
|
||||||
|
|
||||||
|
|||||||
-127
@@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.gradle.scan.plugin.BuildScanExtension
|
|
||||||
import org.gradle.api.logging.Logging
|
|
||||||
import org.gradle.tooling.events.FinishEvent
|
|
||||||
import org.gradle.tooling.events.OperationCompletionListener
|
|
||||||
import org.gradle.tooling.events.task.TaskFinishEvent
|
|
||||||
import org.jetbrains.kotlin.build.report.metrics.SizeMetricType
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.CompileStatisticsData
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.formatSize
|
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.measureTimeMillisWithResult
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.system.measureTimeMillis
|
|
||||||
|
|
||||||
class BuildScanStatisticsListener(
|
|
||||||
private val buildScan: BuildScanExtension,
|
|
||||||
val projectName: String,
|
|
||||||
val label: String?,
|
|
||||||
val kotlinVersion: String,
|
|
||||||
val buildUuid: String
|
|
||||||
) : OperationCompletionListener, AutoCloseable {
|
|
||||||
companion object {
|
|
||||||
const val lengthLimit = 100_000
|
|
||||||
const val customValuesLimit = 950 //git plugin and others can add custom values as well
|
|
||||||
}
|
|
||||||
|
|
||||||
private val tags = LinkedHashSet<String>()
|
|
||||||
private val log = Logging.getLogger(this.javaClass)
|
|
||||||
private var customValues = 0 // doesn't need to be thread-safe
|
|
||||||
|
|
||||||
override fun onFinish(event: FinishEvent?) {
|
|
||||||
if (event is TaskFinishEvent) {
|
|
||||||
val (collectDataDuration, compileStatData) = measureTimeMillisWithResult {
|
|
||||||
KotlinBuildStatListener.prepareData(event, projectName, buildUuid, label, kotlinVersion)
|
|
||||||
}
|
|
||||||
log.debug("Collect data takes $collectDataDuration: $compileStatData")
|
|
||||||
|
|
||||||
compileStatData?.also {
|
|
||||||
report(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun close() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun report(data: CompileStatisticsData) {
|
|
||||||
val elapsedTime = measureTimeMillis {
|
|
||||||
if (!tags.contains(buildUuid)) {
|
|
||||||
tags.add(buildUuid)
|
|
||||||
}
|
|
||||||
data.label?.takeIf { !tags.contains(it) }?.also {
|
|
||||||
buildScan.tag(it)
|
|
||||||
tags.add(it)
|
|
||||||
}
|
|
||||||
data.tags
|
|
||||||
.filter { !tags.contains(it) }
|
|
||||||
.forEach {
|
|
||||||
buildScan.tag(it)
|
|
||||||
tags.add(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (customValues < customValuesLimit) {
|
|
||||||
readableString(data).forEach {
|
|
||||||
if (customValues < customValuesLimit) {
|
|
||||||
buildScan.value(data.taskName, it)
|
|
||||||
customValues++
|
|
||||||
} else {
|
|
||||||
log.debug("Statistic data for ${data.taskName} was cut due to custom values limit.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.debug("Can't add any more custom values into build scan.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("Report statistic to build scan takes $elapsedTime ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readableString(data: CompileStatisticsData): List<String> {
|
|
||||||
val readableString = StringBuilder()
|
|
||||||
if (data.nonIncrementalAttributes.isEmpty()) {
|
|
||||||
readableString.append("Incremental build; ")
|
|
||||||
data.changes.joinTo(readableString, prefix = "Changes: [", postfix = "]; ") { it.substringAfterLast(File.separator) }
|
|
||||||
} else {
|
|
||||||
data.nonIncrementalAttributes.joinTo(readableString, prefix = "Non incremental build because: [", postfix = "]; ") { it.readableString }
|
|
||||||
}
|
|
||||||
|
|
||||||
val timeData =
|
|
||||||
data.buildTimesMetrics.map { (key, value) -> "${key.readableString}: ${value}ms" } //sometimes it is better to have separate variable to be able debug
|
|
||||||
val perfData = data.performanceMetrics.map { (key, value) ->
|
|
||||||
when (key.type) {
|
|
||||||
SizeMetricType.BYTES -> "${key.readableString}: ${formatSize(value)}"
|
|
||||||
else -> "${key.readableString}: $value}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timeData.union(perfData).joinTo(readableString, ",", "Performance: [", "]")
|
|
||||||
|
|
||||||
return splitStringIfNeed(readableString.toString(), lengthLimit)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun splitStringIfNeed(str: String, lengthLimit: Int): List<String> {
|
|
||||||
val splattedString = ArrayList<String>()
|
|
||||||
var tempStr = str
|
|
||||||
while (tempStr.length > lengthLimit) {
|
|
||||||
val subSequence = tempStr.substring(lengthLimit)
|
|
||||||
var index = subSequence.lastIndexOf(';')
|
|
||||||
if (index == -1) {
|
|
||||||
index = subSequence.lastIndexOf(',')
|
|
||||||
if (index == -1) {
|
|
||||||
index = lengthLimit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
splattedString.add(tempStr.substring(index))
|
|
||||||
tempStr = tempStr.substring(index)
|
|
||||||
|
|
||||||
}
|
|
||||||
splattedString.add(tempStr)
|
|
||||||
return splattedString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-132
@@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.tooling.events.task.TaskFailureResult
|
|
||||||
import org.gradle.tooling.events.task.TaskFinishEvent
|
|
||||||
import org.gradle.tooling.events.task.TaskSkippedResult
|
|
||||||
import org.gradle.tooling.events.task.TaskSuccessResult
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.CompileStatisticsData
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.StatTag
|
|
||||||
import org.jetbrains.kotlin.gradle.report.TaskExecutionResult
|
|
||||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
|
|
||||||
import java.lang.management.ManagementFactory
|
|
||||||
import java.net.InetAddress
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
enum class TaskExecutionState {
|
|
||||||
SKIPPED,
|
|
||||||
FAILED,
|
|
||||||
UNKNOWN,
|
|
||||||
SUCCESS,
|
|
||||||
FROM_CACHE,
|
|
||||||
UP_TO_DATE
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
class KotlinBuildStatListener {
|
|
||||||
companion object {
|
|
||||||
val hostName: String? = try {
|
|
||||||
InetAddress.getLocalHost().hostName
|
|
||||||
} catch (_: Exception) {
|
|
||||||
//do nothing
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun availableForStat(taskPath: String): Boolean {
|
|
||||||
return taskPath.contains("Kotlin") && (TaskExecutionResults[taskPath] != null)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun prepareData(
|
|
||||||
event: TaskFinishEvent,
|
|
||||||
projectName: String,
|
|
||||||
uuid: String,
|
|
||||||
label: String?,
|
|
||||||
kotlinVersion: String,
|
|
||||||
additionalTags: List<StatTag> = emptyList()
|
|
||||||
): CompileStatisticsData? {
|
|
||||||
val result = event.result
|
|
||||||
val taskPath = event.descriptor.taskPath
|
|
||||||
val durationMs = result.endTime - result.startTime
|
|
||||||
val taskResult = when (result) {
|
|
||||||
is TaskSuccessResult -> when {
|
|
||||||
result.isFromCache -> TaskExecutionState.FROM_CACHE
|
|
||||||
result.isUpToDate -> TaskExecutionState.UP_TO_DATE
|
|
||||||
else -> TaskExecutionState.SUCCESS
|
|
||||||
}
|
|
||||||
|
|
||||||
is TaskSkippedResult -> TaskExecutionState.SKIPPED
|
|
||||||
is TaskFailureResult -> TaskExecutionState.FAILED
|
|
||||||
else -> TaskExecutionState.UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!availableForStat(taskPath)) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val taskExecutionResult = TaskExecutionResults[taskPath]
|
|
||||||
val buildTimesMs = taskExecutionResult?.buildMetrics?.buildTimes?.asMapMs()?.filterValues { value -> value != 0L } ?: emptyMap()
|
|
||||||
val perfData =
|
|
||||||
taskExecutionResult?.buildMetrics?.buildPerformanceMetrics?.asMap()?.filterValues { value -> value != 0L } ?: emptyMap()
|
|
||||||
val changes = when (val changedFiles = taskExecutionResult?.taskInfo?.changedFiles) {
|
|
||||||
is ChangedFiles.Known -> changedFiles.modified.map { it.absolutePath } + changedFiles.removed.map { it.absolutePath }
|
|
||||||
is ChangedFiles.Dependencies -> changedFiles.modified.map { it.absolutePath } + changedFiles.removed.map { it.absolutePath }
|
|
||||||
else -> emptyList<String>()
|
|
||||||
|
|
||||||
}
|
|
||||||
return CompileStatisticsData(
|
|
||||||
durationMs = durationMs,
|
|
||||||
taskResult = taskResult.name,
|
|
||||||
label = label,
|
|
||||||
buildTimesMetrics = buildTimesMs,
|
|
||||||
performanceMetrics = perfData,
|
|
||||||
projectName = projectName,
|
|
||||||
taskName = taskPath,
|
|
||||||
changes = changes,
|
|
||||||
tags = parseTags(taskExecutionResult, additionalTags).map { it.name },
|
|
||||||
nonIncrementalAttributes = taskExecutionResult?.buildMetrics?.buildAttributes?.asMap()?.filter { it.value > 0 }?.keys ?: emptySet(),
|
|
||||||
hostName = hostName,
|
|
||||||
kotlinVersion = kotlinVersion,
|
|
||||||
buildUuid = uuid,
|
|
||||||
finishTime = System.currentTimeMillis(),
|
|
||||||
compilerArguments = taskExecutionResult?.taskInfo?.compilerArguments?.asList() ?: emptyList()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseTags(taskExecutionResult: TaskExecutionResult?, additionalTags: List<StatTag>): List<StatTag> {
|
|
||||||
val tags = ArrayList(additionalTags)
|
|
||||||
|
|
||||||
val nonIncrementalAttributes = taskExecutionResult?.buildMetrics?.buildAttributes?.asMap() ?: emptyMap()
|
|
||||||
|
|
||||||
if (nonIncrementalAttributes.isEmpty()) {
|
|
||||||
tags.add(StatTag.INCREMENTAL)
|
|
||||||
} else {
|
|
||||||
tags.add(StatTag.NON_INCREMENTAL)
|
|
||||||
}
|
|
||||||
|
|
||||||
val taskInfo = taskExecutionResult?.taskInfo
|
|
||||||
|
|
||||||
taskInfo?.withAbiSnapshot?.ifTrue {
|
|
||||||
tags.add(StatTag.ABI_SNAPSHOT)
|
|
||||||
}
|
|
||||||
taskInfo?.withArtifactTransform?.ifTrue {
|
|
||||||
tags.add(StatTag.ARTIFACT_TRANSFORM)
|
|
||||||
}
|
|
||||||
|
|
||||||
val debugConfiguration = "-agentlib:"
|
|
||||||
if (ManagementFactory.getRuntimeMXBean().inputArguments.firstOrNull { it.startsWith(debugConfiguration) } != null) {
|
|
||||||
tags.add(StatTag.GRADLE_DEBUG)
|
|
||||||
}
|
|
||||||
return tags
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+249
-40
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.gradle.report
|
package org.jetbrains.kotlin.gradle.report
|
||||||
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.gradle.scan.plugin.BuildScanExtension
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
@@ -17,24 +16,34 @@ import org.gradle.api.services.BuildService
|
|||||||
import org.gradle.api.services.BuildServiceParameters
|
import org.gradle.api.services.BuildServiceParameters
|
||||||
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.TaskFailureResult
|
||||||
import org.gradle.tooling.events.task.TaskFinishEvent
|
import org.gradle.tooling.events.task.TaskFinishEvent
|
||||||
|
import org.gradle.tooling.events.task.TaskSkippedResult
|
||||||
|
import org.gradle.tooling.events.task.TaskSuccessResult
|
||||||
|
import org.jetbrains.kotlin.build.report.metrics.SizeMetricType
|
||||||
import org.jetbrains.kotlin.gradle.plugin.BuildEventsListenerRegistryHolder
|
import org.jetbrains.kotlin.gradle.plugin.BuildEventsListenerRegistryHolder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.BuildFinishStatisticsData
|
import org.jetbrains.kotlin.gradle.plugin.stat.BuildFinishStatisticsData
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.stat.CompileStatisticsData
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.GradleBuildStartParameters
|
import org.jetbrains.kotlin.gradle.plugin.stat.GradleBuildStartParameters
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.StatTag
|
import org.jetbrains.kotlin.gradle.plugin.stat.StatTag
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.BuildScanStatisticsListener
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatListener
|
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionData
|
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionData
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.formatSize
|
||||||
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.measureTimeMillisWithResult
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
|
import java.net.InetAddress
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
abstract class BuildReportsService : BuildService<BuildReportsService.Parameters>, AutoCloseable, OperationCompletionListener {
|
abstract class BuildReportsService : BuildService<BuildReportsService.Parameters>, AutoCloseable, OperationCompletionListener {
|
||||||
@@ -45,8 +54,8 @@ abstract class BuildReportsService : BuildService<BuildReportsService.Parameters
|
|||||||
private val buildUuid = UUID.randomUUID().toString()
|
private val buildUuid = UUID.randomUUID().toString()
|
||||||
private var executorService: ExecutorService = Executors.newSingleThreadExecutor()
|
private var executorService: ExecutorService = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
private var buildMetricsService: Provider<BuildMetricsService>? = null
|
private val tags = LinkedHashSet<String>()
|
||||||
|
private var customValues = 0 // doesn't need to be thread-safe
|
||||||
|
|
||||||
init {
|
init {
|
||||||
log.info("Build report service is registered. Unique build id: $buildUuid")
|
log.info("Build report service is registered. Unique build id: $buildUuid")
|
||||||
@@ -112,35 +121,11 @@ abstract class BuildReportsService : BuildService<BuildReportsService.Parameters
|
|||||||
sendDataViaHttp(buildFinishData)
|
sendDataViaHttp(buildFinishData)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initService(project: Project) {
|
|
||||||
addListeners(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addBuildScanReport(project: Project) {
|
|
||||||
if (parameters.reportingSettings.buildReportOutputs.contains(BuildReportType.BUILD_SCAN)) {
|
|
||||||
val listenerRegistryHolder = BuildEventsListenerRegistryHolder.getInstance(project)
|
|
||||||
project.rootProject.extensions.findByName("buildScan")
|
|
||||||
?.also {
|
|
||||||
listenerRegistryHolder.listenerRegistry.onTaskCompletion(
|
|
||||||
project.provider {
|
|
||||||
BuildScanStatisticsListener(
|
|
||||||
it as BuildScanExtension,
|
|
||||||
parameters.projectName.get(),
|
|
||||||
parameters.label.orNull,
|
|
||||||
parameters.kotlinVersion.get(),
|
|
||||||
buildUuid
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addHttpReport(event: FinishEvent?) {
|
private fun addHttpReport(event: FinishEvent?) {
|
||||||
if (parameters.reportingSettings.get().httpReportSettings != null) {
|
if (parameters.reportingSettings.get().httpReportSettings != null) {
|
||||||
if (event is TaskFinishEvent) {
|
if (event is TaskFinishEvent) {
|
||||||
val data =
|
val data =
|
||||||
KotlinBuildStatListener.prepareData(
|
prepareData(
|
||||||
event,
|
event,
|
||||||
parameters.projectName.get(),
|
parameters.projectName.get(),
|
||||||
buildUuid,
|
buildUuid,
|
||||||
@@ -154,10 +139,6 @@ abstract class BuildReportsService : BuildService<BuildReportsService.Parameters
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addListeners(project: Project) {
|
|
||||||
addBuildScanReport(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var invalidUrl = false
|
private var invalidUrl = false
|
||||||
private var requestPreviousFailed = false
|
private var requestPreviousFailed = false
|
||||||
private fun sendDataViaHttp(data: Any) {
|
private fun sendDataViaHttp(data: Any) {
|
||||||
@@ -213,8 +194,123 @@ abstract class BuildReportsService : BuildService<BuildReportsService.Parameters
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun addBuildScanReport(event: FinishEvent?, buildScan: BuildScanExtensionHolder) {
|
||||||
|
val buildScanSettings = parameters.reportingSettings.orNull?.buildScanReportSettings
|
||||||
|
if (buildScanSettings != null && buildScan.buildScan != null) {
|
||||||
|
if (event is TaskFinishEvent) {
|
||||||
|
val (collectDataDuration, compileStatData) = measureTimeMillisWithResult {
|
||||||
|
prepareData(event, parameters.projectName.get(), buildUuid, parameters.label.orNull, parameters.kotlinVersion.get())
|
||||||
|
}
|
||||||
|
log.debug("Collect data takes $collectDataDuration: $compileStatData")
|
||||||
|
|
||||||
|
compileStatData?.also {
|
||||||
|
addBuildScanReport(it, buildScanSettings.customValueLimit, buildScan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addBuildScanReport(data: CompileStatisticsData, customValuesLimit: Int, buildScan: BuildScanExtensionHolder) {
|
||||||
|
val elapsedTime = measureTimeMillis {
|
||||||
|
buildScan.buildScan?.also {
|
||||||
|
if (!tags.contains(buildUuid)) {
|
||||||
|
addBuildScanTag(buildScan, buildUuid)
|
||||||
|
}
|
||||||
|
data.label?.takeIf { !tags.contains(it) }?.also {
|
||||||
|
addBuildScanTag(buildScan, it)
|
||||||
|
}
|
||||||
|
data.tags
|
||||||
|
.filter { !tags.contains(it) }
|
||||||
|
.forEach {
|
||||||
|
addBuildScanTag(buildScan, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customValues < customValuesLimit) {
|
||||||
|
readableString(data).forEach {
|
||||||
|
if (customValues < customValuesLimit) {
|
||||||
|
addBuildScanValue(buildScan, data, it)
|
||||||
|
} else {
|
||||||
|
log.debug(
|
||||||
|
"Can't add any more custom values into build scan." +
|
||||||
|
" Statistic data for ${data.taskName} was cut due to custom values limit."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("Can't add any more custom values into build scan.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Report statistic to build scan takes $elapsedTime ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addBuildScanValue(
|
||||||
|
buildScan: BuildScanExtensionHolder,
|
||||||
|
data: CompileStatisticsData,
|
||||||
|
customValue: String
|
||||||
|
) {
|
||||||
|
buildScan.buildScan?.value(data.taskName, customValue)
|
||||||
|
customValues++
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addBuildScanTag(buildScan: BuildScanExtensionHolder, tag: String) {
|
||||||
|
buildScan.buildScan?.tag(tag)
|
||||||
|
tags.add(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readableString(data: CompileStatisticsData): List<String> {
|
||||||
|
val readableString = StringBuilder()
|
||||||
|
if (data.nonIncrementalAttributes.isEmpty()) {
|
||||||
|
readableString.append("Incremental build; ")
|
||||||
|
data.changes.joinTo(readableString, prefix = "Changes: [", postfix = "]; ") { it.substringAfterLast(File.separator) }
|
||||||
|
} else {
|
||||||
|
data.nonIncrementalAttributes.joinTo(
|
||||||
|
readableString,
|
||||||
|
prefix = "Non incremental build because: [",
|
||||||
|
postfix = "]; "
|
||||||
|
) { it.readableString }
|
||||||
|
}
|
||||||
|
|
||||||
|
val timeData =
|
||||||
|
data.buildTimesMetrics.map { (key, value) -> "${key.readableString}: ${value}ms" } //sometimes it is better to have separate variable to be able debug
|
||||||
|
val perfData = data.performanceMetrics.map { (key, value) ->
|
||||||
|
when (key.type) {
|
||||||
|
SizeMetricType.BYTES -> "${key.readableString}: ${formatSize(value)}"
|
||||||
|
else -> "${key.readableString}: $value}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timeData.union(perfData).joinTo(readableString, ",", "Performance: [", "]")
|
||||||
|
|
||||||
|
return splitStringIfNeed(readableString.toString(), lengthLimit)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun splitStringIfNeed(str: String, lengthLimit: Int): List<String> {
|
||||||
|
val splattedString = ArrayList<String>()
|
||||||
|
var tempStr = str
|
||||||
|
while (tempStr.length > lengthLimit) {
|
||||||
|
val subSequence = tempStr.substring(lengthLimit)
|
||||||
|
var index = subSequence.lastIndexOf(';')
|
||||||
|
if (index == -1) {
|
||||||
|
index = subSequence.lastIndexOf(',')
|
||||||
|
if (index == -1) {
|
||||||
|
index = lengthLimit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
splattedString.add(tempStr.substring(index))
|
||||||
|
tempStr = tempStr.substring(index)
|
||||||
|
|
||||||
|
}
|
||||||
|
splattedString.add(tempStr)
|
||||||
|
return splattedString
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
private val log = Logging.getLogger(this.javaClass)
|
||||||
|
const val lengthLimit = 100_000
|
||||||
|
|
||||||
fun getStartParameters(project: Project) = project.gradle.startParameter.let {
|
fun getStartParameters(project: Project) = project.gradle.startParameter.let {
|
||||||
GradleBuildStartParameters(
|
GradleBuildStartParameters(
|
||||||
tasks = it.taskRequests.flatMap { it.args },
|
tasks = it.taskRequests.flatMap { it.args },
|
||||||
@@ -251,12 +347,19 @@ abstract class BuildReportsService : BuildService<BuildReportsService.Parameters
|
|||||||
|
|
||||||
//init gradle tags for build scan and http reports
|
//init gradle tags for build scan and http reports
|
||||||
it.parameters.additionalTags.value(setupTags(gradle))
|
it.parameters.additionalTags.value(setupTags(gradle))
|
||||||
}!!.also {
|
}.also {
|
||||||
val buildReportsService = it.get()
|
if (reportingSettings.httpReportSettings != null) {
|
||||||
buildReportsService.initService(project)
|
|
||||||
if (buildReportsService.parameters.reportingSettings.get().buildReportOutputs.contains(BuildReportType.HTTP)) {
|
|
||||||
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(it)
|
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val buildScanExtension = project.rootProject.extensions.findByName("buildScan")
|
||||||
|
if (reportingSettings.buildScanReportSettings != null && buildScanExtension != null) {
|
||||||
|
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(project.provider {
|
||||||
|
OperationCompletionListener { event ->
|
||||||
|
it.get().addBuildScanReport(event, BuildScanExtensionHolder(buildScanExtension))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +373,112 @@ abstract class BuildReportsService : BuildService<BuildReportsService.Parameters
|
|||||||
}
|
}
|
||||||
return additionalTags
|
return additionalTags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun prepareData(
|
||||||
|
event: TaskFinishEvent,
|
||||||
|
projectName: String,
|
||||||
|
uuid: String,
|
||||||
|
label: String?,
|
||||||
|
kotlinVersion: String,
|
||||||
|
additionalTags: List<StatTag> = emptyList()
|
||||||
|
): CompileStatisticsData? {
|
||||||
|
val result = event.result
|
||||||
|
val taskPath = event.descriptor.taskPath
|
||||||
|
val durationMs = result.endTime - result.startTime
|
||||||
|
val taskResult = when (result) {
|
||||||
|
is TaskSuccessResult -> when {
|
||||||
|
result.isFromCache -> TaskExecutionState.FROM_CACHE
|
||||||
|
result.isUpToDate -> TaskExecutionState.UP_TO_DATE
|
||||||
|
else -> TaskExecutionState.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
is TaskSkippedResult -> TaskExecutionState.SKIPPED
|
||||||
|
is TaskFailureResult -> TaskExecutionState.FAILED
|
||||||
|
else -> TaskExecutionState.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!availableForStat(taskPath)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val taskExecutionResult = TaskExecutionResults[taskPath]
|
||||||
|
val buildTimesMs = taskExecutionResult?.buildMetrics?.buildTimes?.asMapMs()?.filterValues { value -> value != 0L } ?: emptyMap()
|
||||||
|
val perfData =
|
||||||
|
taskExecutionResult?.buildMetrics?.buildPerformanceMetrics?.asMap()?.filterValues { value -> value != 0L } ?: emptyMap()
|
||||||
|
val changes = when (val changedFiles = taskExecutionResult?.taskInfo?.changedFiles) {
|
||||||
|
is ChangedFiles.Known -> changedFiles.modified.map { it.absolutePath } + changedFiles.removed.map { it.absolutePath }
|
||||||
|
is ChangedFiles.Dependencies -> changedFiles.modified.map { it.absolutePath } + changedFiles.removed.map { it.absolutePath }
|
||||||
|
else -> emptyList<String>()
|
||||||
|
|
||||||
|
}
|
||||||
|
return CompileStatisticsData(
|
||||||
|
durationMs = durationMs,
|
||||||
|
taskResult = taskResult.name,
|
||||||
|
label = label,
|
||||||
|
buildTimesMetrics = buildTimesMs,
|
||||||
|
performanceMetrics = perfData,
|
||||||
|
projectName = projectName,
|
||||||
|
taskName = taskPath,
|
||||||
|
changes = changes,
|
||||||
|
tags = parseTags(taskExecutionResult, additionalTags).map { it.name },
|
||||||
|
nonIncrementalAttributes = taskExecutionResult?.buildMetrics?.buildAttributes?.asMap()?.filter { it.value > 0 }?.keys
|
||||||
|
?: emptySet(),
|
||||||
|
hostName = hostName,
|
||||||
|
kotlinVersion = kotlinVersion,
|
||||||
|
buildUuid = uuid,
|
||||||
|
finishTime = System.currentTimeMillis(),
|
||||||
|
compilerArguments = taskExecutionResult?.taskInfo?.compilerArguments?.asList() ?: emptyList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val hostName: String? = try {
|
||||||
|
InetAddress.getLocalHost().hostName
|
||||||
|
} catch (_: Exception) {
|
||||||
|
//do nothing
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun availableForStat(taskPath: String): Boolean {
|
||||||
|
return taskPath.contains("Kotlin") && (TaskExecutionResults[taskPath] != null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseTags(taskExecutionResult: TaskExecutionResult?, additionalTags: List<StatTag>): List<StatTag> {
|
||||||
|
val tags = ArrayList(additionalTags)
|
||||||
|
|
||||||
|
val nonIncrementalAttributes = taskExecutionResult?.buildMetrics?.buildAttributes?.asMap() ?: emptyMap()
|
||||||
|
|
||||||
|
if (nonIncrementalAttributes.isEmpty()) {
|
||||||
|
tags.add(StatTag.INCREMENTAL)
|
||||||
|
} else {
|
||||||
|
tags.add(StatTag.NON_INCREMENTAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
val taskInfo = taskExecutionResult?.taskInfo
|
||||||
|
|
||||||
|
taskInfo?.withAbiSnapshot?.ifTrue {
|
||||||
|
tags.add(StatTag.ABI_SNAPSHOT)
|
||||||
|
}
|
||||||
|
taskInfo?.withArtifactTransform?.ifTrue {
|
||||||
|
tags.add(StatTag.ARTIFACT_TRANSFORM)
|
||||||
|
}
|
||||||
|
|
||||||
|
val debugConfiguration = "-agentlib:"
|
||||||
|
if (ManagementFactory.getRuntimeMXBean().inputArguments.firstOrNull { it.startsWith(debugConfiguration) } != null) {
|
||||||
|
tags.add(StatTag.GRADLE_DEBUG)
|
||||||
|
}
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class TaskExecutionState {
|
||||||
|
SKIPPED,
|
||||||
|
FAILED,
|
||||||
|
UNKNOWN,
|
||||||
|
SUCCESS,
|
||||||
|
FROM_CACHE,
|
||||||
|
UP_TO_DATE
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.report
|
||||||
|
|
||||||
|
import com.gradle.scan.plugin.BuildScanExtension
|
||||||
|
|
||||||
|
class BuildScanExtensionHolder(val buildScan: BuildScanExtension?) : java.io.Serializable {
|
||||||
|
constructor(extension: Any?) : this(extension as BuildScanExtension)
|
||||||
|
}
|
||||||
+9
@@ -14,6 +14,7 @@ data class ReportingSettings(
|
|||||||
val buildReportLabel: String? = null,
|
val buildReportLabel: String? = null,
|
||||||
val fileReportSettings: FileReportSettings? = null,
|
val fileReportSettings: FileReportSettings? = null,
|
||||||
val httpReportSettings: HttpReportSettings? = null,
|
val httpReportSettings: HttpReportSettings? = null,
|
||||||
|
val buildScanReportSettings: BuildScanSettings? = null,
|
||||||
val singleOutputFile: File? = null
|
val singleOutputFile: File? = null
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -38,4 +39,12 @@ data class HttpReportSettings(
|
|||||||
companion object {
|
companion object {
|
||||||
const val serialVersionUID: Long = 0
|
const val serialVersionUID: Long = 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class BuildScanSettings(
|
||||||
|
val customValueLimit: Int
|
||||||
|
): Serializable {
|
||||||
|
companion object {
|
||||||
|
const val serialVersionUID: Long = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+8
-1
@@ -37,8 +37,14 @@ internal fun reportingSettings(rootProject: Project): ReportingSettings {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val buildScanSettings = if (buildReportOutputTypes.contains(BuildReportType.BUILD_SCAN)) {
|
||||||
|
BuildScanSettings(properties.buildReportBuildScanCustomValuesLimit)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
//temporary solution. support old property
|
//temporary solution. support old property
|
||||||
val oldSingleBuildMetric = properties.singleBuildMetricsFile?.also { buildReportOutputTypes.add(BuildReportType.SINGLE_FILE) }
|
val oldSingleBuildMetric = properties.singleBuildMetricsFile?.also { buildReportOutputTypes.add(BuildReportType.SINGLE_FILE) }
|
||||||
|
|
||||||
val singleOutputFile = if (buildReportOutputTypes.contains(BuildReportType.SINGLE_FILE)) {
|
val singleOutputFile = if (buildReportOutputTypes.contains(BuildReportType.SINGLE_FILE)) {
|
||||||
properties.buildReportSingleFile ?: oldSingleBuildMetric
|
properties.buildReportSingleFile ?: oldSingleBuildMetric
|
||||||
@@ -49,6 +55,7 @@ internal fun reportingSettings(rootProject: Project): ReportingSettings {
|
|||||||
buildReportLabel = properties.buildReportLabel,
|
buildReportLabel = properties.buildReportLabel,
|
||||||
fileReportSettings = fileReportSettings,
|
fileReportSettings = fileReportSettings,
|
||||||
httpReportSettings = httpReportSettings,
|
httpReportSettings = httpReportSettings,
|
||||||
|
buildScanReportSettings = buildScanSettings,
|
||||||
buildReportOutputs = buildReportOutputTypes,
|
buildReportOutputs = buildReportOutputTypes,
|
||||||
singleOutputFile = singleOutputFile,
|
singleOutputFile = singleOutputFile,
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-4
@@ -59,13 +59,13 @@ internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile
|
|||||||
.disallowChanges()
|
.disallowChanges()
|
||||||
|
|
||||||
task.localStateDirectories.from(task.taskBuildLocalStateDirectory).disallowChanges()
|
task.localStateDirectories.from(task.taskBuildLocalStateDirectory).disallowChanges()
|
||||||
val buildMetricsService = BuildMetricsService.registerIfAbsent(project)?.also {
|
BuildMetricsService.registerIfAbsent(project)?.also {
|
||||||
task.buildMetricsService.value(it)
|
task.buildMetricsService.value(it)
|
||||||
|
BuildReportsService.registerIfAbsent(project, it)?.also {
|
||||||
|
task.buildReportsService.value(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildMetricsService?.let { BuildReportsService.registerIfAbsent(project, it) }
|
|
||||||
?.let { task.buildReportsService.value(it) }
|
|
||||||
|
|
||||||
propertiesProvider.kotlinDaemonJvmArgs?.let { kotlinDaemonJvmArgs ->
|
propertiesProvider.kotlinDaemonJvmArgs?.let { kotlinDaemonJvmArgs ->
|
||||||
task.kotlinDaemonJvmArguments.set(providers.provider {
|
task.kotlinDaemonJvmArguments.set(providers.provider {
|
||||||
kotlinDaemonJvmArgs.split("\\s+".toRegex())
|
kotlinDaemonJvmArgs.split("\\s+".toRegex())
|
||||||
|
|||||||
Reference in New Issue
Block a user