Added FUS extensions and new metrics for reporting statistics from gradle
This commit is contained in:
@@ -21,11 +21,26 @@ enum class FUSEventGroups(groupIdSuffix: String, val events: Set<String> = setOf
|
|||||||
Debug("ide.debugger"),
|
Debug("ide.debugger"),
|
||||||
J2K("ide.j2k"),
|
J2K("ide.j2k"),
|
||||||
Editor("ide.editor"),
|
Editor("ide.editor"),
|
||||||
Settings("ide.settings");
|
Settings("ide.settings"),
|
||||||
|
GradlePerformance("gradle.performance");
|
||||||
|
|
||||||
val GROUP_ID: String = "kotlin.$groupIdSuffix"
|
val GROUP_ID: String = "kotlin.$groupIdSuffix"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("EnumEntryName")
|
||||||
|
enum class GradleStatisticsEvents {
|
||||||
|
Environment,
|
||||||
|
Kapt,
|
||||||
|
CompilerPlugins,
|
||||||
|
MPP,
|
||||||
|
Libraries,
|
||||||
|
GradleConfiguration,
|
||||||
|
ComponentVersions,
|
||||||
|
KotlinFeatures,
|
||||||
|
GradlePerformance,
|
||||||
|
UseScenarios
|
||||||
|
}
|
||||||
|
|
||||||
val gradleTargetEvents = setOf(
|
val gradleTargetEvents = setOf(
|
||||||
"kotlin-android",
|
"kotlin-android",
|
||||||
"kotlin-platform-common",
|
"kotlin-platform-common",
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ dependencies {
|
|||||||
compileOnly(intellijPluginDep("junit"))
|
compileOnly(intellijPluginDep("junit"))
|
||||||
compileOnly(intellijPluginDep("testng"))
|
compileOnly(intellijPluginDep("testng"))
|
||||||
|
|
||||||
|
compileOnly(project(":kotlin-gradle-statistics"))
|
||||||
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
compileOnly(intellijPluginDep("java"))
|
compileOnly(intellijPluginDep("java"))
|
||||||
testCompileOnly(intellijPluginDep("java"))
|
testCompileOnly(intellijPluginDep("java"))
|
||||||
|
|||||||
+2
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.util.NotNullableCopyableDataNodeUserDataPropert
|
|||||||
import org.jetbrains.kotlin.idea.util.PsiPrecedences
|
import org.jetbrains.kotlin.idea.util.PsiPrecedences
|
||||||
import org.jetbrains.kotlin.idea.statistics.FUSEventGroups
|
import org.jetbrains.kotlin.idea.statistics.FUSEventGroups
|
||||||
import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger
|
import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger
|
||||||
|
import org.jetbrains.kotlin.idea.statistics.KotlinGradleFUSLogger
|
||||||
import org.jetbrains.plugins.gradle.model.ExternalProjectDependency
|
import org.jetbrains.plugins.gradle.model.ExternalProjectDependency
|
||||||
import org.jetbrains.plugins.gradle.model.ExternalSourceSet
|
import org.jetbrains.plugins.gradle.model.ExternalSourceSet
|
||||||
import org.jetbrains.plugins.gradle.model.FileCollectionDependency
|
import org.jetbrains.plugins.gradle.model.FileCollectionDependency
|
||||||
@@ -294,6 +295,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
|
|||||||
nextResolver.populateModuleContentRoots(gradleModule, ideModule)
|
nextResolver.populateModuleContentRoots(gradleModule, ideModule)
|
||||||
val moduleNamePrefix = GradleProjectResolverUtil.getModuleId(resolverCtx, gradleModule)
|
val moduleNamePrefix = GradleProjectResolverUtil.getModuleId(resolverCtx, gradleModule)
|
||||||
resolverCtx.getExtraProject(gradleModule, KotlinGradleModel::class.java)?.let { gradleModel ->
|
resolverCtx.getExtraProject(gradleModule, KotlinGradleModel::class.java)?.let { gradleModel ->
|
||||||
|
KotlinGradleFUSLogger.populateGradleUserDir(gradleModel.gradleUserHome)
|
||||||
ideModule.pureKotlinSourceFolders =
|
ideModule.pureKotlinSourceFolders =
|
||||||
gradleModel.kotlinTaskProperties.flatMap { it.value.pureKotlinSourceFolders ?: emptyList() }.map { it.absolutePath }
|
gradleModel.kotlinTaskProperties.flatMap { it.value.pureKotlinSourceFolders ?: emptyList() }.map { it.absolutePath }
|
||||||
val gradleSourceSets = ideModule.children.filter { it.data is GradleSourceSetData } as Collection<DataNode<GradleSourceSetData>>
|
val gradleSourceSets = ideModule.children.filter { it.data is GradleSourceSetData } as Collection<DataNode<GradleSourceSetData>>
|
||||||
|
|||||||
+6
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.configuration
|
package org.jetbrains.kotlin.idea.configuration
|
||||||
|
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.externalSystem.model.DataNode
|
import com.intellij.openapi.externalSystem.model.DataNode
|
||||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||||
@@ -54,6 +55,7 @@ import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
|
|||||||
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedVersionByModuleData
|
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedVersionByModuleData
|
||||||
import org.jetbrains.kotlin.idea.platform.tooling
|
import org.jetbrains.kotlin.idea.platform.tooling
|
||||||
import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders
|
import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders
|
||||||
|
import org.jetbrains.kotlin.idea.statistics.KotlinGradleFUSLogger
|
||||||
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
|
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
|
||||||
import org.jetbrains.kotlin.platform.IdePlatformKind
|
import org.jetbrains.kotlin.platform.IdePlatformKind
|
||||||
import org.jetbrains.kotlin.platform.impl.isCommon
|
import org.jetbrains.kotlin.platform.impl.isCommon
|
||||||
@@ -153,6 +155,10 @@ class KotlinGradleProjectDataService : AbstractProjectDataService<ModuleData, Vo
|
|||||||
|
|
||||||
val codeStyleStr = GradlePropertiesFileFacade.forProject(project).readProperty(KOTLIN_CODE_STYLE_GRADLE_SETTING)
|
val codeStyleStr = GradlePropertiesFileFacade.forProject(project).readProperty(KOTLIN_CODE_STYLE_GRADLE_SETTING)
|
||||||
ProjectCodeStyleImporter.apply(project, codeStyleStr)
|
ProjectCodeStyleImporter.apply(project, codeStyleStr)
|
||||||
|
|
||||||
|
ApplicationManager.getApplication().executeOnPooledThread {
|
||||||
|
KotlinGradleFUSLogger.reportStatistics()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.idea.statistics
|
||||||
|
|
||||||
|
import com.intellij.ide.util.PropertiesComponent
|
||||||
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.project.DumbAware
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.startup.StartupActivity
|
||||||
|
import com.intellij.util.concurrency.AppExecutorUtil
|
||||||
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger
|
||||||
|
import java.io.File
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger.Companion.STATISTICS_FOLDER_NAME
|
||||||
|
import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer
|
||||||
|
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
||||||
|
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
||||||
|
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||||
|
|
||||||
|
class KotlinGradleFUSLogger : StartupActivity, DumbAware, Runnable {
|
||||||
|
|
||||||
|
override fun runActivity(project: Project) {
|
||||||
|
AppExecutorUtil.getAppScheduledExecutorService()
|
||||||
|
.scheduleWithFixedDelay(this, EXECUTION_DELAY_MIN, EXECUTION_DELAY_MIN, TimeUnit.MINUTES)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
reportStatistics()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum amount of directories which were reported as gradle user dirs
|
||||||
|
* These directories should be monitored for reported gradle statistics.
|
||||||
|
*/
|
||||||
|
const val MAXIMUM_USER_DIRS = 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delay between sequential checks of gradle statistics
|
||||||
|
*/
|
||||||
|
const val EXECUTION_DELAY_MIN = 60L
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property name used for persisting gradle user dirs
|
||||||
|
*/
|
||||||
|
private const val GRADLE_USER_DIRS_PROPERTY_NAME = "kotlin-gradle-user-dirs"
|
||||||
|
|
||||||
|
private val isRunning = AtomicBoolean(false)
|
||||||
|
|
||||||
|
private fun MetricsContainer.log(event: GradleStatisticsEvents, vararg metrics: Any) {
|
||||||
|
val data = HashMap<String, String>()
|
||||||
|
fun putIfNotNull(key: String, value: String?) {
|
||||||
|
if (value != null) {
|
||||||
|
data[key.toLowerCase()] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (metric in metrics) {
|
||||||
|
when (metric) {
|
||||||
|
is BooleanMetrics -> putIfNotNull(metric.name, this.getMetric(metric)?.toStringRepresentation())
|
||||||
|
is StringMetrics -> putIfNotNull(metric.name, this.getMetric(metric)?.toStringRepresentation())
|
||||||
|
is NumericalMetrics -> putIfNotNull(metric.name, this.getMetric(metric)?.toStringRepresentation())
|
||||||
|
is Pair<*, *> -> putIfNotNull(metric.first.toString(), metric.second.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.size > 0) {
|
||||||
|
KotlinFUSLogger.log(FUSEventGroups.GradlePerformance, event.name, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processMetricsContainer(container: MetricsContainer, previous: MetricsContainer?) {
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.Environment,
|
||||||
|
NumericalMetrics.CPU_NUMBER_OF_CORES,
|
||||||
|
StringMetrics.GRADLE_VERSION,
|
||||||
|
NumericalMetrics.ARTIFACTS_DOWNLOAD_SPEED,
|
||||||
|
StringMetrics.IDES_INSTALLED,
|
||||||
|
BooleanMetrics.EXECUTED_FROM_IDEA
|
||||||
|
)
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.Kapt,
|
||||||
|
BooleanMetrics.ENABLED_KAPT,
|
||||||
|
BooleanMetrics.ENABLED_DAGGER,
|
||||||
|
BooleanMetrics.ENABLED_DATABINDING
|
||||||
|
)
|
||||||
|
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.CompilerPlugins,
|
||||||
|
BooleanMetrics.ENABLED_COMPILER_PLUGIN_ALL_OPEN,
|
||||||
|
BooleanMetrics.ENABLED_COMPILER_PLUGIN_NO_ARG,
|
||||||
|
BooleanMetrics.ENABLED_COMPILER_PLUGIN_JPA_SUPPORT,
|
||||||
|
BooleanMetrics.ENABLED_COMPILER_PLUGIN_SAM_WITH_RECEIVER
|
||||||
|
)
|
||||||
|
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.MPP,
|
||||||
|
StringMetrics.MPP_PLATFORMS,
|
||||||
|
BooleanMetrics.ENABLED_HMPP
|
||||||
|
)
|
||||||
|
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.Libraries,
|
||||||
|
StringMetrics.LIBRARY_SPRING_VERSION,
|
||||||
|
StringMetrics.LIBRARY_VAADIN_VERSION,
|
||||||
|
StringMetrics.LIBRARY_GWT_VERSION,
|
||||||
|
StringMetrics.LIBRARY_HIBERNATE_VERSION
|
||||||
|
)
|
||||||
|
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.GradleConfiguration,
|
||||||
|
NumericalMetrics.GRADLE_DAEMON_HEAP_SIZE,
|
||||||
|
NumericalMetrics.GRADLE_BUILD_NUMBER_IN_CURRENT_DAEMON,
|
||||||
|
NumericalMetrics.CONFIGURATION_API_COUNT,
|
||||||
|
NumericalMetrics.CONFIGURATION_IMPLEMENTATION_COUNT,
|
||||||
|
NumericalMetrics.CONFIGURATION_COMPILE_COUNT,
|
||||||
|
NumericalMetrics.CONFIGURATION_RUNTIME_COUNT,
|
||||||
|
NumericalMetrics.GRADLE_NUMBER_OF_TASKS,
|
||||||
|
NumericalMetrics.GRADLE_NUMBER_OF_UNCONFIGURED_TASKS,
|
||||||
|
NumericalMetrics.GRADLE_NUMBER_OF_INCREMENTAL_TASKS
|
||||||
|
)
|
||||||
|
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.ComponentVersions,
|
||||||
|
StringMetrics.KOTLIN_COMPILER_VERSION,
|
||||||
|
StringMetrics.KOTLIN_STDLIB_VERSION,
|
||||||
|
StringMetrics.KOTLIN_REFLECT_VERSION,
|
||||||
|
StringMetrics.KOTLIN_COROUTINES_VERSION,
|
||||||
|
StringMetrics.KOTLIN_SERIALIZATION_VERSION,
|
||||||
|
StringMetrics.ANDROID_GRADLE_PLUGIN_VERSION
|
||||||
|
)
|
||||||
|
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.KotlinFeatures,
|
||||||
|
StringMetrics.KOTLIN_LANGUAGE_VERSION,
|
||||||
|
StringMetrics.KOTLIN_API_VERSION,
|
||||||
|
BooleanMetrics.BUILD_SRC_EXISTS,
|
||||||
|
NumericalMetrics.BUILD_SRC_COUNT,
|
||||||
|
BooleanMetrics.GRADLE_BUILD_CACHE_USED,
|
||||||
|
BooleanMetrics.GRADLE_WORKER_API_USED,
|
||||||
|
BooleanMetrics.KOTLIN_OFFICIAL_CODESTYLE,
|
||||||
|
BooleanMetrics.KOTLIN_PROGRESSIVE_MODE,
|
||||||
|
BooleanMetrics.KOTLIN_KTS_USED
|
||||||
|
)
|
||||||
|
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.GradlePerformance,
|
||||||
|
NumericalMetrics.GRADLE_BUILD_DURATION,
|
||||||
|
NumericalMetrics.GRADLE_EXECUTION_DURATION,
|
||||||
|
NumericalMetrics.NUMBER_OF_SUBPROJECTS,
|
||||||
|
NumericalMetrics.STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD
|
||||||
|
)
|
||||||
|
|
||||||
|
val finishTime = container.getMetric(NumericalMetrics.BUILD_FINISH_TIME)?.getValue()
|
||||||
|
val prevFinishTime = previous?.getMetric(NumericalMetrics.BUILD_FINISH_TIME)?.getValue()
|
||||||
|
|
||||||
|
val betweenBuilds = if (finishTime != null && prevFinishTime != null) finishTime - prevFinishTime else null
|
||||||
|
container.log(
|
||||||
|
GradleStatisticsEvents.UseScenarios,
|
||||||
|
Pair("time_between_builds", betweenBuilds),
|
||||||
|
BooleanMetrics.DEBUGGER_ENABLED,
|
||||||
|
BooleanMetrics.COMPILATION_STARTED,
|
||||||
|
BooleanMetrics.TESTS_EXECUTED,
|
||||||
|
BooleanMetrics.MAVEN_PUBLISH_EXECUTED,
|
||||||
|
BooleanMetrics.BUILD_FAILED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reportStatistics() {
|
||||||
|
if (isRunning.compareAndSet(false, true)) {
|
||||||
|
try {
|
||||||
|
for (gradleUserHome in gradleUserDirs) {
|
||||||
|
BuildSessionLogger.listProfileFiles(File(gradleUserHome, STATISTICS_FOLDER_NAME))?.forEach { statisticFile ->
|
||||||
|
try {
|
||||||
|
var previousEvent: MetricsContainer? = null
|
||||||
|
MetricsContainer.readFromFile(statisticFile) { metricContainer ->
|
||||||
|
processMetricsContainer(metricContainer, previousEvent)
|
||||||
|
previousEvent = metricContainer
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.getInstance(KotlinFUSLogger::class.java)
|
||||||
|
.info("Failed to process file ${statisticFile.absolutePath}: ${e.message}", e)
|
||||||
|
} finally {
|
||||||
|
if (!statisticFile.delete()) {
|
||||||
|
Logger.getInstance(KotlinFUSLogger::class.java)
|
||||||
|
.warn("[FUS] Failed to delete file ${statisticFile.absolutePath}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isRunning.set(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var gradleUserDirs: Array<String>
|
||||||
|
set(value) = PropertiesComponent.getInstance().setValues(
|
||||||
|
GRADLE_USER_DIRS_PROPERTY_NAME, value
|
||||||
|
)
|
||||||
|
get() = PropertiesComponent.getInstance().getValues(GRADLE_USER_DIRS_PROPERTY_NAME) ?: emptyArray()
|
||||||
|
|
||||||
|
fun populateGradleUserDir(path: String) {
|
||||||
|
val currentState = gradleUserDirs
|
||||||
|
if (path in currentState) return
|
||||||
|
|
||||||
|
val result = ArrayList<String>()
|
||||||
|
result.add(path)
|
||||||
|
result.addAll(currentState)
|
||||||
|
|
||||||
|
gradleUserDirs =
|
||||||
|
result.filter { filePath -> File(filePath).exists() }.take(MAXIMUM_USER_DIRS).toTypedArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@ interface KotlinGradleModel : Serializable {
|
|||||||
val implements: List<String>
|
val implements: List<String>
|
||||||
val kotlinTarget: String?
|
val kotlinTarget: String?
|
||||||
val kotlinTaskProperties: KotlinTaskPropertiesBySourceSet
|
val kotlinTaskProperties: KotlinTaskPropertiesBySourceSet
|
||||||
|
val gradleUserHome: String
|
||||||
}
|
}
|
||||||
|
|
||||||
data class KotlinGradleModelImpl(
|
data class KotlinGradleModelImpl(
|
||||||
@@ -63,7 +64,8 @@ data class KotlinGradleModelImpl(
|
|||||||
override val platformPluginId: String?,
|
override val platformPluginId: String?,
|
||||||
override val implements: List<String>,
|
override val implements: List<String>,
|
||||||
override val kotlinTarget: String? = null,
|
override val kotlinTarget: String? = null,
|
||||||
override val kotlinTaskProperties: KotlinTaskPropertiesBySourceSet
|
override val kotlinTaskProperties: KotlinTaskPropertiesBySourceSet,
|
||||||
|
override val gradleUserHome: String
|
||||||
) : KotlinGradleModel
|
) : KotlinGradleModel
|
||||||
|
|
||||||
abstract class AbstractKotlinGradleModelBuilder : ModelBuilderService {
|
abstract class AbstractKotlinGradleModelBuilder : ModelBuilderService {
|
||||||
@@ -189,7 +191,8 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() {
|
|||||||
platform,
|
platform,
|
||||||
implementedProjects.map { it.pathOrName() },
|
implementedProjects.map { it.pathOrName() },
|
||||||
platform ?: kotlinPluginId,
|
platform ?: kotlinPluginId,
|
||||||
extraProperties
|
extraProperties,
|
||||||
|
project.gradle.gradleUserHomeDir.absolutePath
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -880,6 +880,8 @@
|
|||||||
|
|
||||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.framework.CreateKotlinSdkActivity"/>
|
<postStartupActivity implementation="org.jetbrains.kotlin.idea.framework.CreateKotlinSdkActivity"/>
|
||||||
|
|
||||||
|
<postStartupActivity implementation="org.jetbrains.kotlin.idea.statistics.KotlinGradleFUSLogger"/>
|
||||||
|
|
||||||
<moduleConfigurationEditorProvider implementation="org.jetbrains.kotlin.idea.roots.ui.NonJvmKotlinModuleEditorsProvider"/>
|
<moduleConfigurationEditorProvider implementation="org.jetbrains.kotlin.idea.roots.ui.NonJvmKotlinModuleEditorsProvider"/>
|
||||||
|
|
||||||
<projectStructure.sourceRootEditHandler implementation="org.jetbrains.kotlin.idea.roots.ui.KotlinModuleSourceRootEditHandler$Source"/>
|
<projectStructure.sourceRootEditHandler implementation="org.jetbrains.kotlin.idea.roots.ui.KotlinModuleSourceRootEditHandler$Source"/>
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
|||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
|
||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
|
||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
|
||||||
|
<statistics.counterUsagesCollector groupId="kotlin.gradle.performance" version="1"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.IDESettingsFUSCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.IDESettingsFUSCollector"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
|||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
|
||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
|
||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
|
||||||
|
<statistics.counterUsagesCollector groupId="kotlin.gradle.performance" version="1"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.IDESettingsFUSCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.IDESettingsFUSCollector"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
|||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
|
||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
|
||||||
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
|
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
|
||||||
|
<statistics.counterUsagesCollector groupId="kotlin.gradle.performance" version="1"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.IDESettingsFUSCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.IDESettingsFUSCollector"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
|
||||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
|
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
|
||||||
|
|||||||
+4
@@ -28,12 +28,14 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.checkSourceSetVisibilityRequirements
|
import org.jetbrains.kotlin.gradle.plugin.sources.checkSourceSetVisibilityRequirements
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||||
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.*
|
||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget.*
|
import org.jetbrains.kotlin.konan.target.KonanTarget.*
|
||||||
import org.jetbrains.kotlin.konan.target.presetName
|
import org.jetbrains.kotlin.konan.target.presetName
|
||||||
|
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||||
|
|
||||||
class KotlinMultiplatformPlugin(
|
class KotlinMultiplatformPlugin(
|
||||||
private val kotlinPluginVersion: String,
|
private val kotlinPluginVersion: String,
|
||||||
@@ -261,6 +263,8 @@ class KotlinMultiplatformPlugin(
|
|||||||
target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME)?.let { testCompilation ->
|
target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME)?.let { testCompilation ->
|
||||||
sourceSets.findByName(testCompilation.defaultSourceSetName)?.dependsOn(test)
|
sourceSets.findByName(testCompilation.defaultSourceSetName)?.dependsOn(test)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KotlinBuildStatsService.getInstance()?.report(StringMetrics.MPP_PLATFORMS, target.targetName)
|
||||||
}
|
}
|
||||||
|
|
||||||
UnusedSourceSetsChecker.checkSourceSets(project)
|
UnusedSourceSetsChecker.checkSourceSets(project)
|
||||||
|
|||||||
-2
@@ -12,11 +12,9 @@ import javax.management.ObjectName
|
|||||||
import javax.management.StandardMBean
|
import javax.management.StandardMBean
|
||||||
|
|
||||||
interface IDaemonReuseCounterMXBean {
|
interface IDaemonReuseCounterMXBean {
|
||||||
|
|
||||||
fun getOrdinal(): Long
|
fun getOrdinal(): Long
|
||||||
|
|
||||||
fun incrementAndGetOrdinal(): Long
|
fun incrementAndGetOrdinal(): Long
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+59
-38
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.gradle.plugin.statistics
|
|||||||
|
|
||||||
import org.gradle.BuildAdapter
|
import org.gradle.BuildAdapter
|
||||||
import org.gradle.BuildResult
|
import org.gradle.BuildResult
|
||||||
|
import org.gradle.api.artifacts.DependencySet
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
import org.gradle.initialization.BuildCompletionListener
|
|
||||||
import org.gradle.initialization.BuildRequestMetaData
|
import org.gradle.initialization.BuildRequestMetaData
|
||||||
import org.gradle.invocation.DefaultGradle
|
import org.gradle.invocation.DefaultGradle
|
||||||
import org.jetbrains.kotlin.statistics.BuildSessionLogger
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger
|
||||||
@@ -20,6 +20,7 @@ import java.lang.management.ManagementFactory
|
|||||||
import javax.management.MBeanServer
|
import javax.management.MBeanServer
|
||||||
import javax.management.ObjectName
|
import javax.management.ObjectName
|
||||||
import javax.management.StandardMBean
|
import javax.management.StandardMBean
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for populating statistics collection method via JXM interface
|
* Interface for populating statistics collection method via JXM interface
|
||||||
@@ -27,21 +28,16 @@ import javax.management.StandardMBean
|
|||||||
* of Kotlin Plugin and other classloaders
|
* of Kotlin Plugin and other classloaders
|
||||||
*/
|
*/
|
||||||
interface KotlinBuildStatsMXBean {
|
interface KotlinBuildStatsMXBean {
|
||||||
|
|
||||||
fun reportBoolean(name: String, value: Boolean, subprojectName: String?)
|
fun reportBoolean(name: String, value: Boolean, subprojectName: String?)
|
||||||
|
|
||||||
fun reportNumber(name: String, value: Long, subprojectName: String?)
|
fun reportNumber(name: String, value: Long, subprojectName: String?)
|
||||||
|
|
||||||
fun reportString(name: String, value: String, subprojectName: String?)
|
fun reportString(name: String, value: String, subprojectName: String?)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal abstract class KotlinBuildStatsService internal constructor() : BuildAdapter(), IStatisticsValuesConsumer,
|
internal abstract class KotlinBuildStatsService internal constructor() : BuildAdapter(), IStatisticsValuesConsumer {
|
||||||
BuildCompletionListener {
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
// Do not rename this bean otherwise compatibility with the older Kotlin Gradle Plugins would be lost
|
// Do not rename this bean otherwise compatibility with the older Kotlin Gradle Plugins would be lost
|
||||||
const val JMX_BEAN_NAME = "org.jetbrains.kotlin.gradle.plugin.statistics:type=StatsService"
|
const val JMX_BEAN_NAME = "org.jetbrains.kotlin.gradle.plugin.statistics:type=StatsService"
|
||||||
|
|
||||||
@@ -54,7 +50,6 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd
|
|||||||
// "emergency file" collecting statistics is disabled it the file exists
|
// "emergency file" collecting statistics is disabled it the file exists
|
||||||
const val DISABLE_STATISTICS_FILE_NAME = "${STATISTICS_FOLDER_NAME}/.disable"
|
const val DISABLE_STATISTICS_FILE_NAME = "${STATISTICS_FOLDER_NAME}/.disable"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for getting IStatisticsValuesConsumer for reporting some statistics
|
* Method for getting IStatisticsValuesConsumer for reporting some statistics
|
||||||
* Could be invoked during any build phase after applying first Kotlin plugin and
|
* Could be invoked during any build phase after applying first Kotlin plugin and
|
||||||
@@ -145,16 +140,11 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class JMXKotlinBuildStatsService(private val mbs: MBeanServer, private val beanName: ObjectName) :
|
internal class JMXKotlinBuildStatsService(private val mbs: MBeanServer, private val beanName: ObjectName) :
|
||||||
KotlinBuildStatsService() {
|
KotlinBuildStatsService() {
|
||||||
|
|
||||||
override fun buildFinished(result: BuildResult) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun callJmx(method: String, type: String, metricName: String, value: Any, subprojectName: String?) {
|
private fun callJmx(method: String, type: String, metricName: String, value: Any, subprojectName: String?) {
|
||||||
mbs.invoke(
|
mbs.invoke(
|
||||||
beanName,
|
beanName,
|
||||||
@@ -182,50 +172,89 @@ internal class JMXKotlinBuildStatsService(private val mbs: MBeanServer, private
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun completed() {
|
override fun buildFinished(result: BuildResult) {
|
||||||
instance = null
|
instance = null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultKotlinBuildStatsService internal constructor(
|
internal class DefaultKotlinBuildStatsService internal constructor(
|
||||||
gradle: Gradle,
|
gradle: Gradle,
|
||||||
val beanName: ObjectName
|
val beanName: ObjectName
|
||||||
) : KotlinBuildStatsService(), KotlinBuildStatsMXBean {
|
) : KotlinBuildStatsService(), KotlinBuildStatsMXBean {
|
||||||
|
|
||||||
private val sessionLogger = BuildSessionLogger(gradle.gradleUserHomeDir)
|
private val sessionLogger = BuildSessionLogger(gradle.gradleUserHomeDir)
|
||||||
|
|
||||||
private fun gradleBuildStartTime(gradle: Gradle): Long? {
|
private fun gradleBuildStartTime(gradle: Gradle): Long? {
|
||||||
return (gradle as? DefaultGradle)?.services?.get(BuildRequestMetaData::class.java)?.startTime
|
return (gradle as? DefaultGradle)?.services?.get(BuildRequestMetaData::class.java)?.startTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reportLibrariesVersions(dependencies: DependencySet?) {
|
||||||
|
dependencies?.forEach { dependency ->
|
||||||
|
when {
|
||||||
|
dependency.group?.startsWith("org.springframework") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_SPRING_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group?.startsWith("com.vaadin") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_VAADIN_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group?.startsWith("com.google.gwt") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_GWT_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group?.startsWith("org.hibernate") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_HIBERNATE_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun reportGlobalMetrics(gradle: Gradle) {
|
private fun reportGlobalMetrics(gradle: Gradle) {
|
||||||
System.getProperty("os.name")?.also {
|
System.getProperty("os.name")?.also {
|
||||||
sessionLogger.report(StringMetrics.OS_TYPE, gradle.gradleVersion)
|
sessionLogger.report(StringMetrics.OS_TYPE, System.getProperty("os.name"))
|
||||||
}
|
}
|
||||||
sessionLogger.report(NumericalMetrics.CPU_NUMBER_OF_CORES, Runtime.getRuntime().availableProcessors().toLong())
|
sessionLogger.report(NumericalMetrics.CPU_NUMBER_OF_CORES, Runtime.getRuntime().availableProcessors().toLong())
|
||||||
sessionLogger.report(StringMetrics.GRADLE_VERSION, gradle.gradleVersion)
|
sessionLogger.report(StringMetrics.GRADLE_VERSION, gradle.gradleVersion)
|
||||||
sessionLogger.report(BooleanMetrics.EXECUTED_FROM_IDEA, System.getProperty("idea.active") != null)
|
sessionLogger.report(BooleanMetrics.EXECUTED_FROM_IDEA, System.getProperty("idea.active") != null)
|
||||||
|
|
||||||
|
val statisticOverhead = measureTimeMillis {
|
||||||
|
gradle.allprojects { project ->
|
||||||
|
for (configuration in project.configurations) {
|
||||||
|
val configurationName = configuration.name
|
||||||
|
val dependencies = configuration.dependencies
|
||||||
|
|
||||||
gradle.allprojects { project ->
|
when (configurationName) {
|
||||||
for (configuration in project.configurations) {
|
"kapt" -> {
|
||||||
val configurationName = configuration.name
|
sessionLogger.report(BooleanMetrics.ENABLED_KAPT, true)
|
||||||
val dependencies = configuration.dependencies
|
dependencies?.forEach { dependency ->
|
||||||
|
when (dependency.group) {
|
||||||
when (configurationName) {
|
"com.google.dagger" -> sessionLogger.report(BooleanMetrics.ENABLED_DAGGER, true)
|
||||||
"kapt" -> {
|
"com.android.databinding" -> sessionLogger.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
||||||
sessionLogger.report(BooleanMetrics.ENABLED_KAPT, true)
|
}
|
||||||
dependencies.forEach { dependency ->
|
|
||||||
when (dependency.group) {
|
|
||||||
"com.google.dagger" -> sessionLogger.report(BooleanMetrics.ENABLED_DAGGER, true)
|
|
||||||
"com.android.databinding" -> sessionLogger.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"api" -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_API_COUNT, 1)
|
||||||
|
reportLibrariesVersions(dependencies)
|
||||||
|
}
|
||||||
|
"implementation" -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_IMPLEMENTATION_COUNT, 1)
|
||||||
|
reportLibrariesVersions(dependencies)
|
||||||
|
}
|
||||||
|
"compile" -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_COMPILE_COUNT, 1)
|
||||||
|
reportLibrariesVersions(dependencies)
|
||||||
|
}
|
||||||
|
"runtime" -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_RUNTIME_COUNT, 1)
|
||||||
|
reportLibrariesVersions(dependencies)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sessionLogger.report(NumericalMetrics.STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD, statisticOverhead)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun projectsEvaluated(gradle: Gradle) {
|
override fun projectsEvaluated(gradle: Gradle) {
|
||||||
@@ -243,16 +272,8 @@ internal class DefaultKotlinBuildStatsService internal constructor(
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
override fun buildFinished(result: BuildResult) {
|
override fun buildFinished(result: BuildResult) {
|
||||||
runSafe("${DefaultKotlinBuildStatsService::class.java}.buildFinished") {
|
runSafe("${DefaultKotlinBuildStatsService::class.java}.buildFinished") {
|
||||||
sessionLogger.finishBuildSession(result.action, result.failure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
override fun completed() {
|
|
||||||
runSafe("${DefaultKotlinBuildStatsService::class.java}.completed") {
|
|
||||||
try {
|
try {
|
||||||
sessionLogger.unlockJournalFile()
|
sessionLogger.finishBuildSession(result.action, result.failure)
|
||||||
} finally {
|
} finally {
|
||||||
val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer()
|
val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer()
|
||||||
if (mbs.isRegistered(beanName)) {
|
if (mbs.isRegistered(beanName)) {
|
||||||
|
|||||||
-2
@@ -25,7 +25,5 @@ class BuildStatServiceTest {
|
|||||||
jmxService.report(StringMetrics.KOTLIN_COMPILER_VERSION, "1.2.3")
|
jmxService.report(StringMetrics.KOTLIN_COMPILER_VERSION, "1.2.3")
|
||||||
jmxService.report(NumericalMetrics.NUMBER_OF_SUBPROJECTS, 10)
|
jmxService.report(NumericalMetrics.NUMBER_OF_SUBPROJECTS, 10)
|
||||||
jmxService.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
jmxService.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
||||||
|
|
||||||
jmxService.completed()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(kotlinStdlib())
|
compileOnly(kotlinStdlib())
|
||||||
|
|
||||||
testCompile(project(":kotlin-test::kotlin-test-junit"))
|
testCompile(project(":kotlin-test:kotlin-test-junit"))
|
||||||
testCompile("junit:junit:4.12")
|
testCompile("junit:junit:4.12")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,5 +19,3 @@ sourceSets {
|
|||||||
projectTest {
|
projectTest {
|
||||||
workingDir = rootDir
|
workingDir = rootDir
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeJar(rewriteDefaultJarDepsToShadedCompiler())
|
|
||||||
|
|||||||
+3
-2
@@ -21,8 +21,9 @@ internal val salt: String by lazy {
|
|||||||
fun anonymizeComponentVersion(version: String): String {
|
fun anonymizeComponentVersion(version: String): String {
|
||||||
return version.replace('-', '.')
|
return version.replace('-', '.')
|
||||||
.split(".")
|
.split(".")
|
||||||
.filterIndexed { i, _ -> i < 3 }
|
.plus(listOf("0", "0")) // pad with zeros
|
||||||
.map { s -> s.toIntOrNull() ?: "?" }
|
.take(3)
|
||||||
|
.map { s -> s.toIntOrNull() ?: "0" }
|
||||||
.joinToString(".")
|
.joinToString(".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -6,7 +6,5 @@
|
|||||||
package org.jetbrains.kotlin.statistics
|
package org.jetbrains.kotlin.statistics
|
||||||
|
|
||||||
class BuildSession(val buildStartedTime: Long?) {
|
class BuildSession(val buildStartedTime: Long?) {
|
||||||
|
|
||||||
val projectEvaluatedTime = System.currentTimeMillis()
|
val projectEvaluatedTime = System.currentTimeMillis()
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
+48
-23
@@ -16,17 +16,23 @@ import java.time.LocalDateTime
|
|||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
class BuildSessionLogger(
|
class BuildSessionLogger(
|
||||||
private val rootPath: File,
|
rootPath: File,
|
||||||
private val maxProfileFiles: Int = DEFAULT_MAX_PROFILE_FILES,
|
private val maxProfileFiles: Int = DEFAULT_MAX_PROFILE_FILES,
|
||||||
private val maxFileSize: Long = DEFAULT_MAX_PROFILE_FILE_SIZE
|
private val maxFileSize: Long = DEFAULT_MAX_PROFILE_FILE_SIZE,
|
||||||
|
private val maxFileAge: Long = DEFAULT_MAX_FILE_AGE
|
||||||
) : IStatisticsValuesConsumer {
|
) : IStatisticsValuesConsumer {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val STATISTICS_FOLDER_NAME = "kotlin-profile"
|
const val STATISTICS_FOLDER_NAME = "kotlin-profile"
|
||||||
const val STATISTICS_FILE_NAME_PATTERN = "\\d{4}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{3}.profile"
|
internal const val STATISTICS_FILE_NAME_PATTERN = "\\d{4}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{3}.profile"
|
||||||
|
|
||||||
private const val DEFAULT_MAX_PROFILE_FILES = 1_000
|
private const val DEFAULT_MAX_PROFILE_FILES = 1_000
|
||||||
private const val DEFAULT_MAX_PROFILE_FILE_SIZE = 100_000L
|
private const val DEFAULT_MAX_PROFILE_FILE_SIZE = 100_000L
|
||||||
|
private const val DEFAULT_MAX_FILE_AGE = 30 * 24 * 3600 * 1000L //30 days
|
||||||
|
|
||||||
|
fun listProfileFiles(statisticsFolder: File): List<File>? {
|
||||||
|
return statisticsFolder.listFiles()?.filterTo(ArrayList()) { it.name.matches(STATISTICS_FILE_NAME_PATTERN.toRegex()) }?.sorted()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val profileFileNameFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HH-mm-ss-SSS'.profile'")
|
private val profileFileNameFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HH-mm-ss-SSS'.profile'")
|
||||||
@@ -53,29 +59,44 @@ class BuildSessionLogger(
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun closeTrackingFile() {
|
private fun closeTrackingFile() {
|
||||||
metricsContainer.flush(trackingFile)
|
trackingFile?.let {
|
||||||
trackingFile?.close()
|
metricsContainer.flush(it)
|
||||||
trackingFile = null
|
it.close()
|
||||||
|
trackingFile = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new tracking file
|
||||||
|
* The following contracts are implemented:
|
||||||
|
* - number of tracking files should not be more than maxProfileFiles (the earlier file created the earlier deleted)
|
||||||
|
* - files with age (current time - last modified) more than maxFileAge should be deleted (if we trust lastModified returned by FS)
|
||||||
|
* - files are ordered on the basis of name (creation timestamp)
|
||||||
|
* - if the last file has size less then maxFileSize, the next record will be append to it (new file created otherwise)
|
||||||
|
* -
|
||||||
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun initTrackingFile() {
|
private fun initTrackingFile() {
|
||||||
closeTrackingFile()
|
closeTrackingFile()
|
||||||
|
|
||||||
// Get list of existing files. Try to create folder if possible, return from function if failed to create folder
|
// Get list of existing files. Try to create folder if possible, return from function if failed to create folder
|
||||||
val fileCandidates =
|
val fileCandidates = listProfileFiles(statisticsFolder) ?: if (statisticsFolder.mkdirs()) emptyList<File>() else return
|
||||||
statisticsFolder.listFiles()?.filter { it.name.matches(STATISTICS_FILE_NAME_PATTERN.toRegex()) }?.toMutableList()
|
|
||||||
?: if (statisticsFolder.mkdirs()) emptyList<File>() else return
|
|
||||||
|
|
||||||
for (i in 0 until fileCandidates.size - maxProfileFiles) {
|
for ((index, file) in fileCandidates.withIndex()) {
|
||||||
val file2delete = fileCandidates[i]
|
val toDelete = if (index < fileCandidates.size - maxProfileFiles)
|
||||||
if (file2delete.isFile) {
|
true
|
||||||
file2delete.delete()
|
else {
|
||||||
|
val lastModified = file.lastModified()
|
||||||
|
(lastModified > 0) && (System.currentTimeMillis() - maxFileAge > lastModified)
|
||||||
|
}
|
||||||
|
if (toDelete) {
|
||||||
|
file.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// emergency check. What if a lot of files are locked due to some reason
|
// emergency check. What if a lot of files are locked due to some reason
|
||||||
if (statisticsFolder.listFiles()?.size ?: 0 > maxProfileFiles * 2) {
|
if (listProfileFiles(statisticsFolder)?.size ?: 0 > maxProfileFiles * 2) {
|
||||||
|
trackingFile = NullRecordLogger()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,20 +120,24 @@ class BuildSessionLogger(
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun finishBuildSession(action: String?, failure: Throwable?) {
|
fun finishBuildSession(action: String?, failure: Throwable?) {
|
||||||
// nanotime could not be used as build start time in nanotime is unknown. As result, the measured duration
|
try {
|
||||||
// could be affected by system clock correction
|
// nanotime could not be used as build start time in nanotime is unknown. As result, the measured duration
|
||||||
val finishTime = System.currentTimeMillis()
|
// could be affected by system clock correction
|
||||||
buildSession?.also {
|
val finishTime = System.currentTimeMillis()
|
||||||
if (it.buildStartedTime != null) {
|
buildSession?.also {
|
||||||
report(NumericalMetrics.GRADLE_BUILD_DURATION, finishTime - it.buildStartedTime)
|
if (it.buildStartedTime != null) {
|
||||||
|
report(NumericalMetrics.GRADLE_BUILD_DURATION, finishTime - it.buildStartedTime)
|
||||||
|
}
|
||||||
|
report(NumericalMetrics.GRADLE_EXECUTION_DURATION, finishTime - it.projectEvaluatedTime)
|
||||||
}
|
}
|
||||||
report(NumericalMetrics.GRADLE_EXECUTION_DURATION, finishTime - it.projectEvaluatedTime)
|
buildSession = null
|
||||||
|
} finally {
|
||||||
|
unlockJournalFile()
|
||||||
}
|
}
|
||||||
buildSession = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun unlockJournalFile() {
|
private fun unlockJournalFile() {
|
||||||
closeTrackingFile()
|
closeTrackingFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-1
@@ -15,7 +15,6 @@ import java.nio.file.Paths
|
|||||||
import java.nio.file.StandardOpenOption
|
import java.nio.file.StandardOpenOption
|
||||||
|
|
||||||
class FileRecordLogger(file: File) : IRecordLogger {
|
class FileRecordLogger(file: File) : IRecordLogger {
|
||||||
|
|
||||||
private val channel: FileChannel =
|
private val channel: FileChannel =
|
||||||
FileChannel.open(Paths.get(file.toURI()), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
|
FileChannel.open(Paths.get(file.toURI()), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
|
||||||
?: throw IOException("Could not open file $file")
|
?: throw IOException("Could not open file $file")
|
||||||
|
|||||||
+1
-3
@@ -8,7 +8,5 @@ package org.jetbrains.kotlin.statistics.fileloggers
|
|||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
|
|
||||||
interface IRecordLogger : Closeable {
|
interface IRecordLogger : Closeable {
|
||||||
|
|
||||||
fun append(s: String)
|
fun append(s: String)
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
+5
-6
@@ -15,11 +15,11 @@ import java.nio.file.StandardOpenOption
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class MetricsContainer : IStatisticsValuesConsumer {
|
class MetricsContainer : IStatisticsValuesConsumer {
|
||||||
|
|
||||||
data class MetricDescriptor(val name: String, val projectHash: String?) : Comparable<MetricDescriptor> {
|
data class MetricDescriptor(val name: String, val projectHash: String?) : Comparable<MetricDescriptor> {
|
||||||
override fun compareTo(other: MetricDescriptor): Int {
|
override fun compareTo(other: MetricDescriptor): Int {
|
||||||
|
val compareNames = name.compareTo(other.name)
|
||||||
return when {
|
return when {
|
||||||
name.compareTo(other.name) != 0 -> name.compareTo(other.name)
|
compareNames != 0 -> compareNames
|
||||||
projectHash == other.projectHash -> 0
|
projectHash == other.projectHash -> 0
|
||||||
else -> (projectHash ?: "").compareTo(other.projectHash ?: "")
|
else -> (projectHash ?: "").compareTo(other.projectHash ?: "")
|
||||||
}
|
}
|
||||||
@@ -33,16 +33,15 @@ class MetricsContainer : IStatisticsValuesConsumer {
|
|||||||
private val stringMetrics = TreeMap<MetricDescriptor, IMetricContainer<String>>()
|
private val stringMetrics = TreeMap<MetricDescriptor, IMetricContainer<String>>()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val BUILD_SESSION_SEPARATOR = "BUILD FINISHED"
|
private const val BUILD_SESSION_SEPARATOR = "BUILD FINISHED"
|
||||||
|
|
||||||
val ENCODING = Charsets.UTF_8
|
val ENCODING = Charsets.UTF_8
|
||||||
|
|
||||||
private val stringMetricsMap = StringMetrics.values().map { m -> m.name to m }.toMap()
|
private val stringMetricsMap = StringMetrics.values().associateBy(StringMetrics::name)
|
||||||
|
|
||||||
private val booleanMetricsMap = BooleanMetrics.values().map { m -> m.name to m }.toMap()
|
private val booleanMetricsMap = BooleanMetrics.values().associateBy(BooleanMetrics::name)
|
||||||
|
|
||||||
private val numericalMetricsMap = NumericalMetrics.values().map { m -> m.name to m }.toMap()
|
private val numericalMetricsMap = NumericalMetrics.values().associateBy(NumericalMetrics::name)
|
||||||
|
|
||||||
fun readFromFile(file: File, consumer: (MetricsContainer) -> Unit) {
|
fun readFromFile(file: File, consumer: (MetricsContainer) -> Unit) {
|
||||||
val channel = FileChannel.open(Paths.get(file.toURI()), StandardOpenOption.WRITE, StandardOpenOption.READ)
|
val channel = FileChannel.open(Paths.get(file.toURI()), StandardOpenOption.WRITE, StandardOpenOption.READ)
|
||||||
|
|||||||
+13
-6
@@ -13,7 +13,6 @@ interface IMetricContainer<T> {
|
|||||||
fun toStringRepresentation(): String
|
fun toStringRepresentation(): String
|
||||||
|
|
||||||
fun getValue(): T?
|
fun getValue(): T?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMetricContainerFactory<T> {
|
interface IMetricContainerFactory<T> {
|
||||||
@@ -23,7 +22,6 @@ interface IMetricContainerFactory<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class OverrideMetricContainer<T>() : IMetricContainer<T> {
|
open class OverrideMetricContainer<T>() : IMetricContainer<T> {
|
||||||
|
|
||||||
internal var myValue: T? = null
|
internal var myValue: T? = null
|
||||||
|
|
||||||
override fun addValue(t: T) {
|
override fun addValue(t: T) {
|
||||||
@@ -41,8 +39,19 @@ open class OverrideMetricContainer<T>() : IMetricContainer<T> {
|
|||||||
override fun getValue() = myValue
|
override fun getValue() = myValue
|
||||||
}
|
}
|
||||||
|
|
||||||
class SumMetricContainer() : OverrideMetricContainer<Long>() {
|
class OverrideVersionMetricContainer() : OverrideMetricContainer<String>() {
|
||||||
|
constructor(v: String) : this() {
|
||||||
|
myValue = v
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addValue(t: String) {
|
||||||
|
if (myValue == null || myValue == "0.0.0") {
|
||||||
|
myValue = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SumMetricContainer() : OverrideMetricContainer<Long>() {
|
||||||
constructor(v: Long) : this() {
|
constructor(v: Long) : this() {
|
||||||
myValue = v
|
myValue = v
|
||||||
}
|
}
|
||||||
@@ -85,7 +94,6 @@ class OrMetricContainer() : OverrideMetricContainer<Boolean>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ConcatMetricContainer() : IMetricContainer<String> {
|
class ConcatMetricContainer() : IMetricContainer<String> {
|
||||||
|
|
||||||
private val myValues = TreeSet<String>()
|
private val myValues = TreeSet<String>()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -101,9 +109,8 @@ class ConcatMetricContainer() : IMetricContainer<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toStringRepresentation(): String {
|
override fun toStringRepresentation(): String {
|
||||||
return myValues.joinToString(SEPARATOR)
|
return myValues.sorted().joinToString(SEPARATOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getValue() = toStringRepresentation()
|
override fun getValue() = toStringRepresentation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -16,6 +16,11 @@ enum class StringOverridePolicy: IMetricContainerFactory<String> {
|
|||||||
|
|
||||||
override fun fromStringRepresentation(state: String): IMetricContainer<String>? = OverrideMetricContainer(state)
|
override fun fromStringRepresentation(state: String): IMetricContainer<String>? = OverrideMetricContainer(state)
|
||||||
},
|
},
|
||||||
|
OVERRIDE_VERSION_IF_NOT_SET {
|
||||||
|
override fun newMetricContainer(): IMetricContainer<String> = OverrideVersionMetricContainer()
|
||||||
|
|
||||||
|
override fun fromStringRepresentation(state: String): IMetricContainer<String>? = OverrideVersionMetricContainer(state)
|
||||||
|
},
|
||||||
CONCAT {
|
CONCAT {
|
||||||
override fun newMetricContainer(): IMetricContainer<String> = ConcatMetricContainer()
|
override fun newMetricContainer(): IMetricContainer<String> = ConcatMetricContainer()
|
||||||
|
|
||||||
|
|||||||
+2
@@ -47,6 +47,8 @@ enum class NumericalMetrics(val type: NumberOverridePolicy, val anonymization: N
|
|||||||
|
|
||||||
NUMBER_OF_SUBPROJECTS(OVERRIDE, RANDOM_10_PERCENT),
|
NUMBER_OF_SUBPROJECTS(OVERRIDE, RANDOM_10_PERCENT),
|
||||||
|
|
||||||
|
STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD(SUM, RANDOM_10_PERCENT),
|
||||||
|
|
||||||
// User scenarios
|
// User scenarios
|
||||||
|
|
||||||
// this value is not reported, only time intervals from the previous build are used
|
// this value is not reported, only time intervals from the previous build are used
|
||||||
|
|||||||
+1
-3
@@ -18,11 +18,9 @@ interface AdditiveStatisticsValue<T> : ReportStatisticsValue<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IStatisticsValuesConsumer {
|
interface IStatisticsValuesConsumer {
|
||||||
|
|
||||||
fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String? = null)
|
fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String? = null)
|
||||||
|
|
||||||
fun report(metric: NumericalMetrics, value: Long, subprojectName: String? = null)
|
fun report(metric: NumericalMetrics, value: Long, subprojectName: String? = null)
|
||||||
|
|
||||||
fun report(metric: StringMetrics, value: String, subprojectName: String? = null)
|
fun report(metric: StringMetrics, value: String, subprojectName: String? = null)
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|||||||
+4
-9
@@ -23,10 +23,10 @@ enum class StringMetrics(val type: StringOverridePolicy, val anonymization: Stri
|
|||||||
MPP_PLATFORMS(CONCAT, SAFE),
|
MPP_PLATFORMS(CONCAT, SAFE),
|
||||||
|
|
||||||
// Component versions
|
// Component versions
|
||||||
LIBRARY_SPRING_VERSION(OVERRIDE, COMPONENT_VERSION),
|
LIBRARY_SPRING_VERSION(OVERRIDE_VERSION_IF_NOT_SET, COMPONENT_VERSION),
|
||||||
LIBRARY_VAADIN_VERSION(OVERRIDE, COMPONENT_VERSION),
|
LIBRARY_VAADIN_VERSION(OVERRIDE_VERSION_IF_NOT_SET, COMPONENT_VERSION),
|
||||||
LIBRARY_GWT_VERSION(OVERRIDE, COMPONENT_VERSION),
|
LIBRARY_GWT_VERSION(OVERRIDE_VERSION_IF_NOT_SET, COMPONENT_VERSION),
|
||||||
LIBRARY_HYBERNATE_VERSION(OVERRIDE, COMPONENT_VERSION),
|
LIBRARY_HIBERNATE_VERSION(OVERRIDE_VERSION_IF_NOT_SET, COMPONENT_VERSION),
|
||||||
|
|
||||||
KOTLIN_COMPILER_VERSION(OVERRIDE, COMPONENT_VERSION),
|
KOTLIN_COMPILER_VERSION(OVERRIDE, COMPONENT_VERSION),
|
||||||
KOTLIN_STDLIB_VERSION(OVERRIDE, COMPONENT_VERSION),
|
KOTLIN_STDLIB_VERSION(OVERRIDE, COMPONENT_VERSION),
|
||||||
@@ -39,9 +39,4 @@ enum class StringMetrics(val type: StringOverridePolicy, val anonymization: Stri
|
|||||||
// Features
|
// Features
|
||||||
KOTLIN_LANGUAGE_VERSION(OVERRIDE, COMPONENT_VERSION),
|
KOTLIN_LANGUAGE_VERSION(OVERRIDE, COMPONENT_VERSION),
|
||||||
KOTLIN_API_VERSION(OVERRIDE, COMPONENT_VERSION),
|
KOTLIN_API_VERSION(OVERRIDE, COMPONENT_VERSION),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+37
-15
@@ -5,25 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.statistics
|
package org.jetbrains.kotlin.statistics
|
||||||
|
|
||||||
import com.sun.javafx.font.Metrics
|
|
||||||
import org.jetbrains.kotlin.statistics.BuildSessionLogger.Companion.STATISTICS_FILE_NAME_PATTERN
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger.Companion.STATISTICS_FILE_NAME_PATTERN
|
||||||
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger.Companion.listProfileFiles
|
||||||
import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer
|
import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer
|
||||||
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
||||||
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
||||||
import org.jetbrains.kotlin.statistics.metrics.OverrideMetricContainer
|
|
||||||
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
import kotlin.test.Test
|
import kotlin.test.*
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
import kotlin.test.fail
|
|
||||||
|
|
||||||
class BuildSessionLoggerTest {
|
class BuildSessionLoggerTest {
|
||||||
|
|
||||||
lateinit var rootFolder: File
|
private lateinit var rootFolder: File
|
||||||
|
|
||||||
private fun statFilesCount() = rootFolder.listFiles().single().listFiles().size
|
private fun statFilesCount() = rootFolder.listFiles().single().listFiles().size
|
||||||
|
|
||||||
@@ -74,7 +70,6 @@ class BuildSessionLoggerTest {
|
|||||||
val logger = BuildSessionLogger(rootFolder, 100, maxFileSize.toLong())
|
val logger = BuildSessionLogger(rootFolder, 100, maxFileSize.toLong())
|
||||||
logger.startBuildSession(0, null)
|
logger.startBuildSession(0, null)
|
||||||
logger.finishBuildSession("", null)
|
logger.finishBuildSession("", null)
|
||||||
logger.unlockJournalFile()
|
|
||||||
|
|
||||||
assertEquals(1, statFilesCount())
|
assertEquals(1, statFilesCount())
|
||||||
|
|
||||||
@@ -82,7 +77,6 @@ class BuildSessionLoggerTest {
|
|||||||
|
|
||||||
logger.startBuildSession(0, 0)
|
logger.startBuildSession(0, 0)
|
||||||
logger.finishBuildSession("", null)
|
logger.finishBuildSession("", null)
|
||||||
logger.unlockJournalFile()
|
|
||||||
//new file should not be created
|
//new file should not be created
|
||||||
assertEquals(1, statFilesCount())
|
assertEquals(1, statFilesCount())
|
||||||
|
|
||||||
@@ -90,7 +84,6 @@ class BuildSessionLoggerTest {
|
|||||||
|
|
||||||
logger.startBuildSession(0, 0)
|
logger.startBuildSession(0, 0)
|
||||||
logger.finishBuildSession("", null)
|
logger.finishBuildSession("", null)
|
||||||
logger.unlockJournalFile()
|
|
||||||
|
|
||||||
// a new file should be created as maximal file size
|
// a new file should be created as maximal file size
|
||||||
assertEquals(2, statFilesCount())
|
assertEquals(2, statFilesCount())
|
||||||
@@ -102,7 +95,6 @@ class BuildSessionLoggerTest {
|
|||||||
val logger = BuildSessionLogger(rootFolder, maxFiles)
|
val logger = BuildSessionLogger(rootFolder, maxFiles)
|
||||||
logger.startBuildSession(0, null)
|
logger.startBuildSession(0, null)
|
||||||
logger.finishBuildSession("", null)
|
logger.finishBuildSession("", null)
|
||||||
logger.unlockJournalFile()
|
|
||||||
assertEquals(1, statFilesCount())
|
assertEquals(1, statFilesCount())
|
||||||
|
|
||||||
val statsFolder = rootFolder.listFiles().single()
|
val statsFolder = rootFolder.listFiles().single()
|
||||||
@@ -116,7 +108,6 @@ class BuildSessionLoggerTest {
|
|||||||
|
|
||||||
logger.startBuildSession(0, 0)
|
logger.startBuildSession(0, 0)
|
||||||
logger.finishBuildSession("", null)
|
logger.finishBuildSession("", null)
|
||||||
logger.unlockJournalFile()
|
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
statsFolder.listFiles().filter { it.name == singleStatFile.name }.count() == 1,
|
statsFolder.listFiles().filter { it.name == singleStatFile.name }.count() == 1,
|
||||||
@@ -135,6 +126,10 @@ class BuildSessionLoggerTest {
|
|||||||
statsFolder.listFiles().filter { it.name.matches(STATISTICS_FILE_NAME_PATTERN.toRegex()) }.count(),
|
statsFolder.listFiles().filter { it.name.matches(STATISTICS_FILE_NAME_PATTERN.toRegex()) }.count(),
|
||||||
"Some files which should not be affected, were removed"
|
"Some files which should not be affected, were removed"
|
||||||
)
|
)
|
||||||
|
assertEquals(
|
||||||
|
statsFolder.listFiles().filter { it.name.matches(STATISTICS_FILE_NAME_PATTERN.toRegex()) }.sorted(),
|
||||||
|
listProfileFiles(statsFolder)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -142,10 +137,9 @@ class BuildSessionLoggerTest {
|
|||||||
val logger = BuildSessionLogger(rootFolder)
|
val logger = BuildSessionLogger(rootFolder)
|
||||||
logger.report(StringMetrics.KOTLIN_COMPILER_VERSION, "1.2.3.4-snapshot")
|
logger.report(StringMetrics.KOTLIN_COMPILER_VERSION, "1.2.3.4-snapshot")
|
||||||
|
|
||||||
val startTime = System.currentTimeMillis() - 1000
|
val startTime = System.currentTimeMillis() - 1001
|
||||||
logger.startBuildSession(1, startTime)
|
logger.startBuildSession(1, startTime)
|
||||||
logger.finishBuildSession("Build", null)
|
logger.finishBuildSession("Build", null)
|
||||||
logger.unlockJournalFile()
|
|
||||||
assertEquals(1, statFilesCount())
|
assertEquals(1, statFilesCount())
|
||||||
|
|
||||||
val statFile = rootFolder.listFiles().single().listFiles().single()
|
val statFile = rootFolder.listFiles().single().listFiles().single()
|
||||||
@@ -165,7 +159,6 @@ class BuildSessionLoggerTest {
|
|||||||
|
|
||||||
|
|
||||||
logger.finishBuildSession("", null)
|
logger.finishBuildSession("", null)
|
||||||
logger.unlockJournalFile()
|
|
||||||
|
|
||||||
val metrics = ArrayList<MetricsContainer>()
|
val metrics = ArrayList<MetricsContainer>()
|
||||||
MetricsContainer.readFromFile(statFile) {
|
MetricsContainer.readFromFile(statFile) {
|
||||||
@@ -186,4 +179,33 @@ class BuildSessionLoggerTest {
|
|||||||
val buildDuration = metrics[0].getMetric(NumericalMetrics.GRADLE_BUILD_DURATION)?.getValue() ?: 0L
|
val buildDuration = metrics[0].getMetric(NumericalMetrics.GRADLE_BUILD_DURATION)?.getValue() ?: 0L
|
||||||
assertTrue(buildDuration > 1000, "It was expected that build duration is > 1000, but got $buildDuration")
|
assertTrue(buildDuration > 1000, "It was expected that build duration is > 1000, but got $buildDuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSaveAndReadAllMetrics() {
|
||||||
|
val logger = BuildSessionLogger(rootFolder)
|
||||||
|
logger.startBuildSession(1, 1)
|
||||||
|
for (metric in StringMetrics.values()) {
|
||||||
|
logger.report(metric, "value")
|
||||||
|
logger.report(metric, metric.name)
|
||||||
|
}
|
||||||
|
for (metric in BooleanMetrics.values()) {
|
||||||
|
logger.report(metric, true)
|
||||||
|
}
|
||||||
|
for (metric in NumericalMetrics.values()) {
|
||||||
|
logger.report(metric, System.currentTimeMillis())
|
||||||
|
}
|
||||||
|
logger.finishBuildSession("Build", null)
|
||||||
|
|
||||||
|
MetricsContainer.readFromFile(rootFolder.listFiles().single().listFiles().single()) {
|
||||||
|
for (metric in StringMetrics.values()) {
|
||||||
|
assertNotNull(it.getMetric(metric), "Could not find metric ${metric.name}")
|
||||||
|
}
|
||||||
|
for (metric in BooleanMetrics.values()) {
|
||||||
|
assertTrue(it.getMetric(metric)?.getValue() ?: false, "Could not find metric ${metric.name}")
|
||||||
|
}
|
||||||
|
for (metric in NumericalMetrics.values()) {
|
||||||
|
assertNotNull(it.getMetric(metric), "Could not find metric ${metric.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ val projectsToShadow by extra(listOf(
|
|||||||
":js:js.translator",
|
":js:js.translator",
|
||||||
":kotlin-native:kotlin-native-utils",
|
":kotlin-native:kotlin-native-utils",
|
||||||
":kotlin-native:kotlin-native-library-reader",
|
":kotlin-native:kotlin-native-library-reader",
|
||||||
|
":kotlin-gradle-statistics",
|
||||||
":compiler:light-classes",
|
":compiler:light-classes",
|
||||||
":compiler:plugin-api",
|
":compiler:plugin-api",
|
||||||
":kotlin-preloader",
|
":kotlin-preloader",
|
||||||
|
|||||||
Reference in New Issue
Block a user