IDEA-356847 [Gradle|Sync|FUS] new: added feature usage statistics for the Gradle model fetch phases

GitOrigin-RevId: e86ce0971d245803e8c9cabd4a84b43d8df67179
This commit is contained in:
Sergei Vorobyov
2024-08-02 22:50:06 +00:00
committed by intellij-monorepo-bot
parent 6a03680849
commit fb6c155c49
6 changed files with 146 additions and 9 deletions
@@ -173,6 +173,7 @@
<runAnything.executionProvider implementation="org.jetbrains.plugins.gradle.execution.GradleRunAnythingProvider" order="first"/>
<statistics.projectUsagesCollector implementation="org.jetbrains.plugins.gradle.statistics.GradleSettingsCollector"/>
<statistics.counterUsagesCollector implementationClass="org.jetbrains.plugins.gradle.statistics.GradleSyncCollector"/>
<statistics.counterUsagesCollector implementationClass="org.jetbrains.plugins.gradle.statistics.GradleModelBuilderMessageCollector"/>
<statistics.counterUsagesCollector implementationClass="org.jetbrains.plugins.gradle.statistics.GradleActionsUsagesCollector"/>
<statistics.counterUsagesCollector implementationClass="org.jetbrains.plugins.gradle.statistics.GradleTaskExecutionCollector"/>
@@ -2,6 +2,7 @@
package org.jetbrains.plugins.gradle.service.modelAction
import com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction
import com.intellij.gradle.toolingExtension.modelAction.GradleModelFetchPhase
import com.intellij.gradle.toolingExtension.util.GradleVersionUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.registry.Registry
@@ -15,7 +16,7 @@ import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
import org.jetbrains.plugins.gradle.service.project.DefaultProjectResolverContext
import org.jetbrains.plugins.gradle.service.project.GradleOperationHelperExtension
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
import org.jetbrains.plugins.gradle.statistics.GradleSyncCollector
/**
* This class handles setting up and running the [BuildActionExecuter] it deals with calling the correct APIs based on the version of
* Gradle that is present.
@@ -32,7 +33,7 @@ class GradleModelFetchActionRunner private constructor(
private val resolverContext: DefaultProjectResolverContext,
private val settings: GradleExecutionSettings,
private val modelFetchAction: GradleModelFetchAction,
private val modelFetchActionListener: GradleModelFetchActionListener
private val modelFetchActionListener: GradleModelFetchActionListener,
) {
/**
@@ -114,14 +115,36 @@ class GradleModelFetchActionRunner private constructor(
companion object {
@JvmStatic
fun runBuildAction(
private fun runBuildAction(
resolverContext: DefaultProjectResolverContext,
settings: GradleExecutionSettings,
modelFetchAction: GradleModelFetchAction,
modelFetchActionListener: GradleModelFetchActionListener
modelFetchActionListener: GradleModelFetchActionListener,
) {
GradleModelFetchActionRunner(resolverContext, settings, modelFetchAction, modelFetchActionListener).runBuildAction()
}
@JvmStatic
fun runAndTraceBuildAction(
resolverContext: DefaultProjectResolverContext,
settings: GradleExecutionSettings,
modelFetchAction: GradleModelFetchAction,
modelFetchActionListener: GradleModelFetchActionListener,
) {
GradleSyncCollector.ModelFetchCollector(resolverContext).use { collector ->
val modelFetchActionListenerWithTrace = object : GradleModelFetchActionListener by modelFetchActionListener {
override suspend fun onModelFetchPhaseCompleted(phase: GradleModelFetchPhase) {
modelFetchActionListener.onModelFetchPhaseCompleted(phase)
collector.logModelFetchPhaseCompleted(phase)
}
override suspend fun onModelFetchFailed(exception: Throwable) {
modelFetchActionListener.onModelFetchFailed(exception)
collector.logModelFetchFailure(exception)
}
}
runBuildAction(resolverContext, settings, modelFetchAction, modelFetchActionListenerWithTrace)
}
}
}
}
@@ -318,7 +318,6 @@ public class DefaultProjectResolverContext extends UserDataHolderBase implements
return myProjectGradleVersion;
}
@Override
public boolean isBuildSrcProject() {
return myBuildSrcProject;
}
@@ -335,7 +335,7 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
}
try (Scope ignore = gradleCallSpan.makeCurrent()) {
var modelFetchActionResultHandler = new GradleModelFetchActionResultHandler(resolverContext);
GradleModelFetchActionRunner.runBuildAction(resolverContext, executionSettings, buildAction, modelFetchActionResultHandler);
GradleModelFetchActionRunner.runAndTraceBuildAction(resolverContext, executionSettings, buildAction, modelFetchActionResultHandler);
var gradleVersion = ObjectUtils.doIfNotNull(resolverContext.getProjectGradleVersion(), it -> GradleVersion.version(it));
if (gradleVersion != null && GradleJvmSupportMatrix.isGradleDeprecatedByIdea(gradleVersion)) {
@@ -101,8 +101,6 @@ public interface ProjectResolverContext extends UserDataHolderEx {
@Nullable
String getProjectGradleVersion();
boolean isBuildSrcProject();
@Nullable
String getBuildSrcGroup();
@@ -0,0 +1,116 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.statistics
import com.intellij.gradle.toolingExtension.modelAction.GradleModelFetchPhase
import com.intellij.gradle.toolingExtension.modelAction.GradleModelFetchPhase.*
import com.intellij.internal.statistic.eventLog.EventLogGroup
import com.intellij.internal.statistic.eventLog.events.EventFields
import com.intellij.internal.statistic.eventLog.events.LongEventField
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.gradle.service.project.DefaultProjectResolverContext
import java.util.*
@ApiStatus.Internal
internal object GradleSyncCollector : CounterUsagesCollector() {
override fun getGroup(): EventLogGroup = GROUP
private val GROUP = EventLogGroup("gradle.sync", 1)
private val ACTIVITY_ID = EventFields.Long("ide_activity_id")
private val MODEL_FETCH_FOR_BUILD_SRC = EventFields.Boolean("model_fetch_for_build_src")
private val MODEL_FETCH_ERROR_COUNT = EventFields.Int("model_fetch_error_count")
private val MODEL_FETCH_COMPLETION_STAMP = EventFields.Long("model_fetch_completion_stamp")
private val PROJECT_LOADED_PHASE_COMPLETION_STAMP = EventFields.Long("project_loaded_phase_completion_stamp")
private val WARM_UP_PHASE_COMPLETION_STAMP = EventFields.Long("warm_up_phase_completion_stamp")
private val PROJECT_MODEL_PHASE_COMPLETION_STAMP = EventFields.Long("project_model_phase_completion_stamp")
private val PROJECT_SOURCE_SET_PHASE_COMPLETION_STAMP = EventFields.Long("project_source_set_phase_completion_stamp")
private val PROJECT_SOURCE_SET_DEPENDENCY_PHASE_COMPLETION_STAMP = EventFields.Long("project_source_set_dependency_phase_completion_stamp")
private val ADDITIONAL_MODEL_PHASE_COMPLETION_STAMP = EventFields.Long("additional_model_phase_completion_stamp")
private val MODEL_FETCH_COMPLETED_EVENT = GROUP.registerVarargEvent(
"gradle.sync.model.fetch.completed",
ACTIVITY_ID,
MODEL_FETCH_FOR_BUILD_SRC,
MODEL_FETCH_ERROR_COUNT,
MODEL_FETCH_COMPLETION_STAMP,
PROJECT_LOADED_PHASE_COMPLETION_STAMP,
WARM_UP_PHASE_COMPLETION_STAMP,
PROJECT_MODEL_PHASE_COMPLETION_STAMP,
PROJECT_SOURCE_SET_PHASE_COMPLETION_STAMP,
PROJECT_SOURCE_SET_DEPENDENCY_PHASE_COMPLETION_STAMP,
ADDITIONAL_MODEL_PHASE_COMPLETION_STAMP
)
class ModelFetchCollector(
private val context: DefaultProjectResolverContext,
) : AutoCloseable {
private val modelFetchStartStamp: GlobalStamp = GlobalStamp.now()
private val phaseCompletionStamps: MutableMap<GradleModelFetchPhase, LocalStamp> = EnumMap(GradleModelFetchPhase::class.java)
private val exceptions = ArrayList<Throwable>()
fun logModelFetchPhaseCompleted(phase: GradleModelFetchPhase) {
val currentStamp = GlobalStamp.now()
val phaseCompletionStamp = currentStamp - modelFetchStartStamp
phaseCompletionStamps[phase] = phaseCompletionStamp
}
fun logModelFetchFailure(exception: Throwable) {
exceptions.add(exception)
}
override fun close() {
val currentStamp = GlobalStamp.now()
val project = context.externalSystemTaskId.findProject()
MODEL_FETCH_COMPLETED_EVENT.log(project) {
add(ACTIVITY_ID with context.externalSystemTaskId.id)
add(MODEL_FETCH_FOR_BUILD_SRC with context.isBuildSrcProject)
add(MODEL_FETCH_ERROR_COUNT with exceptions.size)
val modelFetchStamp = currentStamp - modelFetchStartStamp
add(MODEL_FETCH_COMPLETION_STAMP with modelFetchStamp.time)
for (phase in entries) {
val field = phase.getModelFetchPhaseStampEventField()
val stamp = phaseCompletionStamps[phase] ?: continue
add(field with stamp.time)
}
}
}
private fun GradleModelFetchPhase.getModelFetchPhaseStampEventField(): LongEventField {
return when (this) {
PROJECT_LOADED_PHASE -> PROJECT_LOADED_PHASE_COMPLETION_STAMP
WARM_UP_PHASE -> WARM_UP_PHASE_COMPLETION_STAMP
PROJECT_MODEL_PHASE -> PROJECT_MODEL_PHASE_COMPLETION_STAMP
PROJECT_SOURCE_SET_PHASE -> PROJECT_SOURCE_SET_PHASE_COMPLETION_STAMP
PROJECT_SOURCE_SET_DEPENDENCY_PHASE -> PROJECT_SOURCE_SET_DEPENDENCY_PHASE_COMPLETION_STAMP
ADDITIONAL_MODEL_PHASE -> ADDITIONAL_MODEL_PHASE_COMPLETION_STAMP
}
}
}
@JvmInline
private value class GlobalStamp(val time: Long) {
operator fun minus(stamp: GlobalStamp): LocalStamp {
return LocalStamp(time - stamp.time)
}
companion object {
fun now(): GlobalStamp {
return GlobalStamp(System.currentTimeMillis())
}
}
}
@JvmInline
private value class LocalStamp(val time: Long)
}