Unique build id
diff --git a/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/BuildUidService.kt b/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/BuildUidService.kt
new file mode 100644
index 0000000..b11d9ce
--- /dev/null
+++ b/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/BuildUidService.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2024 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.fus
+
+import org.gradle.api.Project
+import org.gradle.api.logging.Logging
+import org.gradle.api.provider.Provider
+import org.gradle.api.services.BuildService
+import org.gradle.api.services.BuildServiceParameters
+import java.util.UUID.randomUUID
+
+abstract class BuildUidService : BuildService<BuildServiceParameters.None>, AutoCloseable {
+ public val buildId = randomUUID().toString()
+ private val log = Logging.getLogger(this.javaClass)
+
+ init {
+ log.info("Build $buildId is started")
+ }
+
+ companion object {
+ fun registerIfAbsent(project: Project): Provider<out BuildUidService> {
+ return project.gradle.sharedServices.registerIfAbsent(BuildUidService::class.java.name, BuildUidService::class.java) {
+ }
+ }
+ }
+
+ override fun close() {
+ log.info("Build $buildId is closed")
+ }
+}
\ No newline at end of file
diff --git a/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/FusStatisticsPlugin.kt b/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/FusStatisticsPlugin.kt
index 5835959..4ff1085 100644
--- a/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/FusStatisticsPlugin.kt
+++ b/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/FusStatisticsPlugin.kt
@@ -19,6 +19,7 @@
private val providerFactory: ProviderFactory
) : Plugin<Project> {
override fun apply(project: Project) {
- GradleBuildFusStatisticsBuildService.registerIfAbsent(project)
+ val buildUidService = BuildUidService.registerIfAbsent(project)
+ GradleBuildFusStatisticsBuildService.registerIfAbsent(project, buildUidService)
}
}
\ No newline at end of file
diff --git a/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/internal/GradleBuildFusStatisticsBuildService.kt b/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/internal/GradleBuildFusStatisticsBuildService.kt
index 8f176df..6c6a5db 100644
--- a/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/internal/GradleBuildFusStatisticsBuildService.kt
+++ b/libraries/tools/gradle/fus-statistics-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/fus/internal/GradleBuildFusStatisticsBuildService.kt
@@ -10,9 +10,9 @@
import org.gradle.api.provider.Provider
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
+import org.jetbrains.kotlin.gradle.fus.BuildUidService
import org.jetbrains.kotlin.gradle.fus.GradleBuildFusStatisticsService
import org.jetbrains.kotlin.gradle.fus.UsesGradleBuildFusStatisticsService
-import java.util.*
abstract class GradleBuildFusStatisticsBuildService : GradleBuildFusStatisticsService,
BuildService<GradleBuildFusStatisticsBuildService.Parameters>, AutoCloseable {
@@ -20,13 +20,14 @@
val fusStatisticsRootDirPath: Property<String>
val buildId: Property<String>
}
+// private var buildUid: String? = null
companion object {
private var statisticsIsEnabled: Boolean = true //KT-59629 Wait for user confirmation before start to collect metrics
private const val FUS_STATISTICS_PATH = "kotlin.fus.statistics.path"
private val serviceClass = GradleBuildFusStatisticsBuildService::class.java
private val serviceName = "${serviceClass.name}_${serviceClass.classLoader.hashCode()}"
- fun registerIfAbsent(project: Project): Provider<out GradleBuildFusStatisticsService>? {
+ fun registerIfAbsent(project: Project, buildUidService: Provider<out BuildUidService>): Provider<out GradleBuildFusStatisticsService> {
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
@Suppress("UNCHECKED_CAST")
return it.service as Provider<GradleBuildFusStatisticsService>
@@ -40,7 +41,7 @@
project.gradle.gradleUserHomeDir.path
}
it.parameters.fusStatisticsRootDirPath.set(customPath)
- it.parameters.buildId.set(UUID.randomUUID().toString())
+ it.parameters.buildId.set(buildUidService.get().buildId)
}
} else {
project.gradle.sharedServices.registerIfAbsent(serviceName, DummyGradleBuildFusStatisticsService::class.java) {}
diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
index 8793585..39eccb6 100644
--- a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
+++ b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
@@ -1,14 +1,24 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+buildscript {
+ dependencies {
+ classpath("org.jetbrains.kotlin:fus-statistics-gradle-plugin:2.0.255-SNAPSHOT")
+ }
+}
+
plugins {
id("gradle-plugin-common-configuration")
id("org.jetbrains.kotlinx.binary-compatibility-validator")
+// id ("org.jetbrains.kotlin.fus-statistics-gradle-plugin") version "2.0.255-SNAPSHOT"
}
+plugins.apply("org.jetbrains.kotlin.fus-statistics-gradle-plugin")
+
repositories {
google()
mavenCentral()
+ mavenLocal()
gradlePluginPortal()
}
@@ -101,6 +111,7 @@
commonImplementation(project(":native:kotlin-klib-commonizer-api"))
commonImplementation(project(":compiler:build-tools:kotlin-build-tools-api"))
commonImplementation(project(":compiler:build-tools:kotlin-build-statistics"))
+ commonImplementation("org.jetbrains.kotlin:fus-statistics-gradle-plugin:2.0.255-SNAPSHOT")
commonRuntimeOnly(project(":kotlin-compiler-runner")) {
// Excluding dependency with not-relocated 'com.intellij' types
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/btapi/BuildToolsApiCompilationWork.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/btapi/BuildToolsApiCompilationWork.kt
index 9d155e5..03b5ef8 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/btapi/BuildToolsApiCompilationWork.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/btapi/BuildToolsApiCompilationWork.kt
@@ -21,19 +21,14 @@
import org.jetbrains.kotlin.compilerRunner.asFinishLogMessage
import org.jetbrains.kotlin.gradle.internal.ClassLoadersCachingBuildService
import org.jetbrains.kotlin.gradle.internal.ParentClassLoaderProvider
-import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
-import org.jetbrains.kotlin.gradle.logging.SL4JKotlinLogger
import org.jetbrains.kotlin.gradle.plugin.BuildFinishedListenerService
import org.jetbrains.kotlin.gradle.plugin.internal.BuildIdService
-import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
import org.jetbrains.kotlin.gradle.plugin.internal.state.getTaskLogger
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.tasks.FailedCompilationException
import org.jetbrains.kotlin.gradle.tasks.TaskOutputsBackup
import org.jetbrains.kotlin.incremental.ClasspathChanges
-import org.slf4j.LoggerFactory
import java.io.File
-import java.rmi.RemoteException
import javax.inject.Inject
private const val LOGGER_PREFIX = "[KOTLIN] "
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt
index ac076ff..32b8941 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt
@@ -57,6 +57,7 @@
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.tooling.core.KotlinToolingVersion
import kotlin.reflect.KClass
+import org.jetbrains.kotlin.gradle.fus.BuildUidService
/**
* Base Kotlin plugin that is responsible for creating basic build services, configurations,
@@ -95,7 +96,8 @@
kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, pluginVersion)
}
- BuildMetricsService.registerIfAbsent(project)
+ val buildUidService = BuildUidService.registerIfAbsent(project)
+ BuildMetricsService.registerIfAbsent(project, buildUidService)
KotlinNativeBundleBuildService.registerIfAbsent(project)
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt
index 022bdd1..a074a2a 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/StatisticsBuildFlowManager.kt
@@ -10,6 +10,7 @@
import org.gradle.api.provider.Property
import org.gradle.api.services.ServiceReference
import org.gradle.api.tasks.Input
+import org.jetbrains.kotlin.gradle.fus.BuildUidService
import org.jetbrains.kotlin.gradle.plugin.statistics.BuildFusService
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
import org.jetbrains.kotlin.gradle.report.BuildScanExtensionHolder
@@ -46,12 +47,18 @@
@get:ServiceReference
val buildMetricService: Property<BuildMetricsService>
+ @get:ServiceReference
+ val buildUidService: Property<BuildUidService>
+
@get: Input
val buildScanExtensionHolder: Property<BuildScanExtensionHolder>
}
override fun execute(parameters: Parameters) {
- parameters.buildMetricService.orNull?.addBuildScanReport(parameters.buildScanExtensionHolder.orNull)
+ parameters.buildMetricService.orNull?.addBuildScanReport(
+ parameters.buildScanExtensionHolder.orNull,
+ parameters.buildUidService.orNull?.buildId ?: "Unknown Build ID"
+ )
}
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt
index 83937b6..1bf7039 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildMetricsService.kt
@@ -41,6 +41,7 @@
import org.jetbrains.kotlin.gradle.plugin.internal.isConfigurationCacheEnabled
import org.jetbrains.kotlin.gradle.plugin.internal.isProjectIsolationEnabled
import java.lang.management.ManagementFactory
+import org.jetbrains.kotlin.gradle.fus.BuildUidService
internal interface UsesBuildMetricsService : Task {
@get:Internal
@@ -49,7 +50,7 @@
abstract class BuildMetricsService : BuildService<BuildMetricsService.Parameters>, AutoCloseable, OperationCompletionListener {
- //Part of BuildReportService
+ //Part of the BuildReportService
interface Parameters : BuildServiceParameters {
val startParameters: Property<BuildStartParameters>
val reportingSettings: Property<ReportingSettings>
@@ -62,7 +63,7 @@
val buildConfigurationTags: ListProperty<StatTag>
}
- private val buildReportService = BuildReportsService()
+ private val buildReportService = BuildReportsService("unknown")
// Tasks and transforms' records
private val buildOperationRecords = ConcurrentLinkedQueue<BuildOperationRecord>()
@@ -166,6 +167,7 @@
private fun registerIfAbsentImpl(
project: Project,
+ buildIdService: Provider<BuildIdService>,
): Provider<BuildMetricsService>? {
// Return early if the service was already registered to avoid the overhead of reading the reporting settings below
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
@@ -200,15 +202,19 @@
//init gradle tags for build scan and http reports
it.parameters.buildConfigurationTags.value(setupTags(project))
}.also {
- subscribeForTaskEvents(project, it)
+ subscribeForTaskEvents(project, it, buildIdService.get().buildUid)
}
}
- private fun subscribeForTaskEvents(project: Project, buildMetricServiceProvider: Provider<BuildMetricsService>) {
+ private fun subscribeForTaskEvents(
+ project: Project,
+ buildMetricServiceProvider: Provider<BuildMetricsService>,
+ buildUid: String,
+ ) {
val buildScanHolder = initBuildScanExtensionHolder(project, buildMetricServiceProvider)
if (buildScanHolder != null) {
- subscribeForTaskEventsForBuildScan(project, buildMetricServiceProvider, buildScanHolder)
+ subscribeForTaskEventsForBuildScan(project, buildMetricServiceProvider, buildScanHolder, buildUid)
}
val gradle80withBuildScanReport =
@@ -252,23 +258,28 @@
project: Project,
buildMetricServiceProvider: Provider<BuildMetricsService>,
buildScanHolder: BuildScanExtensionHolder,
+ buildUid: String,
) {
when {
GradleVersion.current().baseVersion < GradleVersion.version("8.0") -> {
buildScanHolder.buildScan.buildFinished {
- buildMetricServiceProvider.map { it.addBuildScanReport(buildScanHolder) }.get()
+ buildMetricServiceProvider.map { it.addBuildScanReport(buildScanHolder, buildUid) }.get()
}
}
GradleVersion.current().baseVersion < GradleVersion.version("8.1") -> {
val buildMetricService = buildMetricServiceProvider.get()
- buildMetricService.buildReportService.initBuildScanTags(buildScanHolder, buildMetricService.parameters.label.orNull)
+ buildMetricService.buildReportService.initBuildScanTags(
+ buildScanHolder,
+ buildMetricService.parameters.label.orNull,
+ buildUid
+ )
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(project.provider {
OperationCompletionListener { event ->
if (event is TaskFinishEvent) {
val buildOperation = buildMetricService.updateBuildOperationRecord(event)
val buildParameters = buildMetricService.parameters.toBuildReportParameters()
val buildReportService = buildMetricServiceProvider.map { it.buildReportService }.get()
- buildReportService.addBuildScanReport(event, buildOperation, buildParameters, buildScanHolder)
+ buildReportService.addBuildScanReport(event, buildOperation, buildParameters, buildScanHolder, buildUid)
buildReportService.onFinish(event, buildOperation, buildParameters)
}
}
@@ -281,8 +292,8 @@
}
}
- fun registerIfAbsent(project: Project) =
- registerIfAbsentImpl(project)?.also { serviceProvider ->
+ fun registerIfAbsent(project: Project, buildIdService: Provider<BuildUidService>) =
+ registerIfAbsentImpl(project, buildIdService)?.also { serviceProvider ->
SingleActionPerProject.run(project, UsesBuildMetricsService::class.java.name) {
project.tasks.withType<UsesBuildMetricsService>().configureEach { task ->
task.buildMetricsService.value(serviceProvider).disallowChanges()
@@ -308,10 +319,10 @@
}
}
- internal fun addBuildScanReport(buildScan: BuildScanExtensionHolder?) {
+ internal fun addBuildScanReport(buildScan: BuildScanExtensionHolder?, buildUid: String) {
if (buildScan == null) return
- buildReportService.initBuildScanTags(buildScan, parameters.label.orNull)
- buildReportService.addBuildScanReport(buildOperationRecords, parameters.toBuildReportParameters(), buildScan)
+ buildReportService.initBuildScanTags(buildScan, parameters.label.orNull, buildUid)
+ buildReportService.addBuildScanReport(buildOperationRecords, parameters.toBuildReportParameters(), buildScan, buildUid)
parameters.buildConfigurationTags.orNull?.forEach { buildScan.buildScan.tag(it.readableString) }
buildReportService.addCollectedTags(buildScan)
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt
index c5d989e..2e8bfded 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/report/BuildReportsService.kt
@@ -27,24 +27,20 @@
import java.util.concurrent.TimeUnit
import kotlin.system.measureTimeMillis
-//Because of https://github.com/gradle/gradle/issues/23359 gradle issue, two build services interaction is not reliable at the end of the build
+//Because of https://github.com/gradle/gradle/issues/23359 gradle issue:
+//interaction between two build services is not reliable at the end of the build
//Switch back to proper BuildService as soon as this issue is fixed
-class BuildReportsService {
+class BuildReportsService(private val buildUid: String) {
private val log = Logging.getLogger(this.javaClass)
private val loggerAdapter = GradleLoggerAdapter(log)
private val startTime = System.nanoTime()
- private val buildUuid = UUID.randomUUID().toString()
private val executorService: ExecutorService = Executors.newSingleThreadExecutor()
private val tags = LinkedHashSet<StatTag>()
private var customValues = 0 // doesn't need to be thread-safe
- init {
- log.info("Build report service is registered. Unique build id: $buildUuid")
- }
-
fun close(
buildOperationRecords: Collection<BuildOperationRecord>,
failureMessages: List<String>,
@@ -68,7 +64,7 @@
it.includeMetricsInReport,
).process(
ReadableFileReportData(
- transformOperationRecordsToCompileStatisticsData(buildOperationRecords, parameters, onlyKotlinTask = false),
+ transformOperationRecordsToCompileStatisticsData(buildOperationRecords, parameters, onlyKotlinTask = false, buildUid),
parameters.startParameters,
failureMessages.filter { it.isNotEmpty() },
),
@@ -88,7 +84,7 @@
JsonReportService(it, parameters.projectName).process(buildData, loggerAdapter)
}
- //It's expected that bad internet connection can cause a significant delay for big project
+ //It's expected that bad internet connection can cause a significant delay for a big project
executorService.shutdown()
}
@@ -96,6 +92,7 @@
buildOperationRecords: Collection<BuildOperationRecord>,
parameters: BuildReportParameters,
onlyKotlinTask: Boolean,
+ buildUid: String,
metricsToShow: Set<String>? = null,
) = buildOperationRecords.mapNotNull {
prepareData(
@@ -104,7 +101,7 @@
it.startTimeMs,
it.totalTimeMs + it.startTimeMs,
parameters.projectName,
- buildUuid,
+ buildUid,
parameters.label,
parameters.kotlinVersion,
it,
@@ -137,7 +134,7 @@
projectName = parameters.projectName,
startParameters = parameters.startParameters
.includeVerboseEnvironment(parameters.reportingSettings.httpReportSettings.verboseEnvironment),
- buildUuid = buildUuid,
+ buildUuid = buildUid,
label = parameters.label,
totalTime = TimeUnit.NANOSECONDS.toMillis((System.nanoTime() - startTime)),
finishTime = System.currentTimeMillis(),
@@ -173,7 +170,7 @@
prepareData(
event,
parameters.projectName,
- buildUuid,
+ buildUid,
parameters.label,
parameters.kotlinVersion,
buildOperationRecord,
@@ -194,13 +191,14 @@
buildOperationRecord: BuildOperationRecord,
parameters: BuildReportParameters,
buildScanExtension: BuildScanExtensionHolder,
+ buildUid: String,
) {
val buildScanSettings = parameters.reportingSettings.buildScanReportSettings ?: return
val (collectDataDuration, compileStatData) = measureTimeMillisWithResult {
prepareData(
event,
- parameters.projectName, buildUuid, parameters.label,
+ parameters.projectName, buildUid, parameters.label,
parameters.kotlinVersion,
buildOperationRecord,
metricsToShow = buildScanSettings.metrics
@@ -217,6 +215,7 @@
buildOperationRecords: Collection<BuildOperationRecord>,
parameters: BuildReportParameters,
buildScanExtension: BuildScanExtensionHolder,
+ buildUid: String,
) {
val buildScanSettings = parameters.reportingSettings.buildScanReportSettings ?: return
@@ -225,7 +224,8 @@
buildOperationRecords,
parameters,
onlyKotlinTask = true,
- metricsToShow = buildScanSettings.metrics
+ buildUid = buildUid,
+ metricsToShow = buildScanSettings.metrics,
)
}
log.debug("Collect data takes $collectDataDuration: $compileStatData")
@@ -314,7 +314,7 @@
val timeData =
data.getBuildTimesMetrics()
- .map { (key, value) -> "${key.getReadableString()}: ${value}ms" } //sometimes it is better to have separate variable to be able debug
+ .map { (key, value) -> "${key.getReadableString()}: ${value}ms" } //sometimes it is better to have a separate variable to be able to debug
val perfData = data.getPerformanceMetrics().map { (key, value) ->
when (key.getType()) {
ValueType.BYTES -> "${key.getReadableString()}: ${formatSize(value)}"
@@ -347,9 +347,8 @@
return splattedString
}
- internal fun initBuildScanTags(buildScan: BuildScanExtensionHolder, label: String?) {
- buildScan.buildScan.tag(buildUuid)
- label?.also {
+ internal fun initBuildScanTags(buildScan: BuildScanExtensionHolder, vararg tags: String?) {
+ tags.filterNotNull().forEach {
buildScan.buildScan.tag(it)
}
}