IJPL-164376 Provide an action to create an issue for a plugin that causes freezes

(cherry picked from commit 87094e17a61390740e84eafc843c6ee46495db2a)
IJ-CR-146685

GitOrigin-RevId: dc4be0e511efc8d4af99094c6de66537a5b62613
This commit is contained in:
Maxim.Kolmakov
2024-10-17 17:24:02 +02:00
committed by intellij-monorepo-bot
parent 8c61cdf9db
commit 9dbc6953c2
5 changed files with 88 additions and 2 deletions

View File

@@ -1,5 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="kotlin-language" name="Kotlin">
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
<compilerSettings>
<option name="additionalArguments" value="-Xjvm-default=all" />
</compilerSettings>
<compilerArguments>
<stringArguments>
<stringArg name="jvmTarget" arg="17" />
<stringArg name="apiVersion" arg="2.0" />
<stringArg name="languageVersion" arg="2.0" />
</stringArguments>
<arrayArguments>
<arrayArg name="pluginClasspaths">
<args>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</args>
</arrayArg>
</arrayArguments>
</compilerArguments>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">

View File

@@ -1,4 +1,6 @@
action.disable.plugin.text=Disable plugin
action.close.panel.text=Dismiss
action.ignore.plugin.text=Ignore freezes in plugin
notification.content.plugin.caused.freeze.detected=Plugin ''{0}'' might be slowing things down
notification.content.plugin.caused.freeze.detected=Plugin ''{0}'' might be slowing things down
action.open.issue.tracker.text=Open issue tracker
progress.title.opening.issue.tracker=Opening plugin issue tracker

View File

@@ -2,6 +2,8 @@
package com.intellij.platform.diagnostic.plugin.freeze
import com.intellij.featureStatistics.fusCollectors.LifecycleUsageTriggerCollector
import com.intellij.ide.BrowserUtil
import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.impl.ApplicationInfoImpl
@@ -10,6 +12,7 @@ import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
import com.intellij.ui.EditorNotificationPanel
import com.intellij.ui.EditorNotificationProvider
import com.intellij.ui.EditorNotifications
@@ -45,6 +48,11 @@ internal class PluginFreezeNotifier : EditorNotificationProvider {
closePanel(project)
}
createActionLabel(PluginFreezeBundle.message("action.open.issue.tracker.text")) {
openIssueTracker(project, pluginDescriptor)
LifecycleUsageTriggerCollector.pluginIssueTrackerOpened()
}
createActionLabel(PluginFreezeBundle.message("action.close.panel.text")) {
closePanel(project)
}
@@ -60,6 +68,14 @@ internal class PluginFreezeNotifier : EditorNotificationProvider {
}
}
private fun openIssueTracker(project: Project, pluginDescriptor: IdeaPluginDescriptor) {
runWithModalProgressBlocking(project, PluginFreezeBundle.message("progress.title.opening.issue.tracker")) {
PluginIssueTrackerResolver.getMarketplaceBugTrackerUrl(pluginDescriptor)?.let {
BrowserUtil.open(it)
}
}
}
private fun closePanel(project: Project) {
freezeWatcher.reset()
EditorNotifications.getInstance(project).updateAllNotifications()

View File

@@ -0,0 +1,41 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.diagnostic.plugin.freeze
import com.intellij.ide.plugins.marketplace.utils.MarketplaceUrls
import com.intellij.openapi.extensions.PluginDescriptor
import com.intellij.util.io.HttpRequests
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import java.util.concurrent.TimeUnit
@Serializable
private data class MarketplacePluginInfo(
val urls: PluginUrls,
val icon: String,
)
@Serializable
private data class PluginUrls(
val url: String,
val bugtrackerUrl: String,
)
internal object PluginIssueTrackerResolver {
private val json = Json { ignoreUnknownKeys = true }
suspend fun getMarketplaceBugTrackerUrl(pluginDescriptor: PluginDescriptor): String? {
val url = pluginDescriptor.url?.replace("/plugin/", "/api/plugins/")
if (url == null) return MarketplaceUrls.getPluginHomepage(pluginDescriptor.pluginId)
val timeoutMillis = TimeUnit.SECONDS.toMillis(5)
return withContext(Dispatchers.IO) {
runCatching {
val response = HttpRequests.request(url).connectTimeout(timeoutMillis.toInt()).readTimeout(timeoutMillis.toInt()).readString()
val pluginInfo: MarketplacePluginInfo = json.decodeFromString(response)
pluginInfo.urls.bugtrackerUrl
}.getOrDefault(MarketplaceUrls.getPluginHomepage(pluginDescriptor.pluginId))
}
}
}

View File

@@ -28,7 +28,7 @@ import static com.intellij.internal.statistic.utils.PluginInfoDetectorKt.getPlug
public final class LifecycleUsageTriggerCollector extends CounterUsagesCollector {
private static final Logger LOG = Logger.getInstance(LifecycleUsageTriggerCollector.class);
private static final EventLogGroup LIFECYCLE = new EventLogGroup("lifecycle", 71);
private static final EventLogGroup LIFECYCLE = new EventLogGroup("lifecycle", 72);
private static final EventField<Boolean> eapField = EventFields.Boolean("eap");
private static final EventField<Boolean> testField = EventFields.Boolean("test");
@@ -72,6 +72,8 @@ public final class LifecycleUsageTriggerCollector extends CounterUsagesCollector
LIFECYCLE.registerEvent("ide.freeze.disabled.plugin", EventFields.PluginInfo);
private static final EventId1<PluginInfo> IDE_FREEZE_PLUGIN_IGNORED =
LIFECYCLE.registerEvent("ide.freeze.ignored.plugin", EventFields.PluginInfo);
private static final EventId IDE_FREEZE_PLUGIN_ISSUE_TRACKER_OPENED =
LIFECYCLE.registerEvent("ide.freeze.issue.tracker.opened");
private static final ClassEventField errorField = EventFields.Class("error");
private static final EventField<VMOptions.MemoryKind> memoryErrorKindField =
@@ -240,4 +242,8 @@ public final class LifecycleUsageTriggerCollector extends CounterUsagesCollector
public static void pluginFreezeIgnored(@NotNull PluginId id) {
IDE_FREEZE_PLUGIN_IGNORED.log(getPluginInfoById(id));
}
public static void pluginIssueTrackerOpened() {
IDE_FREEZE_PLUGIN_ISSUE_TRACKER_OPENED.log();
}
}