mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-91367 [PPTW] Add usage statistics tracking for key interactions in the Install Package dialog and tool window.
Original MR: IJ-MR-216488 Merge-request: IJ-MR-216726 Merged-by: Timur Malanin <timur.malanin@jetbrains.com> GitOrigin-RevId: e2db1ab8633b2d96397698720fb56b8550e2ddd0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
06bab38258
commit
29ba1b4ff8
@@ -22,6 +22,7 @@ import com.intellij.ui.EditorNotificationProvider
|
||||
import com.intellij.ui.components.TwoSideComponent
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.icons.PythonIcons
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.requirements.RequirementsFileType
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.awt.BorderLayout
|
||||
@@ -116,6 +117,7 @@ internal class PyPackageManagerEditorBanner : EditorNotificationProvider, DumbAw
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
PythonPackagesToolwindowStatisticsCollector.navigateFromDependencyFileEvent.log()
|
||||
ToolWindowManager.getInstance(project).getToolWindow(PACKAGING_TOOL_WINDOW_ID)?.activate(null)
|
||||
}
|
||||
|
||||
|
||||
+62
-8
@@ -1,17 +1,71 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.packaging.statistics
|
||||
|
||||
import com.intellij.ide.actions.ToolWindowMoveAction
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||
import com.intellij.internal.statistic.eventLog.events.EventId
|
||||
import com.intellij.internal.statistic.eventLog.events.EventId1
|
||||
import com.intellij.internal.statistic.eventLog.events.EventId2
|
||||
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
||||
|
||||
object PythonPackagesToolwindowStatisticsCollector : CounterUsagesCollector() {
|
||||
|
||||
override fun getGroup() = GROUP
|
||||
override fun getGroup(): EventLogGroup = GROUP
|
||||
|
||||
private val GROUP = EventLogGroup("python.packages.toolwindow", 1)
|
||||
// Tool-window open/close and anchor changes are already covered by the platform "toolwindow" group
|
||||
// (ToolWindowEventLogGroup): `shown`/`activated`/`hidden` events with `id="Python Packages"` and
|
||||
// an `Anchor` `Location` field. This collector only tracks PPTW-specific interactions the
|
||||
// platform does not see.
|
||||
private val GROUP = EventLogGroup("python.packages.toolwindow", 2)
|
||||
|
||||
val installPackageEvent = GROUP.registerEvent("installed")
|
||||
val uninstallPackageEvent = GROUP.registerEvent("uninstalled")
|
||||
val requestDetailsEvent = GROUP.registerEvent("details.requested")
|
||||
val repositoriesChangedEvent = GROUP.registerEvent("repositories.changed")
|
||||
}
|
||||
internal val installPackageEvent: EventId = GROUP.registerEvent("installed")
|
||||
internal val uninstallPackageEvent: EventId = GROUP.registerEvent("uninstalled")
|
||||
internal val requestDetailsEvent: EventId = GROUP.registerEvent("details.requested")
|
||||
internal val repositoriesChangedEvent: EventId = GROUP.registerEvent("repositories.changed")
|
||||
|
||||
// Install-dialog entry points: keyboard shortcut / PPTW header install button / gutter or context
|
||||
// action on an InstallablePackage tree node / dependency-group inlay hint.
|
||||
internal val installDialogOpenedEvent: EventId1<PyInstallDialogSource> = GROUP.registerEvent(
|
||||
"install.dialog.opened",
|
||||
EventFields.Enum<PyInstallDialogSource>("source"),
|
||||
)
|
||||
|
||||
// Not covered by the platform "toolwindow" group: we need to attribute anchor changes
|
||||
// specifically to the PPTW toggle action (right/bottom button) with from/to, so users of the
|
||||
// dashboard can compare "user dragged" vs "user clicked our action" flows.
|
||||
internal val anchorToggledEvent: EventId2<ToolWindowMoveAction.Anchor, ToolWindowMoveAction.Anchor> = GROUP.registerEvent(
|
||||
"anchor.toggled",
|
||||
EventFields.Enum<ToolWindowMoveAction.Anchor>("from"),
|
||||
EventFields.Enum<ToolWindowMoveAction.Anchor>("to"),
|
||||
)
|
||||
|
||||
// DialogMode is internal; keep the collector free of that dependency by using a String allow-list
|
||||
// that mirrors the DialogMode enum names.
|
||||
internal val installDialogInstallEvent: EventId2<String?, Boolean> = GROUP.registerEvent(
|
||||
"install.dialog.installed",
|
||||
EventFields.String("mode", listOf("SEARCH", "DIRECT_INSTALL", "COMMAND")),
|
||||
EventFields.Boolean("editable"),
|
||||
)
|
||||
|
||||
// Editor-banner navigation from a dependency file to the PPTW.
|
||||
internal val navigateFromDependencyFileEvent: EventId = GROUP.registerEvent("navigate.from.dependency.file")
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point that opened the [com.jetbrains.python.packaging.toolwindow.ui.PyInstallPackageDialog].
|
||||
* Kept top-level (not nested in [PythonPackagesToolwindowStatisticsCollector]) so its FQN stays
|
||||
* short in the generated FUS events scheme.
|
||||
*/
|
||||
internal enum class PyInstallDialogSource {
|
||||
/** Keyboard shortcut / Find Action invocation of `PyInstallPackageAction`. */
|
||||
SHORTCUT,
|
||||
/** Install button in the PPTW header search bar. */
|
||||
HEADER,
|
||||
/** Click on the install icon of an `InstallablePackage` node in the tree. */
|
||||
LIST_ICON,
|
||||
/** Context-menu `InstallPackageAction` on a selected `InstallablePackage`. */
|
||||
INSTALLABLE_ACTION,
|
||||
/** `+ Add package` inlay hint inside a `pyproject.toml` dependency group. */
|
||||
INLAY_HINT,
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import com.intellij.ui.dsl.gridLayout.UnscaledGapsY
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.packaging.statistics.PyInstallDialogSource
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.actions.PyTogglePackagingToolWindowAnchorAction
|
||||
import com.jetbrains.python.packaging.toolwindow.details.PyPackageInfoPanel
|
||||
import com.jetbrains.python.packaging.toolwindow.model.DisplayablePackage
|
||||
@@ -207,6 +209,7 @@ internal class PyPackagingToolWindowPanel(private val project: Project) : Simple
|
||||
PyPackageIcons.AddPackage,
|
||||
) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
PythonPackagesToolwindowStatisticsCollector.installDialogOpenedEvent.log(PyInstallDialogSource.HEADER)
|
||||
PyInstallPackageDialog(project).show(packageSearchController.text.trim().takeIf { it.isNotEmpty() })
|
||||
}
|
||||
}.apply {
|
||||
|
||||
@@ -4,6 +4,8 @@ package com.jetbrains.python.packaging.toolwindow.actions
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.jetbrains.python.packaging.management.PythonPackageInstallRequest
|
||||
import com.jetbrains.python.packaging.pyRequirement
|
||||
import com.jetbrains.python.packaging.statistics.PyInstallDialogSource
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.model.InstallablePackage
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyInstallPackageDialog
|
||||
@@ -27,6 +29,7 @@ internal class InstallPackageAction : ModifyPackagesActionBase() {
|
||||
return
|
||||
}
|
||||
val pkg = e.selectedPackage as? InstallablePackage ?: return
|
||||
PythonPackagesToolwindowStatisticsCollector.installDialogOpenedEvent.log(PyInstallDialogSource.INSTALLABLE_ACTION)
|
||||
PyInstallPackageDialog(project).show(pkg.name)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.jetbrains.python.packaging.statistics.PyInstallDialogSource
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyInstallPackageDialog
|
||||
|
||||
@@ -24,6 +26,7 @@ internal class PyInstallPackageAction : DumbAwareAction() {
|
||||
// when no SDK is available, but invoking it through a keymap binding bypasses that gate in
|
||||
// some contexts (Find Action / global shortcut), so re-check before showing the dialog.
|
||||
if (project.service<PyPackagingToolWindowService>().currentSdk == null) return
|
||||
PythonPackagesToolwindowStatisticsCollector.installDialogOpenedEvent.log(PyInstallDialogSource.SHORTCUT)
|
||||
PyInstallPackageDialog(project).show()
|
||||
}
|
||||
|
||||
|
||||
+9
-4
@@ -10,6 +10,7 @@ import com.intellij.openapi.wm.ToolWindow
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowPanel
|
||||
|
||||
internal class PyTogglePackagingToolWindowAnchorAction : DumbAwareAction() {
|
||||
@@ -33,13 +34,17 @@ internal class PyTogglePackagingToolWindowAnchorAction : DumbAwareAction() {
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val toolWindow = findToolWindow(e) ?: return
|
||||
val target = if (toolWindow.anchor == ToolWindowAnchor.RIGHT) {
|
||||
ToolWindowMoveAction.Anchor.BottomLeft
|
||||
// The action only swaps between the two corners its two icons point to, so encoding "from" as
|
||||
// whichever of those two matches the current basic anchor is exact — no need to reach into
|
||||
// `WindowInfo` (internal API) to distinguish split states we never produce ourselves.
|
||||
val (from, to) = if (toolWindow.anchor == ToolWindowAnchor.RIGHT) {
|
||||
ToolWindowMoveAction.Anchor.RightBottom to ToolWindowMoveAction.Anchor.BottomLeft
|
||||
}
|
||||
else {
|
||||
ToolWindowMoveAction.Anchor.RightBottom
|
||||
ToolWindowMoveAction.Anchor.BottomLeft to ToolWindowMoveAction.Anchor.RightBottom
|
||||
}
|
||||
target.applyTo(toolWindow)
|
||||
to.applyTo(toolWindow)
|
||||
PythonPackagesToolwindowStatisticsCollector.anchorToggledEvent.log(from, to)
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
|
||||
+3
@@ -36,6 +36,8 @@ import com.intellij.ui.dsl.builder.panel
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.packaging.management.isDependencyGroupSupported
|
||||
import com.jetbrains.python.packaging.statistics.PyInstallDialogSource
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyInstallPackageDialog
|
||||
import com.jetbrains.python.sdk.PythonSdkUtil
|
||||
import org.toml.lang.psi.TomlKeySegment
|
||||
@@ -120,6 +122,7 @@ internal class PyDependencyGroupInlayHintsProvider : InlayHintsProvider<NoSettin
|
||||
project.service<PyPackagingToolWindowService>().initForSdk(moduleSdk)
|
||||
}
|
||||
withContext(Dispatchers.EDT) {
|
||||
PythonPackagesToolwindowStatisticsCollector.installDialogOpenedEvent.log(PyInstallDialogSource.INLAY_HINT)
|
||||
PyInstallPackageDialog(project).show(preselectModuleName = preselectName, preselectGroupName = groupName)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -37,6 +37,8 @@ import com.jetbrains.python.packaging.toolwindow.model.UndeclaredPackagesGroup
|
||||
import com.jetbrains.python.packaging.toolwindow.packages.tree.renderers.PyPackageTreeCellRenderer
|
||||
import com.jetbrains.python.packaging.toolwindow.packages.tree.renderers.asInstalledPackageOrNull
|
||||
import com.jetbrains.python.packaging.toolwindow.packages.tree.renderers.trailingIconTooltip
|
||||
import com.jetbrains.python.packaging.statistics.PyInstallDialogSource
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.PyInstallPackageDialog
|
||||
import com.jetbrains.python.packaging.toolwindow.ui.showChangeVersionPopup
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
@@ -377,7 +379,8 @@ internal class PyPackagesTree(
|
||||
}
|
||||
|
||||
private fun showInstallDialog(pkg: InstallablePackage) {
|
||||
PyInstallPackageDialog(project).show(pkg.name)
|
||||
PythonPackagesToolwindowStatisticsCollector.installDialogOpenedEvent.log(PyInstallDialogSource.LIST_ICON)
|
||||
PyInstallPackageDialog(project).show(initialSearchText = pkg.name)
|
||||
}
|
||||
|
||||
private fun updatePackageToLatest(pkg: InstalledPackage) {
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import com.jetbrains.python.packaging.statistics.PythonPackagesToolwindowStatisticsCollector
|
||||
import com.jetbrains.python.packaging.toolwindow.PyPackagingToolWindowService
|
||||
import com.jetbrains.python.sdk.findFirstPythonSdk
|
||||
import com.jetbrains.python.sdk.findModuleForSdk
|
||||
@@ -553,6 +554,10 @@ internal class PyInstallPackageDialog(private val project: Project) : BigPopupUI
|
||||
}
|
||||
|
||||
private fun performInstall() {
|
||||
PythonPackagesToolwindowStatisticsCollector.installDialogInstallEvent.log(
|
||||
currentMode.name,
|
||||
versionPanel.editableCheckbox.isSelected,
|
||||
)
|
||||
when (currentMode) {
|
||||
DialogMode.DIRECT_INSTALL -> performDirectInstall()
|
||||
DialogMode.COMMAND -> performCommandExecution(mySearchField.text.trim())
|
||||
|
||||
Reference in New Issue
Block a user