Fix repeating custom values in build scan. Refactor build statistic
This commit is contained in:
+3
-3
@@ -13,7 +13,7 @@ import org.gradle.api.provider.Provider
|
|||||||
import org.gradle.api.tasks.Classpath
|
import org.gradle.api.tasks.Classpath
|
||||||
import org.gradle.api.tasks.Internal
|
import org.gradle.api.tasks.Internal
|
||||||
import org.jetbrains.kotlin.build.report.metrics.*
|
import org.jetbrains.kotlin.build.report.metrics.*
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClassSnapshotGranularity
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClassSnapshotGranularity
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClassSnapshotGranularity.CLASS_LEVEL
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClassSnapshotGranularity.CLASS_LEVEL
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClassSnapshotGranularity.CLASS_MEMBER_LEVEL
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClassSnapshotGranularity.CLASS_MEMBER_LEVEL
|
||||||
@@ -31,7 +31,7 @@ abstract class ClasspathEntrySnapshotTransform : TransformAction<ClasspathEntryS
|
|||||||
abstract val gradleUserHomeDir: DirectoryProperty
|
abstract val gradleUserHomeDir: DirectoryProperty
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
abstract val buildMetricsReporterService: Property<BuildMetricsReporterService>
|
abstract val buildMetricsService: Property<BuildMetricsService>
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Classpath
|
@get:Classpath
|
||||||
@@ -44,7 +44,7 @@ abstract class ClasspathEntrySnapshotTransform : TransformAction<ClasspathEntryS
|
|||||||
|
|
||||||
val granularity = getClassSnapshotGranularity(classpathEntryInputDirOrJar, parameters.gradleUserHomeDir.get().asFile)
|
val granularity = getClassSnapshotGranularity(classpathEntryInputDirOrJar, parameters.gradleUserHomeDir.get().asFile)
|
||||||
|
|
||||||
val buildMetricsReporterService = parameters.buildMetricsReporterService.orNull
|
val buildMetricsReporterService = parameters.buildMetricsService.orNull
|
||||||
val metricsReporter = buildMetricsReporterService?.let { BuildMetricsReporterImpl() } ?: DoNothingBuildMetricsReporter
|
val metricsReporter = buildMetricsReporterService?.let { BuildMetricsReporterImpl() } ?: DoNothingBuildMetricsReporter
|
||||||
|
|
||||||
val startTimeMs = System.currentTimeMillis()
|
val startTimeMs = System.currentTimeMillis()
|
||||||
|
|||||||
+4
-7
@@ -41,8 +41,8 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSetFactory
|
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSetFactory
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.report.HttpReportService
|
import org.jetbrains.kotlin.gradle.report.BuildReportsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.addNpmDependencyExtension
|
import org.jetbrains.kotlin.gradle.targets.js.npm.addNpmDependencyExtension
|
||||||
@@ -92,12 +92,9 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin {
|
|||||||
KotlinGradleBuildServices.registerIfAbsent(project).get()
|
KotlinGradleBuildServices.registerIfAbsent(project).get()
|
||||||
KotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion)
|
KotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion)
|
||||||
|
|
||||||
BuildMetricsReporterService.registerIfAbsent(project)?.also {
|
BuildMetricsService.registerIfAbsent(project)?.also {
|
||||||
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpReportService.registerIfAbsent(project, kotlinPluginVersion)?.also {
|
|
||||||
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(it)
|
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(it)
|
||||||
|
BuildReportsService.registerIfAbsent(project, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-50
@@ -20,27 +20,17 @@ import org.jetbrains.kotlin.build.report.metrics.BuildMetrics
|
|||||||
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
||||||
import org.jetbrains.kotlin.build.report.metrics.BuildTime
|
import org.jetbrains.kotlin.build.report.metrics.BuildTime
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.GradleBuildStartParameters
|
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionData
|
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionDataProcessor
|
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildOperationRecord
|
import org.jetbrains.kotlin.gradle.report.data.BuildOperationRecord
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
|
|
||||||
abstract class BuildMetricsReporterService : BuildService<BuildMetricsReporterService.Parameters>,
|
abstract class BuildMetricsService : BuildService<BuildServiceParameters.None>, OperationCompletionListener {
|
||||||
OperationCompletionListener, AutoCloseable {
|
|
||||||
|
|
||||||
interface Parameters : BuildServiceParameters {
|
|
||||||
var buildDataProcessors: List<BuildExecutionDataProcessor>
|
|
||||||
var startParameters: GradleBuildStartParameters
|
|
||||||
var reportingSettings: ReportingSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
private val log = Logging.getLogger(this.javaClass)
|
private val log = Logging.getLogger(this.javaClass)
|
||||||
|
|
||||||
// Tasks and transforms' records
|
// Tasks and transforms' records
|
||||||
private val buildOperationRecords = ConcurrentLinkedQueue<BuildOperationRecord>()
|
internal val buildOperationRecords = ConcurrentLinkedQueue<BuildOperationRecord>()
|
||||||
private val failureMessages = ConcurrentLinkedQueue<String>()
|
internal val failureMessages = ConcurrentLinkedQueue<String>()
|
||||||
|
|
||||||
// Info for tasks only
|
// Info for tasks only
|
||||||
private val taskPathToMetricsReporter = ConcurrentHashMap<String, BuildMetricsReporter>()
|
private val taskPathToMetricsReporter = ConcurrentHashMap<String, BuildMetricsReporter>()
|
||||||
@@ -102,55 +92,24 @@ abstract class BuildMetricsReporterService : BuildService<BuildMetricsReporterSe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
|
||||||
val buildData = BuildExecutionData(
|
|
||||||
startParameters = parameters.startParameters,
|
|
||||||
failureMessages = failureMessages.toList(),
|
|
||||||
buildOperationRecord = buildOperationRecords.sortedBy { it.startTimeMs }
|
|
||||||
)
|
|
||||||
parameters.buildDataProcessors.forEach { it.process(buildData, log) }
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val serviceClass = BuildMetricsService::class.java
|
||||||
|
private val serviceName = "${serviceClass.name}_${serviceClass.classLoader.hashCode()}"
|
||||||
|
|
||||||
fun getStartParameters(project: Project) = project.gradle.startParameter.let {
|
fun registerIfAbsent(project: Project): Provider<BuildMetricsService>? {
|
||||||
GradleBuildStartParameters(
|
|
||||||
tasks = it.taskRequests.flatMap { it.args },
|
|
||||||
excludedTasks = it.excludedTaskNames,
|
|
||||||
currentDir = it.currentDir.path,
|
|
||||||
projectProperties = it.projectProperties.map {(key, value) -> "$key: $value"},
|
|
||||||
systemProperties = it.systemPropertiesArgs.map {(key, value) -> "$key: $value"},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun registerIfAbsent(project: Project): Provider<BuildMetricsReporterService>? {
|
|
||||||
val serviceClass = BuildMetricsReporterService::class.java
|
|
||||||
val serviceName = "${serviceClass.name}_${serviceClass.classLoader.hashCode()}"
|
|
||||||
|
|
||||||
// Return early if the service was already registered to avoid the overhead of reading the reporting settings below
|
// 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 {
|
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return it.service as Provider<BuildMetricsReporterService>
|
return it.service as Provider<BuildMetricsService>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//do not need to collect metrics if there aren't consumers for this data
|
||||||
val reportingSettings = reportingSettings(project.rootProject)
|
val reportingSettings = reportingSettings(project.rootProject)
|
||||||
if (reportingSettings.buildReportOutputs.isEmpty()) {
|
if (reportingSettings.buildReportOutputs.isEmpty()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return project.gradle.sharedServices.registerIfAbsent(serviceName, serviceClass) {
|
return project.gradle.sharedServices.registerIfAbsent(serviceName, serviceClass) {}!!
|
||||||
val buildDataProcessors = mutableListOf<BuildExecutionDataProcessor>()
|
|
||||||
reportingSettings.fileReportSettings?.let { fileReportSettings ->
|
|
||||||
buildDataProcessors.add(PlainTextBuildReportWriterDataProcessor(fileReportSettings, project.rootProject.name))
|
|
||||||
}
|
|
||||||
reportingSettings.singleOutputFile?.let { singleOutputFile ->
|
|
||||||
buildDataProcessors.add(MetricsWriter(singleOutputFile.absoluteFile))
|
|
||||||
}
|
|
||||||
|
|
||||||
it.parameters.startParameters = getStartParameters(project)
|
|
||||||
it.parameters.buildDataProcessors = buildDataProcessors
|
|
||||||
it.parameters.reportingSettings = reportingSettings
|
|
||||||
}!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+273
@@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* 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.google.gson.Gson
|
||||||
|
import com.gradle.scan.plugin.BuildScanExtension
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.invocation.Gradle
|
||||||
|
import org.gradle.api.logging.Logging
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.services.BuildService
|
||||||
|
import org.gradle.api.services.BuildServiceParameters
|
||||||
|
import org.gradle.tooling.events.FinishEvent
|
||||||
|
import org.gradle.tooling.events.OperationCompletionListener
|
||||||
|
import org.gradle.tooling.events.task.TaskFinishEvent
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.BuildEventsListenerRegistryHolder
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.stat.BuildFinishStatisticsData
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.stat.GradleBuildStartParameters
|
||||||
|
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.utils.isConfigurationCacheAvailable
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.HttpURLConnection
|
||||||
|
import java.net.URL
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
abstract class BuildReportsService : BuildService<BuildReportsService.Parameters>, AutoCloseable, OperationCompletionListener {
|
||||||
|
|
||||||
|
private val log = Logging.getLogger(this.javaClass)
|
||||||
|
|
||||||
|
private val startTime = System.nanoTime()
|
||||||
|
private val buildUuid = UUID.randomUUID().toString()
|
||||||
|
private var executorService: ExecutorService = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
log.info("Build report service is registered. Unique build id: $buildUuid")
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Parameters : BuildServiceParameters {
|
||||||
|
val startParameters: Property<GradleBuildStartParameters>
|
||||||
|
val reportingSettings: Property<ReportingSettings>
|
||||||
|
var buildMetricsService: Provider<BuildMetricsService>
|
||||||
|
|
||||||
|
val label: Property<String?>
|
||||||
|
val projectName: Property<String>
|
||||||
|
val kotlinVersion: Property<String>
|
||||||
|
val additionalTags: ListProperty<StatTag>
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
val buildData = BuildExecutionData(
|
||||||
|
startParameters = parameters.startParameters.get(),
|
||||||
|
failureMessages = parameters.buildMetricsService.orNull?.failureMessages?.toList() ?: emptyList(),
|
||||||
|
buildOperationRecord = parameters.buildMetricsService.orNull?.buildOperationRecords?.sortedBy { it.startTimeMs } ?: emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
val reportingSettings = parameters.reportingSettings.get()
|
||||||
|
|
||||||
|
reportingSettings.httpReportSettings?.also {
|
||||||
|
executorService.submit { reportBuildFinish() } //
|
||||||
|
}
|
||||||
|
reportingSettings.fileReportSettings?.also {
|
||||||
|
reportBuildStatInFile(it, buildData)
|
||||||
|
}
|
||||||
|
|
||||||
|
reportingSettings.singleOutputFile?.also { singleOutputFile ->
|
||||||
|
MetricsWriter(singleOutputFile.absoluteFile).process(buildData, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
//It's expected that bad internet connection can cause a significant delay for big project
|
||||||
|
executorService.shutdownNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish(event: FinishEvent?) {
|
||||||
|
addHttpReport(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportBuildStatInFile(fileReportSettings: FileReportSettings, buildData: BuildExecutionData) {
|
||||||
|
val ts = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Calendar.getInstance().time)
|
||||||
|
val reportFile = fileReportSettings.buildReportDir.resolve("${parameters.projectName.get()}-build-$ts.txt")
|
||||||
|
|
||||||
|
PlainTextBuildReportWriter(
|
||||||
|
outputFile = reportFile,
|
||||||
|
printMetrics = fileReportSettings.includeMetricsInReport
|
||||||
|
).process(buildData, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportBuildFinish() {
|
||||||
|
val buildFinishData = BuildFinishStatisticsData(
|
||||||
|
projectName = parameters.projectName.get(),
|
||||||
|
startParameters = parameters.startParameters.get(),
|
||||||
|
buildUuid = buildUuid,
|
||||||
|
label = parameters.label.orNull,
|
||||||
|
totalTime = (System.nanoTime() - startTime) / 1_000_000
|
||||||
|
)
|
||||||
|
sendDataViaHttp(buildFinishData)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initService(project: Project) {
|
||||||
|
addListeners(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addBuildScanReport(project: Project) {
|
||||||
|
if (parameters.reportingSettings.get().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?) {
|
||||||
|
if (parameters.reportingSettings.get().httpReportSettings != null) {
|
||||||
|
if (event is TaskFinishEvent) {
|
||||||
|
val data =
|
||||||
|
KotlinBuildStatListener.prepareData(
|
||||||
|
event,
|
||||||
|
parameters.projectName.get(),
|
||||||
|
buildUuid,
|
||||||
|
parameters.label.orNull,
|
||||||
|
parameters.kotlinVersion.get(),
|
||||||
|
parameters.additionalTags.get()
|
||||||
|
)
|
||||||
|
data?.also { executorService.submit { sendDataViaHttp(data) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addListeners(project: Project) {
|
||||||
|
addBuildScanReport(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var invalidUrl = false
|
||||||
|
private var requestPreviousFailed = false
|
||||||
|
private fun sendDataViaHttp(data: Any) {
|
||||||
|
val httpSettings = parameters.reportingSettings.get().httpReportSettings ?: return
|
||||||
|
|
||||||
|
val elapsedTime = measureTimeMillis {
|
||||||
|
if (invalidUrl) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val connection = try {
|
||||||
|
URL(httpSettings.url).openConnection() as HttpURLConnection
|
||||||
|
} catch (e: IOException) {
|
||||||
|
log.warn("Unable to open connection to ${httpSettings.url}: ${e.message}")
|
||||||
|
invalidUrl = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (httpSettings.user != null && httpSettings.password != null) {
|
||||||
|
val auth = Base64.getEncoder()
|
||||||
|
.encode("${httpSettings.user}:${httpSettings.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)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log.debug("Unexpected exception happened ${e.message}: ${e.stackTrace}")
|
||||||
|
checkResponseAndLog(connection)
|
||||||
|
} finally {
|
||||||
|
connection.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("Report statistic by http takes $elapsedTime ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkResponseAndLog(connection: HttpURLConnection) {
|
||||||
|
val isResponseBad = connection.responseCode !in 200..299
|
||||||
|
if (isResponseBad) {
|
||||||
|
val message = "Failed to send statistic to ${connection.url} with ${connection.responseCode}: ${connection.responseMessage}"
|
||||||
|
if (!requestPreviousFailed) {
|
||||||
|
log.warn(message)
|
||||||
|
} else {
|
||||||
|
log.debug(message)
|
||||||
|
}
|
||||||
|
requestPreviousFailed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun getStartParameters(project: Project) = project.gradle.startParameter.let {
|
||||||
|
GradleBuildStartParameters(
|
||||||
|
tasks = it.taskRequests.flatMap { it.args },
|
||||||
|
excludedTasks = it.excludedTaskNames,
|
||||||
|
currentDir = it.currentDir.path,
|
||||||
|
projectProperties = it.projectProperties.map { (key, value) -> "$key: $value" },
|
||||||
|
systemProperties = it.systemPropertiesArgs.map { (key, value) -> "$key: $value" },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerIfAbsent(project: Project, buildMetricsService: Provider<BuildMetricsService>): Provider<BuildReportsService>? {
|
||||||
|
val serviceClass = BuildReportsService::class.java
|
||||||
|
val serviceName = "${serviceClass.name}_${serviceClass.classLoader.hashCode()}"
|
||||||
|
|
||||||
|
val reportingSettings = reportingSettings(project.rootProject)
|
||||||
|
if (reportingSettings.buildReportOutputs.isEmpty()) {
|
||||||
|
return null //no need to collect data
|
||||||
|
}
|
||||||
|
|
||||||
|
val kotlinVersion = project.getKotlinPluginVersion()
|
||||||
|
val gradle = project.gradle
|
||||||
|
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return it.service as Provider<BuildReportsService>
|
||||||
|
}
|
||||||
|
|
||||||
|
return gradle.sharedServices.registerIfAbsent(serviceName, serviceClass) {
|
||||||
|
it.parameters.label.set(reportingSettings.buildReportLabel)
|
||||||
|
it.parameters.projectName.set(project.rootProject.name)
|
||||||
|
it.parameters.kotlinVersion.set(kotlinVersion)
|
||||||
|
it.parameters.startParameters.set(getStartParameters(project))
|
||||||
|
it.parameters.reportingSettings.set(reportingSettings)
|
||||||
|
it.parameters.buildMetricsService = buildMetricsService
|
||||||
|
|
||||||
|
//init gradle tags for build scan and http reports
|
||||||
|
it.parameters.additionalTags.value(setupTags(gradle))
|
||||||
|
}!!.also {
|
||||||
|
val buildReportsService = it.get()
|
||||||
|
buildReportsService.initService(project)
|
||||||
|
if (buildReportsService.parameters.reportingSettings.get().buildReportOutputs.contains(BuildReportType.HTTP)) {
|
||||||
|
BuildEventsListenerRegistryHolder.getInstance(project).listenerRegistry.onTaskCompletion(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupTags(gradle: Gradle): ArrayList<StatTag> {
|
||||||
|
val additionalTags = ArrayList<StatTag>()
|
||||||
|
if (isConfigurationCacheAvailable(gradle)) {
|
||||||
|
additionalTags.add(StatTag.CONFIGURATION_CACHE)
|
||||||
|
}
|
||||||
|
if (gradle.startParameter.isBuildCacheEnabled) {
|
||||||
|
additionalTags.add(StatTag.BUILD_CACHE)
|
||||||
|
}
|
||||||
|
return additionalTags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
-194
@@ -1,194 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.google.gson.Gson
|
|
||||||
import com.gradle.scan.plugin.BuildScanExtension
|
|
||||||
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 org.gradle.tooling.events.FinishEvent
|
|
||||||
import org.gradle.tooling.events.OperationCompletionListener
|
|
||||||
import org.gradle.tooling.events.task.TaskFinishEvent
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.BuildFinishStatisticsData
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.BuildEventsListenerRegistryHolder
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.GradleBuildStartParameters
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.stat.StatTag
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.BuildScanStatisticsListener
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatListener.Companion.prepareData
|
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService.Companion.getStartParameters
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
|
||||||
import java.io.IOException
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.URL
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.ExecutorService
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import kotlin.system.measureTimeMillis
|
|
||||||
|
|
||||||
abstract class HttpReportService : BuildService<HttpReportService.Parameters>,
|
|
||||||
OperationCompletionListener, AutoCloseable {
|
|
||||||
|
|
||||||
var executorService: ExecutorService = Executors.newSingleThreadExecutor()
|
|
||||||
|
|
||||||
val startTime = System.nanoTime()
|
|
||||||
|
|
||||||
interface Parameters : BuildServiceParameters {
|
|
||||||
var label: String?
|
|
||||||
var projectName: String
|
|
||||||
var httpSettings: HttpReportSettings
|
|
||||||
var kotlinVersion: String
|
|
||||||
var additionalTags: List<StatTag>
|
|
||||||
var startParameters: GradleBuildStartParameters
|
|
||||||
}
|
|
||||||
|
|
||||||
val log = Logging.getLogger(this.javaClass)
|
|
||||||
|
|
||||||
init {
|
|
||||||
log.info("Http report service is registered. Unique build id: $buildUuid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Volatile for one thread executor it does not need
|
|
||||||
private var requestPreviousFailed = false
|
|
||||||
private var invalidUrl = false
|
|
||||||
|
|
||||||
override fun onFinish(event: FinishEvent?) {
|
|
||||||
if (event is TaskFinishEvent) {
|
|
||||||
val data =
|
|
||||||
prepareData(event, parameters.projectName, buildUuid, parameters.label, parameters.kotlinVersion, parameters.additionalTags)
|
|
||||||
data?.also { executorService.submit { report(data) } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun close() {
|
|
||||||
executorService.submit { reportBuildFinish() }
|
|
||||||
executorService.shutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
val buildUuid = UUID.randomUUID().toString()
|
|
||||||
|
|
||||||
fun registerIfAbsent(project: Project, kotlinVersion: String): Provider<HttpReportService>? {
|
|
||||||
val gradle = project.gradle
|
|
||||||
val rootProject = gradle.rootProject
|
|
||||||
val reportingSettings = reportingSettings(rootProject)
|
|
||||||
|
|
||||||
addListeners(project, reportingSettings, kotlinVersion)
|
|
||||||
|
|
||||||
return reportingSettings.httpReportSettings?.let { httpSettings ->
|
|
||||||
gradle.sharedServices.registerIfAbsent(
|
|
||||||
"build_http_metric_service_${HttpReportService::class.java.classLoader.hashCode()}",
|
|
||||||
HttpReportService::class.java
|
|
||||||
) {
|
|
||||||
it.parameters.label = reportingSettings.buildReportLabel
|
|
||||||
it.parameters.projectName = rootProject.name
|
|
||||||
it.parameters.httpSettings = httpSettings
|
|
||||||
it.parameters.kotlinVersion = kotlinVersion
|
|
||||||
it.parameters.startParameters = getStartParameters(project)
|
|
||||||
|
|
||||||
//init gradle tags, that present in build scan
|
|
||||||
val additionalTags = ArrayList<StatTag>()
|
|
||||||
if (isConfigurationCacheAvailable(gradle)) {
|
|
||||||
additionalTags.add(StatTag.CONFIGURATION_CACHE)
|
|
||||||
}
|
|
||||||
if (gradle.startParameter.isBuildCacheEnabled) {
|
|
||||||
additionalTags.add(StatTag.BUILD_CACHE)
|
|
||||||
}
|
|
||||||
it.parameters.additionalTags = additionalTags
|
|
||||||
}!!
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addListeners(project: Project, reportingSettings: ReportingSettings, kotlinVersion: String) {
|
|
||||||
if (reportingSettings.buildReportOutputs.contains(BuildReportType.BUILD_SCAN)) {
|
|
||||||
project.rootProject.extensions.findByName("buildScan")
|
|
||||||
?.also {
|
|
||||||
val listenerRegistryHolder = BuildEventsListenerRegistryHolder.getInstance(project)
|
|
||||||
listenerRegistryHolder.listenerRegistry.onTaskCompletion(
|
|
||||||
project.provider {
|
|
||||||
BuildScanStatisticsListener(
|
|
||||||
it as BuildScanExtension,
|
|
||||||
project.rootProject.name,
|
|
||||||
reportingSettings.buildReportLabel,
|
|
||||||
kotlinVersion,
|
|
||||||
buildUuid
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun report(data: Any) {
|
|
||||||
val elapsedTime = measureTimeMillis {
|
|
||||||
if (invalidUrl) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val connection = try {
|
|
||||||
URL(parameters.httpSettings.url).openConnection() as HttpURLConnection
|
|
||||||
} catch (e: IOException) {
|
|
||||||
log.warn("Unable to open connection to ${parameters.httpSettings.url}: ${e.message}")
|
|
||||||
invalidUrl = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (parameters.httpSettings.user != null && parameters.httpSettings.password != null) {
|
|
||||||
val auth = Base64.getEncoder()
|
|
||||||
.encode("${parameters.httpSettings.user}:${parameters.httpSettings.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() } }
|
|
||||||
} catch (e: Exception) {
|
|
||||||
log.debug("Unexpected exception happened ${e.message}: ${e.stackTrace}")
|
|
||||||
checkResponseAndLog(connection)
|
|
||||||
} finally {
|
|
||||||
connection.disconnect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.debug("Report statistic by http takes $elapsedTime ms")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reportBuildFinish() {
|
|
||||||
val buildFinishData = BuildFinishStatisticsData(
|
|
||||||
projectName = parameters.projectName,
|
|
||||||
startParameters = parameters.startParameters,
|
|
||||||
buildUuid = buildUuid,
|
|
||||||
label = parameters.label,
|
|
||||||
totalTime = (System.nanoTime() - startTime) / 1_000_000
|
|
||||||
)
|
|
||||||
report(buildFinishData)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkResponseAndLog(connection: HttpURLConnection) {
|
|
||||||
val isResponseBad = connection.responseCode !in 200..299
|
|
||||||
if (isResponseBad) {
|
|
||||||
val message = "Failed to send statistic to ${connection.url} with ${connection.responseCode}: ${connection.responseMessage}"
|
|
||||||
if (!requestPreviousFailed) {
|
|
||||||
log.warn(message)
|
|
||||||
} else {
|
|
||||||
log.debug(message)
|
|
||||||
}
|
|
||||||
requestPreviousFailed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+2
-3
@@ -12,15 +12,14 @@ import org.jetbrains.kotlin.gradle.internal.build.metrics.GradleBuildMetricsData
|
|||||||
import org.jetbrains.kotlin.gradle.internal.build.metrics.BuildOperationData
|
import org.jetbrains.kotlin.gradle.internal.build.metrics.BuildOperationData
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionData
|
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionData
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionDataProcessor
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.ObjectOutputStream
|
import java.io.ObjectOutputStream
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
internal class MetricsWriter(
|
internal class MetricsWriter(
|
||||||
private val outputFile: File,
|
private val outputFile: File,
|
||||||
) : BuildExecutionDataProcessor, Serializable {
|
): Serializable {
|
||||||
override fun process(build: BuildExecutionData, log: Logger) {
|
fun process(build: BuildExecutionData, log: Logger) {
|
||||||
if (build.failureMessages.isNotEmpty()) return
|
if (build.failureMessages.isNotEmpty()) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
-17
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.report
|
|||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.jetbrains.kotlin.build.report.metrics.*
|
import org.jetbrains.kotlin.build.report.metrics.*
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionData
|
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionData
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildExecutionDataProcessor
|
|
||||||
import org.jetbrains.kotlin.gradle.report.data.BuildOperationRecord
|
import org.jetbrains.kotlin.gradle.report.data.BuildOperationRecord
|
||||||
import org.jetbrains.kotlin.gradle.utils.Printer
|
import org.jetbrains.kotlin.gradle.utils.Printer
|
||||||
import org.jetbrains.kotlin.gradle.utils.asString
|
import org.jetbrains.kotlin.gradle.utils.asString
|
||||||
@@ -16,25 +15,9 @@ import org.jetbrains.kotlin.gradle.utils.formatSize
|
|||||||
import org.jetbrains.kotlin.gradle.utils.formatTime
|
import org.jetbrains.kotlin.gradle.utils.formatTime
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
internal class PlainTextBuildReportWriterDataProcessor(
|
|
||||||
val reportingSettings: FileReportSettings,
|
|
||||||
val rootProjectName: String
|
|
||||||
) : BuildExecutionDataProcessor, Serializable {
|
|
||||||
override fun process(build: BuildExecutionData, log: Logger) {
|
|
||||||
val ts = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Calendar.getInstance().time)
|
|
||||||
val reportFile = reportingSettings.buildReportDir.resolve("${rootProjectName}-build-$ts.txt")
|
|
||||||
|
|
||||||
PlainTextBuildReportWriter(
|
|
||||||
outputFile = reportFile,
|
|
||||||
printMetrics = reportingSettings.includeMetricsInReport
|
|
||||||
).process(build, log)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class PlainTextBuildReportWriter(
|
internal class PlainTextBuildReportWriter(
|
||||||
private val outputFile: File,
|
private val outputFile: File,
|
||||||
private val printMetrics: Boolean
|
private val printMetrics: Boolean
|
||||||
|
|||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 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.data
|
|
||||||
|
|
||||||
import org.gradle.api.logging.Logger
|
|
||||||
|
|
||||||
interface BuildExecutionDataProcessor {
|
|
||||||
fun process(build: BuildExecutionData, log: Logger)
|
|
||||||
}
|
|
||||||
+3
-3
@@ -12,7 +12,7 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDceDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDceDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
|
||||||
@@ -211,8 +211,8 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
task.description = "build webpack ${mode.name.toLowerCase()} bundle"
|
task.description = "build webpack ${mode.name.toLowerCase()} bundle"
|
||||||
task._destinationDirectory = binary.distribution.directory
|
task._destinationDirectory = binary.distribution.directory
|
||||||
|
|
||||||
BuildMetricsReporterService.registerIfAbsent(project)?.let {
|
BuildMetricsService.registerIfAbsent(project)?.let {
|
||||||
task.buildMetricsReporterService.value(it)
|
task.buildMetricsService.value(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
task.dependsOn(
|
task.dependsOn(
|
||||||
|
|||||||
+3
-3
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isTest
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isTest
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.executeTaskBaseName
|
import org.jetbrains.kotlin.gradle.targets.js.ir.executeTaskBaseName
|
||||||
@@ -237,8 +237,8 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) :
|
|||||||
task.description = "build webpack ${type.name.toLowerCase()} bundle"
|
task.description = "build webpack ${type.name.toLowerCase()} bundle"
|
||||||
task._destinationDirectory = distribution.directory
|
task._destinationDirectory = distribution.directory
|
||||||
|
|
||||||
BuildMetricsReporterService.registerIfAbsent(project)?.let {
|
BuildMetricsService.registerIfAbsent(project)?.let {
|
||||||
task.buildMetricsReporterService.value(it)
|
task.buildMetricsService.value(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
task.commonConfigure(
|
task.commonConfigure(
|
||||||
|
|||||||
+3
-3
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl
|
||||||
@@ -73,7 +73,7 @@ constructor(
|
|||||||
get() = injected
|
get() = injected
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal abstract val buildMetricsReporterService: Property<BuildMetricsReporterService?>
|
internal abstract val buildMetricsService: Property<BuildMetricsService?>
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
val metrics: Property<BuildMetricsReporter> = project.objects
|
val metrics: Property<BuildMetricsReporter> = project.objects
|
||||||
@@ -330,7 +330,7 @@ constructor(
|
|||||||
buildMetrics.addMetric(BuildPerformanceMetric.BUNDLE_SIZE, it)
|
buildMetrics.addMetric(BuildPerformanceMetric.BUNDLE_SIZE, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildMetricsReporterService.orNull?.also { it.addTask(path, this.javaClass, buildMetrics) }
|
buildMetricsService.orNull?.also { it.addTask(path, this.javaClass, buildMetrics) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-7
@@ -51,8 +51,9 @@ import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildReportMode
|
import org.jetbrains.kotlin.gradle.report.BuildReportMode
|
||||||
|
import org.jetbrains.kotlin.gradle.report.BuildReportsService
|
||||||
import org.jetbrains.kotlin.gradle.report.ReportingSettings
|
import org.jetbrains.kotlin.gradle.report.ReportingSettings
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.*
|
||||||
import org.jetbrains.kotlin.incremental.*
|
import org.jetbrains.kotlin.incremental.*
|
||||||
@@ -270,16 +271,19 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
|
|||||||
internal open fun isIncrementalCompilationEnabled(): Boolean =
|
internal open fun isIncrementalCompilationEnabled(): Boolean =
|
||||||
incremental
|
incremental
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
val startParameters = BuildMetricsReporterService.getStartParameters(project)
|
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
abstract val ownModuleName: Property<String>
|
abstract val ownModuleName: Property<String>
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal abstract val buildMetricsReporterService: Property<BuildMetricsReporterService?>
|
internal abstract val buildMetricsService: Property<BuildMetricsService?>
|
||||||
|
|
||||||
internal fun reportingSettings() = buildMetricsReporterService.orNull?.parameters?.reportingSettings ?: ReportingSettings()
|
@get:Internal
|
||||||
|
internal abstract val buildReportsService: Property<BuildReportsService?>
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val startParameters = BuildReportsService.getStartParameters(project)
|
||||||
|
|
||||||
|
internal fun reportingSettings() = buildReportsService.orNull?.parameters?.reportingSettings?.orNull ?: ReportingSettings()
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
protected val multiModuleICSettings: MultiModuleICSettings
|
protected val multiModuleICSettings: MultiModuleICSettings
|
||||||
@@ -403,7 +407,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> @Inject constr
|
|||||||
executeImpl(inputChanges, outputsBackup)
|
executeImpl(inputChanges, outputsBackup)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildMetricsReporterService.orNull?.also { it.addTask(path, this.javaClass, buildMetrics) }
|
buildMetricsService.orNull?.also { it.addTask(path, this.javaClass, buildMetrics) }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun skipCondition(): Boolean = sources.isEmpty
|
protected open fun skipCondition(): Boolean = sources.isEmpty
|
||||||
|
|||||||
+7
-3
@@ -19,7 +19,8 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPro
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithClosure
|
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithClosure
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinOptions
|
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinOptions
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
|
import org.jetbrains.kotlin.gradle.report.BuildReportsService
|
||||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_BUILD_DIR_NAME
|
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_BUILD_DIR_NAME
|
||||||
import org.jetbrains.kotlin.project.model.LanguageSettings
|
import org.jetbrains.kotlin.project.model.LanguageSettings
|
||||||
@@ -58,10 +59,13 @@ internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile
|
|||||||
.disallowChanges()
|
.disallowChanges()
|
||||||
|
|
||||||
task.localStateDirectories.from(task.taskBuildLocalStateDirectory).disallowChanges()
|
task.localStateDirectories.from(task.taskBuildLocalStateDirectory).disallowChanges()
|
||||||
BuildMetricsReporterService.registerIfAbsent(project)?.let {
|
val buildMetricsService = BuildMetricsService.registerIfAbsent(project)?.also {
|
||||||
task.buildMetricsReporterService.value(it)
|
task.buildMetricsService.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())
|
||||||
|
|||||||
+4
-4
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildMetricsReporterService
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import org.jetbrains.kotlin.project.model.LanguageSettings
|
import org.jetbrains.kotlin.project.model.LanguageSettings
|
||||||
|
|
||||||
@@ -111,18 +111,18 @@ internal open class BaseKotlinCompileConfig<TASK : KotlinCompile> : AbstractKotl
|
|||||||
}
|
}
|
||||||
project.extensions.extraProperties[TRANSFORMS_REGISTERED] = true
|
project.extensions.extraProperties[TRANSFORMS_REGISTERED] = true
|
||||||
|
|
||||||
val buildMetricsReporterService = BuildMetricsReporterService.registerIfAbsent(project)
|
val buildMetricsService = BuildMetricsService.registerIfAbsent(project)
|
||||||
project.dependencies.registerTransform(ClasspathEntrySnapshotTransform::class.java) {
|
project.dependencies.registerTransform(ClasspathEntrySnapshotTransform::class.java) {
|
||||||
it.from.attribute(ARTIFACT_TYPE_ATTRIBUTE, JAR_ARTIFACT_TYPE)
|
it.from.attribute(ARTIFACT_TYPE_ATTRIBUTE, JAR_ARTIFACT_TYPE)
|
||||||
it.to.attribute(ARTIFACT_TYPE_ATTRIBUTE, CLASSPATH_ENTRY_SNAPSHOT_ARTIFACT_TYPE)
|
it.to.attribute(ARTIFACT_TYPE_ATTRIBUTE, CLASSPATH_ENTRY_SNAPSHOT_ARTIFACT_TYPE)
|
||||||
it.parameters.gradleUserHomeDir.set(project.gradle.gradleUserHomeDir)
|
it.parameters.gradleUserHomeDir.set(project.gradle.gradleUserHomeDir)
|
||||||
buildMetricsReporterService?.apply { it.parameters.buildMetricsReporterService.set(this) }
|
buildMetricsService?.apply { it.parameters.buildMetricsService.set(this) }
|
||||||
}
|
}
|
||||||
project.dependencies.registerTransform(ClasspathEntrySnapshotTransform::class.java) {
|
project.dependencies.registerTransform(ClasspathEntrySnapshotTransform::class.java) {
|
||||||
it.from.attribute(ARTIFACT_TYPE_ATTRIBUTE, DIRECTORY_ARTIFACT_TYPE)
|
it.from.attribute(ARTIFACT_TYPE_ATTRIBUTE, DIRECTORY_ARTIFACT_TYPE)
|
||||||
it.to.attribute(ARTIFACT_TYPE_ATTRIBUTE, CLASSPATH_ENTRY_SNAPSHOT_ARTIFACT_TYPE)
|
it.to.attribute(ARTIFACT_TYPE_ATTRIBUTE, CLASSPATH_ENTRY_SNAPSHOT_ARTIFACT_TYPE)
|
||||||
it.parameters.gradleUserHomeDir.set(project.gradle.gradleUserHomeDir)
|
it.parameters.gradleUserHomeDir.set(project.gradle.gradleUserHomeDir)
|
||||||
buildMetricsReporterService?.apply { it.parameters.buildMetricsReporterService.set(this) }
|
buildMetricsService?.apply { it.parameters.buildMetricsService.set(this) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user