[terminal] IDEA-348915 Report statistics for feedback survey events

Report when notification is shown, dialog is shown, and feedback is sent.

GitOrigin-RevId: e2273a95af14a3b58ffa6ae23793084dd9c363c0
This commit is contained in:
Konstantin Hudyakov
2024-03-22 11:47:26 +00:00
committed by intellij-monorepo-bot
parent cc7d1687da
commit 0d664bcbc0
3 changed files with 35 additions and 12 deletions
@@ -14,8 +14,7 @@ import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.encodeToJsonElement
import org.jetbrains.plugins.terminal.TerminalBundle
import org.jetbrains.plugins.terminal.exp.TerminalUsageLocalStorage
import org.jetbrains.plugins.terminal.exp.feedback.BlockTerminalFeedbackMoment.AFTER_USAGE
import org.jetbrains.plugins.terminal.exp.feedback.BlockTerminalFeedbackMoment.ON_DISABLING
import org.jetbrains.plugins.terminal.fus.TerminalFeedbackMoment
internal class BlockTerminalFeedbackDialog(project: Project, forTest: Boolean) : BlockBasedFeedbackDialog<BlockTerminalUsageData>(project, forTest) {
override val myFeedbackReportId: String = "new_terminal"
@@ -28,7 +27,7 @@ internal class BlockTerminalFeedbackDialog(project: Project, forTest: Boolean) :
BlockTerminalUsageData(
mostUsedShell = usageStorage.mostUsedShell,
executedCommandsNumber = usageStorage.executedCommandsNumber,
feedbackMoment = if (myProject!!.getUserData(BLOCK_TERMINAL_DISABLING) == true) ON_DISABLING else AFTER_USAGE,
feedbackMoment = getFeedbackMoment(project),
systemInfo = CommonFeedbackSystemData.getCurrentData()
)
}
@@ -73,7 +72,7 @@ internal class BlockTerminalFeedbackDialog(project: Project, forTest: Boolean) :
internal data class BlockTerminalUsageData(
@NlsSafe val mostUsedShell: String,
val executedCommandsNumber: Int,
val feedbackMoment: BlockTerminalFeedbackMoment,
val feedbackMoment: TerminalFeedbackMoment,
val systemInfo: CommonFeedbackSystemData
) : SystemDataJsonSerializable {
override fun serializeToJson(json: Json): JsonElement {
@@ -89,8 +88,4 @@ internal data class BlockTerminalUsageData(
appendLine(feedbackMoment.toString())
append(systemInfo.toString())
}
}
internal enum class BlockTerminalFeedbackMoment {
ON_DISABLING, AFTER_USAGE
}
@@ -15,9 +15,14 @@ import com.intellij.util.PlatformUtils
import kotlinx.datetime.LocalDate
import org.jetbrains.plugins.terminal.TerminalBundle
import org.jetbrains.plugins.terminal.exp.TerminalUsageLocalStorage
import org.jetbrains.plugins.terminal.fus.TerminalFeedbackEvent
import org.jetbrains.plugins.terminal.fus.TerminalFeedbackMoment
import org.jetbrains.plugins.terminal.fus.TerminalFeedbackMoment.AFTER_USAGE
import org.jetbrains.plugins.terminal.fus.TerminalFeedbackMoment.ON_DISABLING
import org.jetbrains.plugins.terminal.fus.TerminalUsageTriggerCollector
/** Used to indicate that we are trying to show the feedback notification after block terminal is disabled */
internal val BLOCK_TERMINAL_DISABLING: Key<Boolean> = Key.create("BlockTerminalDisabling")
private val BLOCK_TERMINAL_DISABLING: Key<Boolean> = Key.create("BlockTerminalDisabling")
internal fun showBlockTerminalFeedbackNotification(project: Project) {
project.putUserData(BLOCK_TERMINAL_DISABLING, true)
@@ -27,6 +32,10 @@ internal fun showBlockTerminalFeedbackNotification(project: Project) {
}
}
internal fun getFeedbackMoment(project: Project): TerminalFeedbackMoment {
return if (project.getUserData(BLOCK_TERMINAL_DISABLING) == true) ON_DISABLING else AFTER_USAGE
}
internal class BlockTerminalFeedbackSurvey : FeedbackSurvey() {
override val feedbackSurveyType: FeedbackSurveyType<*> = InIdeFeedbackSurveyType(BlockTerminalSurveyConfig())
}
@@ -35,11 +44,14 @@ internal class BlockTerminalSurveyConfig : InIdeFeedbackSurveyConfig {
override val surveyId: String = "new_terminal"
override fun createFeedbackDialog(project: Project, forTest: Boolean): BlockBasedFeedbackDialog<out SystemDataJsonSerializable> {
if (!forTest) {
TerminalUsageTriggerCollector.triggerFeedbackSurveyEvent(project, TerminalFeedbackEvent.DIALOG_SHOWN, getFeedbackMoment(project))
}
return BlockTerminalFeedbackDialog(project, forTest)
}
override fun updateStateAfterDialogClosedOk(project: Project) {
// do nothing
TerminalUsageTriggerCollector.triggerFeedbackSurveyEvent(project, TerminalFeedbackEvent.FEEDBACK_SENT, getFeedbackMoment(project))
}
// Last date is an approximate time of 2024.2 release
@@ -53,7 +65,7 @@ internal class BlockTerminalSurveyConfig : InIdeFeedbackSurveyConfig {
val usageStorage = TerminalUsageLocalStorage.getInstance()
return !usageStorage.state.feedbackNotificationShown &&
// show notification if user executed enough commands or if block terminal is being disabled
(usageStorage.executedCommandsNumber >= 15 || usageStorage.executedCommandsNumber > 0 && project.getUserData(BLOCK_TERMINAL_DISABLING) == true)
(usageStorage.executedCommandsNumber >= 15 || usageStorage.executedCommandsNumber > 0 && getFeedbackMoment(project) == ON_DISABLING)
}
override fun createNotification(project: Project, forTest: Boolean): RequestFeedbackNotification {
@@ -64,5 +76,6 @@ internal class BlockTerminalSurveyConfig : InIdeFeedbackSurveyConfig {
override fun updateStateAfterNotificationShowed(project: Project) {
TerminalUsageLocalStorage.getInstance().state.feedbackNotificationShown = true
TerminalUsageTriggerCollector.triggerFeedbackSurveyEvent(project, TerminalFeedbackEvent.NOTIFICATION_SHOWN, getFeedbackMoment(project))
}
}
@@ -18,7 +18,7 @@ import java.util.*
object TerminalUsageTriggerCollector : CounterUsagesCollector() {
override fun getGroup(): EventLogGroup = GROUP
private val GROUP = EventLogGroup(GROUP_ID, 18)
private val GROUP = EventLogGroup(GROUP_ID, 19)
private val TERMINAL_COMMAND_HANDLER_FIELD = EventFields.Class("terminalCommandHandler")
private val RUN_ANYTHING_PROVIDER_FIELD = EventFields.Class("runAnythingProvider")
@@ -47,6 +47,9 @@ object TerminalUsageTriggerCollector : CounterUsagesCollector() {
private val blockTerminalSwitchedEvent = GROUP.registerEvent("new.terminal.switched",
EventFields.Boolean("enabled"),
EventFields.Enum<BlockTerminalSwitchPlace>("switch_place"))
private val feedbackSurveyEvent = GROUP.registerEvent("feedback.event.happened",
EventFields.Enum<TerminalFeedbackEvent>("event_type"),
EventFields.Enum<TerminalFeedbackMoment>("moment"))
@JvmStatic
fun triggerSshShellStarted(project: Project) = sshExecEvent.log(project)
@@ -104,6 +107,10 @@ object TerminalUsageTriggerCollector : CounterUsagesCollector() {
blockTerminalSwitchedEvent.log(project, enabled, place)
}
internal fun triggerFeedbackSurveyEvent(project: Project, event: TerminalFeedbackEvent, moment: TerminalFeedbackMoment) {
feedbackSurveyEvent.log(project, event, moment)
}
@JvmStatic
private fun getShellNameForStat(shellName: String?): String {
if (shellName == null) return "unspecified"
@@ -128,6 +135,14 @@ internal enum class BlockTerminalSwitchPlace {
SETTINGS, TOOLWINDOW_OPTIONS
}
internal enum class TerminalFeedbackEvent {
NOTIFICATION_SHOWN, DIALOG_SHOWN, FEEDBACK_SENT
}
internal enum class TerminalFeedbackMoment {
ON_DISABLING, AFTER_USAGE
}
private const val GROUP_ID = "terminalShell"
private val KNOWN_SHELLS = setOf("unspecified",