diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/actions/persistence/ActionsCollectorImpl.java b/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/actions/persistence/ActionsCollectorImpl.java index 1a5443b1362e..1bb093cf4808 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/actions/persistence/ActionsCollectorImpl.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/actions/persistence/ActionsCollectorImpl.java @@ -2,22 +2,21 @@ package com.intellij.internal.statistic.collectors.fus.actions.persistence; import com.intellij.ide.actions.ActionsCollector; -import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; import com.intellij.internal.statistic.collectors.fus.ui.persistence.ShortcutsCollector; +import com.intellij.internal.statistic.eventLog.FeatureUsageDataBuilder; import com.intellij.internal.statistic.eventLog.FeatureUsageGroup; import com.intellij.internal.statistic.eventLog.FeatureUsageLogger; import com.intellij.internal.statistic.persistence.UsageStatisticsPersistenceComponent; import com.intellij.internal.statistic.service.fus.collectors.FUSUsageContext; +import com.intellij.internal.statistic.utils.PluginInfo; import com.intellij.internal.statistic.utils.StatisticsUtilKt; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; -import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +30,7 @@ import java.util.Map; value = UsageStatisticsPersistenceComponent.USAGE_STATISTICS_XML, roamingType = RoamingType.DISABLED, deprecated = true) ) public class ActionsCollectorImpl extends ActionsCollector implements PersistentStateComponent { - private static final FeatureUsageGroup GROUP = new FeatureUsageGroup("actions.v2", 1); + private static final FeatureUsageGroup GROUP = new FeatureUsageGroup("actions", 1); private static final String DEFAULT_ID = "third.party.plugin.action"; private static final HashMap ourPrefixesBlackList = new HashMap<>(); @@ -51,19 +50,24 @@ public class ActionsCollectorImpl extends ActionsCollector implements Persistent boolean isContextMenu = event != null && event.isFromContextMenu(); final String place = event != null ? event.getPlace() : ""; - final boolean isDevelopedByJB = isDevelopedByJetBrains(context); - String key = isDevelopedByJB ? toReportedId(actionId) : DEFAULT_ID; - final Map data = ContainerUtil.newHashMap(FUSUsageContext.OS_CONTEXT.getData()); - data.put("context_menu", isContextMenu); + final PluginInfo info = StatisticsUtilKt.getPluginInfo(context); + final FeatureUsageDataBuilder builder = new FeatureUsageDataBuilder(). + addFeatureContext(FUSUsageContext.OS_CONTEXT). + addPluginInfo(info). + addData("context_menu", isContextMenu); + + final boolean isDevelopedByJB = info.getType().isDevelopedByJetBrains(); if (isContextMenu && isDevelopedByJB) { - data.put("place", place); + builder.addPlace(place); } final String inputEvent = ShortcutsCollector.getInputEventText(event); if (StringUtil.isNotEmpty(inputEvent)) { - data.put("input_event", inputEvent); + builder.addData("input_event", inputEvent); } - FeatureUsageLogger.INSTANCE.log(GROUP, key, data); + + final String key = isDevelopedByJB ? toReportedId(actionId) : DEFAULT_ID; + FeatureUsageLogger.INSTANCE.log(GROUP, key, builder.createData()); } @NotNull @@ -77,11 +81,6 @@ public class ActionsCollectorImpl extends ActionsCollector implements Persistent return key; } - private static boolean isDevelopedByJetBrains(@NotNull Class aClass) { - final PluginId pluginId = PluginManagerCore.getPluginByClassName(aClass.getName()); - return StatisticsUtilKt.isDevelopedByJetBrains(pluginId); - } - private State myState = new State(); @Nullable diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/FeatureUsageDataBuilder.kt b/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/FeatureUsageDataBuilder.kt new file mode 100644 index 000000000000..a683874dc8e9 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/eventLog/FeatureUsageDataBuilder.kt @@ -0,0 +1,56 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.internal.statistic.eventLog + +import com.intellij.internal.statistic.service.fus.collectors.FUSUsageContext +import com.intellij.internal.statistic.utils.PluginInfo +import com.intellij.internal.statistic.utils.getProjectId +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.text.StringUtil +import com.intellij.util.containers.ContainerUtil +import java.util.* + +class FeatureUsageDataBuilder { + private var data: MutableMap = ContainerUtil.newHashMap() + + fun addFeatureContext(context: FUSUsageContext?): FeatureUsageDataBuilder { + if (context != null) { + data.putAll(context.data) + } + return this + } + + fun addProject(project: Project?): FeatureUsageDataBuilder { + if (project != null) { + data["project"] = getProjectId(project) + } + return this + } + + fun addPluginInfo(info: PluginInfo): FeatureUsageDataBuilder { + data["plugin_type"] = info.type.name + if (info.type.isSafeToReport() && info.id != null && StringUtil.isNotEmpty(info.id)) { + data["plugin"] = info.id + } + return this + } + + fun addPlace(place: String): FeatureUsageDataBuilder { + data["place"] = place + return this + } + + fun addData(key: String, value: Any): FeatureUsageDataBuilder { + data[key] = value + return this + } + + fun createData(): Map { + return data + } +} + +fun newData(project: Project?, context: FUSUsageContext?): Map { + if (project == null && context == null) return Collections.emptyMap() + + return FeatureUsageDataBuilder().addProject(project).addFeatureContext(context).createData() +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt b/platform/platform-impl/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt index a29ea843d5ed..54e7dd380e62 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt +++ b/platform/platform-impl/src/com/intellij/internal/statistic/utils/StatisticsUtil.kt @@ -4,6 +4,7 @@ package com.intellij.internal.statistic.utils import com.intellij.ide.plugins.* import com.intellij.internal.statistic.beans.UsageDescriptor import com.intellij.internal.statistic.eventLog.EventLogConfiguration +import com.intellij.internal.statistic.eventLog.newData import com.intellij.internal.statistic.service.fus.collectors.FUSUsageContext import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ex.ApplicationInfoEx @@ -28,17 +29,7 @@ fun getProjectId(project: Project): String { } fun createData(project: Project?, context: FUSUsageContext?): Map { - if (project == null && context == null) return Collections.emptyMap() - - val data = ContainerUtil.newHashMap() - if (context != null) { - data.putAll(context.data) - } - - if (project != null) { - data["project"] = getProjectId(project) - } - return data + return newData(project, context) } fun mergeWithEventData(data: Map, context: FUSUsageContext?, value : Int): Map { @@ -295,22 +286,49 @@ fun getPluginType(clazz: Class<*>): PluginType { return if (listed) PluginType.LISTED else PluginType.NOT_LISTED } +fun getPluginInfo(clazz: Class<*>): PluginInfo { + val pluginId = PluginManagerCore.getPluginByClassName(clazz.name) ?: return PluginInfo(PluginType.PLATFORM, null) + val plugin = PluginManager.getPlugin(pluginId) ?: return PluginInfo(PluginType.UNKNOWN, null) + + val id = plugin.pluginId.idString + if (PluginManagerMain.isDevelopedByJetBrains(plugin)) { + return if (plugin.isBundled) { + PluginInfo(PluginType.JB_BUNDLED, id) + } + else { + PluginInfo(PluginType.JB_NOT_BUNDLED, id) + } + } + + // only plugins installed from some repository (not bundled and not provided via classpath in development IDE instance - + // they are also considered bundled) would be reported + val listed = !plugin.isBundled && isSafeToReport(pluginId.idString) + return if (listed) { + PluginInfo(PluginType.LISTED, id) + } + else { + PluginInfo(PluginType.NOT_LISTED, null) + } +} + enum class PluginType { PLATFORM, JB_BUNDLED, JB_NOT_BUNDLED, LISTED, NOT_LISTED, UNKNOWN; - fun isPlatformOrJBBundled() : Boolean { + fun isPlatformOrJBBundled(): Boolean { return this == PLATFORM || this == JB_BUNDLED } - fun isDevelopedByJetBrains() : Boolean { + fun isDevelopedByJetBrains(): Boolean { return isPlatformOrJBBundled() || this == JB_NOT_BUNDLED } - fun isSafeToReport() : Boolean { + fun isSafeToReport(): Boolean { return isDevelopedByJetBrains() || this == LISTED; } } +class PluginInfo(val type: PluginType, val id: String?) + private class DelayModificationTracker internal constructor(delay: Long, unit: TimeUnit) : ModificationTracker { private val myStamp = System.currentTimeMillis()