From 58cc77b9403c6ec996a2659348e83493e675a10e Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Tue, 3 Sep 2024 14:49:24 -0700 Subject: [PATCH 1/9] Add file extension type metrics --- .../telemetry/OpenedFileTypesMetrics.kt | 58 +++++++++++++++++++ .../src/main/resources/META-INF/plugin.xml | 1 + 2 files changed, 59 insertions(+) create mode 100644 plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt new file mode 100644 index 00000000000..9af463d8a65 --- /dev/null +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -0,0 +1,58 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.telemetry + +import com.intellij.openapi.Disposable +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.fileEditor.FileEditorManagerListener +import com.intellij.openapi.project.Project +import com.intellij.openapi.startup.ProjectActivity +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.util.Alarm +import software.aws.toolkits.telemetry.IdeTelemetry + +class OpenedFileTypesMetrics : ProjectActivity, Disposable { + private val currentOpenedFileTypes = mutableSetOf() + private val alarm = Alarm(Alarm.ThreadToUse.POOLED_THREAD, this) + override suspend fun execute(project: Project) { + // add already open file extensions + FileEditorManager.getInstance(project).openFiles.forEach { + it.extension?.let { openFileExtension -> currentOpenedFileTypes.add(openFileExtension) } + } + + // add newly opened file extensions + project.messageBus.connect().subscribe( + FileEditorManagerListener.FILE_EDITOR_MANAGER, + object : FileEditorManagerListener { + override fun fileOpened(source: FileEditorManager, file: VirtualFile) { + + file.extension?.let { currentOpenedFileTypes.add(it) } + } + } + ) + scheduleNextMetricEvent() + } + + private fun scheduleNextMetricEvent() { + alarm.addRequest(this::emitFileTypeMetric, INTERVAL_BETWEEN_METRICS) + } + + override fun dispose() {} + + private fun emitFileTypeMetric() { + currentOpenedFileTypes.forEach { + IdeTelemetry.editCodeFile(project = null, filenameExt = it) + } + flush() + scheduleNextMetricEvent() + } + + private fun flush() { + currentOpenedFileTypes.clear() + } + + companion object { + const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 + } +} diff --git a/plugins/core/src/main/resources/META-INF/plugin.xml b/plugins/core/src/main/resources/META-INF/plugin.xml index 10e35898377..49fe443a5dd 100644 --- a/plugins/core/src/main/resources/META-INF/plugin.xml +++ b/plugins/core/src/main/resources/META-INF/plugin.xml @@ -22,5 +22,6 @@ + From 20a098abecadf032dabdcb02d916a5fa4589b6e7 Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Wed, 4 Sep 2024 14:57:22 -0700 Subject: [PATCH 2/9] addressed feedback 1 --- .../telemetry/OpenedFileTypesMetrics.kt | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index 9af463d8a65..7cf04027070 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -4,12 +4,14 @@ package software.aws.toolkits.jetbrains.services.telemetry import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.fileEditor.FileEditorManagerListener import com.intellij.openapi.project.Project import com.intellij.openapi.startup.ProjectActivity import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Alarm +import kotlinx.coroutines.coroutineScope import software.aws.toolkits.telemetry.IdeTelemetry class OpenedFileTypesMetrics : ProjectActivity, Disposable { @@ -22,11 +24,10 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { } // add newly opened file extensions - project.messageBus.connect().subscribe( + project.messageBus.connect(this).subscribe( FileEditorManagerListener.FILE_EDITOR_MANAGER, object : FileEditorManagerListener { override fun fileOpened(source: FileEditorManager, file: VirtualFile) { - file.extension?.let { currentOpenedFileTypes.add(it) } } } @@ -41,18 +42,18 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { override fun dispose() {} private fun emitFileTypeMetric() { - currentOpenedFileTypes.forEach { - IdeTelemetry.editCodeFile(project = null, filenameExt = it) + ApplicationManager.getApplication().executeOnPooledThread{ + currentOpenedFileTypes.forEach { + IdeTelemetry.editCodeFile(project = null, filenameExt = it) + } + currentOpenedFileTypes.clear() + scheduleNextMetricEvent() } - flush() - scheduleNextMetricEvent() - } - private fun flush() { - currentOpenedFileTypes.clear() + } companion object { - const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 + const val INTERVAL_BETWEEN_METRICS = 60 * 60 * 1000 } } From 47214c4334d29775ed98aba1abd3805878bf9c9a Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Fri, 6 Sep 2024 15:37:26 -0700 Subject: [PATCH 3/9] added tests --- .../telemetry/OpenedFileTypesMetrics.kt | 32 ++- .../services/telemetry/TelemetryUtils.kt | 204 ++++++++++++++++++ .../telemetry/OpenedFileTypeMetricsTest.kt | 65 ++++++ 3 files changed, 291 insertions(+), 10 deletions(-) create mode 100644 plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt create mode 100644 plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index 7cf04027070..4a860b06928 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -11,7 +11,6 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.startup.ProjectActivity import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Alarm -import kotlinx.coroutines.coroutineScope import software.aws.toolkits.telemetry.IdeTelemetry class OpenedFileTypesMetrics : ProjectActivity, Disposable { @@ -20,7 +19,8 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { override suspend fun execute(project: Project) { // add already open file extensions FileEditorManager.getInstance(project).openFiles.forEach { - it.extension?.let { openFileExtension -> currentOpenedFileTypes.add(openFileExtension) } + val extension = it.extension ?: return@forEach + addToExistingTelemetryBatch(extension) } // add newly opened file extensions @@ -28,32 +28,44 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { FileEditorManagerListener.FILE_EDITOR_MANAGER, object : FileEditorManagerListener { override fun fileOpened(source: FileEditorManager, file: VirtualFile) { - file.extension?.let { currentOpenedFileTypes.add(it) } + val extension = file.extension ?: return + addToExistingTelemetryBatch(extension) } } ) scheduleNextMetricEvent() } - private fun scheduleNextMetricEvent() { + private fun addToExistingTelemetryBatch(fileExt: String) { + val extension = ".$fileExt" + if (extension in codeFileTypes) { + currentOpenedFileTypes.add(extension) + } + } + + fun scheduleNextMetricEvent() { alarm.addRequest(this::emitFileTypeMetric, INTERVAL_BETWEEN_METRICS) } override fun dispose() {} - private fun emitFileTypeMetric() { - ApplicationManager.getApplication().executeOnPooledThread{ + fun emitFileTypeMetric() { + ApplicationManager.getApplication().executeOnPooledThread { currentOpenedFileTypes.forEach { - IdeTelemetry.editCodeFile(project = null, filenameExt = it) + emitMetric(it) } currentOpenedFileTypes.clear() - scheduleNextMetricEvent() + if (!ApplicationManager.getApplication().isUnitTestMode) { + scheduleNextMetricEvent() + } } + } - + fun emitMetric(openFileExtension: String) { + IdeTelemetry.editCodeFile(project = null, filenameExt = openFileExtension) } companion object { - const val INTERVAL_BETWEEN_METRICS = 60 * 60 * 1000 + const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 } } diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt new file mode 100644 index 00000000000..6832d29f4f5 --- /dev/null +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt @@ -0,0 +1,204 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.telemetry + +val codeFileTypes = setOf( + ".abap", + ".ada", + ".adb", + ".ads", + ".apl", + ".asm", + ".awk", + ".b", + ".bas", + ".bash", + ".bat", + ".boo", + ".c", + ".cbl", + ".cc", + ".cfc", + ".cfm", + ".cjs", + ".class", + ".clj", + ".cljc", + ".cljs", + ".cls", + ".cmake", + ".cob", + ".cobra", + ".coffee", + ".cpp", + ".cpy", + ".cr", + ".cs", + ".css", + ".csx", + ".cxx", + ".d", + ".dart", + ".dfm", + ".dpr", + ".e", + ".el", + ".elc", + ".elm", + ".erl", + ".ex", + ".exs", + ".f", + ".f03", + ".f08", + ".f77", + ".f90", + ".f95", + ".flow", + ".for", + ".fs", + ".fsi", + ".fsx", + ".gd", + ".go", + ".gql", + ".graphql", + ".groovy", + ".gs", + ".gsp", + ".gst", + ".gsx", + ".gvy", + ".h", + ".hack", + ".hh", + ".hpp", + ".hrl", + ".hs", + ".htm", + ".html", + ".hy", + ".idl", + ".io", + ".jar", + ".java", + ".jl", + ".js", + ".json", + ".jsx", + ".kt", + ".kts", + ".lean", + ".lgt", + ".lhs", + ".lisp", + ".logtalk", + ".lsp", + ".lua", + ".m", + ".ma", + ".mak", + ".makefile", + ".md", + ".mjs", + ".ml", + ".mli", + ".mpl", + ".ms", + ".mu", + ".mv", + ".n", + ".nb", + ".nim", + ".nix", + ".oot", + ".oz", + ".pas", + ".pasm", + ".perl", + ".php", + ".phtml", + ".pike", + ".pir", + ".pl", + ".pm", + ".pmod", + ".pp", + ".pro", + ".prolog", + ".ps1", + ".psd1", + ".psm1", + ".purs", + ".py", + ".pyc", + ".pyo", + ".pyw", + ".qs", + ".r", + ".raku", + ".rakumod", + ".rakutest", + ".rb", + ".rbw", + ".rdata", + ".re", + ".red", + ".reds", + ".res", + ".rex", + ".rexx", + ".ring", + ".rkt", + ".rktl", + ".rlib", + ".rm", + ".rmd", + ".roff", + ".ron", + ".rs", + ".ruby", + ".s", + ".sas", + ".sb", + ".sb2", + ".sb3", + ".sc", + ".scala", + ".scd", + ".scm", + ".scss", + ".sh", + ".shen", + ".sig", + ".sml", + ".sol", + ".sql", + ".ss", + ".st", + ".sv", + ".swift", + ".t", + ".tcl", + ".tf", + ".trigger", + ".ts", + ".tsx", + ".tu", + ".v", + ".vala", + ".vapi", + ".vb", + ".vba", + ".vbx", + ".vhd", + ".vhdl", + ".vue", + ".x", + ".xc", + ".xi", + ".xml", + ".yaml", + ".zig", +) diff --git a/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt b/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt new file mode 100644 index 00000000000..13133f9fc6d --- /dev/null +++ b/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt @@ -0,0 +1,65 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.telemetry + +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.testFramework.LightVirtualFile +import com.intellij.testFramework.ProjectRule +import com.intellij.testFramework.runInEdtAndWait +import kotlinx.coroutines.runBlocking +import org.junit.Rule +import org.junit.Test +import org.mockito.kotlin.any +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.spy +import org.mockito.kotlin.stub +import org.mockito.kotlin.verify + +class OpenedFileTypeMetricsTest { + + @Rule + @JvmField + val projectRule = ProjectRule() + + @Test + fun `metrics are recorded for already opened file types`() { + val dummyFile = LightVirtualFile("dummy.kt") + runInEdtAndWait { + FileEditorManager.getInstance(projectRule.project).openFile(dummyFile) + } + + val openedFileTypeMetrics = spy(OpenedFileTypesMetrics()) + openedFileTypeMetrics.stub { + on { openedFileTypeMetrics.scheduleNextMetricEvent() }.doAnswer { + openedFileTypeMetrics.emitFileTypeMetric() + } + } + + runBlocking { + openedFileTypeMetrics.execute(projectRule.project) + } + verify(openedFileTypeMetrics).emitMetric(".kt") + } + + @Test + fun `duplicate metrics are not emitted`() { + val testFile = LightVirtualFile("test1.kt") + val testFile2 = LightVirtualFile("test2.kt") + runInEdtAndWait { + FileEditorManager.getInstance(projectRule.project).openFile(testFile) + FileEditorManager.getInstance(projectRule.project).openFile(testFile2) + } + val openedFileTypeMetrics = spy(OpenedFileTypesMetrics()) + openedFileTypeMetrics.stub { + on { openedFileTypeMetrics.scheduleNextMetricEvent() }.doAnswer { + openedFileTypeMetrics.emitFileTypeMetric() + } + } + + runBlocking { + openedFileTypeMetrics.execute(projectRule.project) + } + verify(openedFileTypeMetrics).emitMetric(any()) + } +} From 2bdf9824848eb47887bc9c28a9dc646355c85e9a Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Wed, 11 Sep 2024 14:34:08 -0700 Subject: [PATCH 4/9] Feedback 2 --- .../amazonq/FeatureDevSessionContext.kt | 3 +- .../jetbrains/services/amazonq/QConstants.kt | 201 --------- .../telemetry/OpenedFileTypesMetrics.kt | 24 +- .../services/telemetry/TelemetryUtils.kt | 394 +++++++++--------- .../telemetry/OpenedFileTypeMetricsTest.kt | 16 +- 5 files changed, 217 insertions(+), 421 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/FeatureDevSessionContext.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/FeatureDevSessionContext.kt index c1f86d45a82..aa0a64c7f4b 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/FeatureDevSessionContext.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/FeatureDevSessionContext.kt @@ -21,6 +21,7 @@ import software.aws.toolkits.core.utils.outputStream import software.aws.toolkits.core.utils.putNextEntry import software.aws.toolkits.jetbrains.core.coroutines.EDT import software.aws.toolkits.jetbrains.core.coroutines.getCoroutineBgContext +import software.aws.toolkits.jetbrains.services.telemetry.ALLOWED_CODE_EXTENSIONS import software.aws.toolkits.resources.AwsCoreBundle import software.aws.toolkits.telemetry.AmazonqTelemetry import java.io.File @@ -94,7 +95,7 @@ class FeatureDevSessionContext(val project: Project, val maxProjectSizeBytes: Lo if (file.isDirectory) return true val extension = file.extension ?: return false - return FeatureDevBundleConfig.ALLOWED_CODE_EXTENSIONS.contains(extension) + return ALLOWED_CODE_EXTENSIONS.contains(extension) } private fun ignoreFileByExtension(file: VirtualFile, scope: CoroutineScope): Boolean = with(scope) { diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QConstants.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QConstants.kt index 8d4f41fe5a8..3cc2bf81741 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QConstants.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/QConstants.kt @@ -7,204 +7,3 @@ object QConstants { const val Q_MARKETPLACE_URI = "https://aws.amazon.com/q/developer/" const val CODEWHISPERER_LOGIN_HELP_URI = "https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/auth-access.html" } - -// List from Stack Overflow 2023 survey: https://survey.stackoverflow.co/2023/#technology -object FeatureDevBundleConfig { - val ALLOWED_CODE_EXTENSIONS = setOf( - "abap", - "ada", - "adb", - "ads", - "apl", - "asm", - "awk", - "b", - "bas", - "bash", - "bat", - "boo", - "c", - "cbl", - "cc", - "cfc", - "cfm", - "cjs", - "clj", - "cljc", - "cljs", - "cls", - "cmake", - "cob", - "cobra", - "coffee", - "cpp", - "cpy", - "cr", - "cs", - "css", - "csx", - "cxx", - "d", - "dart", - "dfm", - "dpr", - "e", - "el", - "elm", - "erl", - "ex", - "exs", - "f", - "f03", - "f08", - "f77", - "f90", - "f95", - "flow", - "for", - "fs", - "fsi", - "fsx", - "gd", - "go", - "gql", - "graphql", - "groovy", - "gs", - "gsp", - "gst", - "gsx", - "gvy", - "h", - "hack", - "hh", - "hpp", - "hrl", - "hs", - "htm", - "html", - "hy", - "idl", - "io", - "jar", - "java", - "jl", - "js", - "json", - "jsx", - "kt", - "kts", - "lean", - "lgt", - "lhs", - "lisp", - "logtalk", - "lsp", - "lua", - "m", - "ma", - "mak", - "makefile", - "md", - "mjs", - "ml", - "mli", - "mpl", - "ms", - "mu", - "mv", - "n", - "nb", - "nim", - "nix", - "oot", - "oz", - "pas", - "pasm", - "perl", - "php", - "phtml", - "pike", - "pir", - "pl", - "pm", - "pmod", - "pp", - "pro", - "prolog", - "ps1", - "psd1", - "psm1", - "purs", - "py", - "pyw", - "qs", - "r", - "raku", - "rakumod", - "rakutest", - "rb", - "rbw", - "rdata", - "re", - "red", - "reds", - "res", - "rex", - "rexx", - "ring", - "rkt", - "rktl", - "rlib", - "rm", - "rmd", - "roff", - "ron", - "rs", - "ruby", - "s", - "sas", - "sb", - "sb2", - "sb3", - "sc", - "scala", - "scd", - "scm", - "scss", - "sass", - "sh", - "shen", - "sig", - "sml", - "sol", - "sql", - "ss", - "st", - "sv", - "swift", - "t", - "tcl", - "tf", - "trigger", - "ts", - "tsx", - "tu", - "v", - "vala", - "vapi", - "vb", - "vba", - "vbx", - "vhd", - "vhdl", - "vue", - "x", - "xc", - "xi", - "xml", - "yaml", - "yml", - "zig" - ) -} diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index 4a860b06928..b177c3b6b58 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -11,6 +11,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.startup.ProjectActivity import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Alarm +import software.aws.toolkits.jetbrains.utils.notifyInfo import software.aws.toolkits.telemetry.IdeTelemetry class OpenedFileTypesMetrics : ProjectActivity, Disposable { @@ -37,9 +38,10 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { } private fun addToExistingTelemetryBatch(fileExt: String) { - val extension = ".$fileExt" - if (extension in codeFileTypes) { - currentOpenedFileTypes.add(extension) + // val extension = ".$fileExt" + notifyInfo("ex") + if (fileExt in ALLOWED_CODE_EXTENSIONS) { + currentOpenedFileTypes.add(fileExt) } } @@ -50,14 +52,12 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { override fun dispose() {} fun emitFileTypeMetric() { - ApplicationManager.getApplication().executeOnPooledThread { - currentOpenedFileTypes.forEach { - emitMetric(it) - } - currentOpenedFileTypes.clear() - if (!ApplicationManager.getApplication().isUnitTestMode) { - scheduleNextMetricEvent() - } + currentOpenedFileTypes.forEach { + emitMetric(it) + } + currentOpenedFileTypes.clear() + if (!ApplicationManager.getApplication().isUnitTestMode) { + scheduleNextMetricEvent() } } @@ -66,6 +66,6 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { } companion object { - const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 + private const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 } } diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt index 6832d29f4f5..32e5164eefe 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/TelemetryUtils.kt @@ -3,202 +3,200 @@ package software.aws.toolkits.jetbrains.services.telemetry -val codeFileTypes = setOf( - ".abap", - ".ada", - ".adb", - ".ads", - ".apl", - ".asm", - ".awk", - ".b", - ".bas", - ".bash", - ".bat", - ".boo", - ".c", - ".cbl", - ".cc", - ".cfc", - ".cfm", - ".cjs", - ".class", - ".clj", - ".cljc", - ".cljs", - ".cls", - ".cmake", - ".cob", - ".cobra", - ".coffee", - ".cpp", - ".cpy", - ".cr", - ".cs", - ".css", - ".csx", - ".cxx", - ".d", - ".dart", - ".dfm", - ".dpr", - ".e", - ".el", - ".elc", - ".elm", - ".erl", - ".ex", - ".exs", - ".f", - ".f03", - ".f08", - ".f77", - ".f90", - ".f95", - ".flow", - ".for", - ".fs", - ".fsi", - ".fsx", - ".gd", - ".go", - ".gql", - ".graphql", - ".groovy", - ".gs", - ".gsp", - ".gst", - ".gsx", - ".gvy", - ".h", - ".hack", - ".hh", - ".hpp", - ".hrl", - ".hs", - ".htm", - ".html", - ".hy", - ".idl", - ".io", - ".jar", - ".java", - ".jl", - ".js", - ".json", - ".jsx", - ".kt", - ".kts", - ".lean", - ".lgt", - ".lhs", - ".lisp", - ".logtalk", - ".lsp", - ".lua", - ".m", - ".ma", - ".mak", - ".makefile", - ".md", - ".mjs", - ".ml", - ".mli", - ".mpl", - ".ms", - ".mu", - ".mv", - ".n", - ".nb", - ".nim", - ".nix", - ".oot", - ".oz", - ".pas", - ".pasm", - ".perl", - ".php", - ".phtml", - ".pike", - ".pir", - ".pl", - ".pm", - ".pmod", - ".pp", - ".pro", - ".prolog", - ".ps1", - ".psd1", - ".psm1", - ".purs", - ".py", - ".pyc", - ".pyo", - ".pyw", - ".qs", - ".r", - ".raku", - ".rakumod", - ".rakutest", - ".rb", - ".rbw", - ".rdata", - ".re", - ".red", - ".reds", - ".res", - ".rex", - ".rexx", - ".ring", - ".rkt", - ".rktl", - ".rlib", - ".rm", - ".rmd", - ".roff", - ".ron", - ".rs", - ".ruby", - ".s", - ".sas", - ".sb", - ".sb2", - ".sb3", - ".sc", - ".scala", - ".scd", - ".scm", - ".scss", - ".sh", - ".shen", - ".sig", - ".sml", - ".sol", - ".sql", - ".ss", - ".st", - ".sv", - ".swift", - ".t", - ".tcl", - ".tf", - ".trigger", - ".ts", - ".tsx", - ".tu", - ".v", - ".vala", - ".vapi", - ".vb", - ".vba", - ".vbx", - ".vhd", - ".vhdl", - ".vue", - ".x", - ".xc", - ".xi", - ".xml", - ".yaml", - ".zig", +val ALLOWED_CODE_EXTENSIONS = setOf( + "abap", + "ada", + "adb", + "ads", + "apl", + "asm", + "awk", + "b", + "bas", + "bash", + "bat", + "boo", + "c", + "cbl", + "cc", + "cfc", + "cfm", + "cjs", + "clj", + "cljc", + "cljs", + "cls", + "cmake", + "cob", + "cobra", + "coffee", + "cpp", + "cpy", + "cr", + "cs", + "css", + "csx", + "cxx", + "d", + "dart", + "dfm", + "dpr", + "e", + "el", + "elm", + "erl", + "ex", + "exs", + "f", + "f03", + "f08", + "f77", + "f90", + "f95", + "flow", + "for", + "fs", + "fsi", + "fsx", + "gd", + "go", + "gql", + "graphql", + "groovy", + "gs", + "gsp", + "gst", + "gsx", + "gvy", + "h", + "hack", + "hh", + "hpp", + "hrl", + "hs", + "htm", + "html", + "hy", + "idl", + "io", + "jar", + "java", + "jl", + "js", + "json", + "jsx", + "kt", + "kts", + "lean", + "lgt", + "lhs", + "lisp", + "logtalk", + "lsp", + "lua", + "m", + "ma", + "mak", + "makefile", + "md", + "mjs", + "ml", + "mli", + "mpl", + "ms", + "mu", + "mv", + "n", + "nb", + "nim", + "nix", + "oot", + "oz", + "pas", + "pasm", + "perl", + "php", + "phtml", + "pike", + "pir", + "pl", + "pm", + "pmod", + "pp", + "pro", + "prolog", + "ps1", + "psd1", + "psm1", + "purs", + "py", + "pyw", + "qs", + "r", + "raku", + "rakumod", + "rakutest", + "rb", + "rbw", + "rdata", + "re", + "red", + "reds", + "res", + "rex", + "rexx", + "ring", + "rkt", + "rktl", + "rlib", + "rm", + "rmd", + "roff", + "ron", + "rs", + "ruby", + "s", + "sas", + "sb", + "sb2", + "sb3", + "sc", + "scala", + "scd", + "scm", + "scss", + "sass", + "sh", + "shen", + "sig", + "sml", + "sol", + "sql", + "ss", + "st", + "sv", + "swift", + "t", + "tcl", + "tf", + "trigger", + "ts", + "tsx", + "tu", + "v", + "vala", + "vapi", + "vb", + "vba", + "vbx", + "vhd", + "vhdl", + "vue", + "x", + "xc", + "xi", + "xml", + "yaml", + "yml", + "zig" ) diff --git a/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt b/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt index 13133f9fc6d..a0466964df5 100644 --- a/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt +++ b/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt @@ -7,7 +7,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.testFramework.LightVirtualFile import com.intellij.testFramework.ProjectRule import com.intellij.testFramework.runInEdtAndWait -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import org.mockito.kotlin.any @@ -23,7 +23,7 @@ class OpenedFileTypeMetricsTest { val projectRule = ProjectRule() @Test - fun `metrics are recorded for already opened file types`() { + fun `metrics are recorded for already opened file types`() = runTest { val dummyFile = LightVirtualFile("dummy.kt") runInEdtAndWait { FileEditorManager.getInstance(projectRule.project).openFile(dummyFile) @@ -36,14 +36,13 @@ class OpenedFileTypeMetricsTest { } } - runBlocking { - openedFileTypeMetrics.execute(projectRule.project) - } + openedFileTypeMetrics.execute(projectRule.project) + verify(openedFileTypeMetrics).emitMetric(".kt") } @Test - fun `duplicate metrics are not emitted`() { + fun `duplicate metrics are not emitted`() = runTest { val testFile = LightVirtualFile("test1.kt") val testFile2 = LightVirtualFile("test2.kt") runInEdtAndWait { @@ -57,9 +56,8 @@ class OpenedFileTypeMetricsTest { } } - runBlocking { - openedFileTypeMetrics.execute(projectRule.project) - } + openedFileTypeMetrics.execute(projectRule.project) + verify(openedFileTypeMetrics).emitMetric(any()) } } From 483b14fe3d11390e1e847921ed0eec6a7b612130 Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Wed, 11 Sep 2024 15:05:56 -0700 Subject: [PATCH 5/9] feedback --- .../jetbrains/services/telemetry/OpenedFileTypesMetrics.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index b177c3b6b58..707bdf82e99 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.fileEditor.FileEditorManagerListener import com.intellij.openapi.project.Project import com.intellij.openapi.startup.ProjectActivity +import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Alarm import software.aws.toolkits.jetbrains.utils.notifyInfo @@ -38,8 +39,6 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { } private fun addToExistingTelemetryBatch(fileExt: String) { - // val extension = ".$fileExt" - notifyInfo("ex") if (fileExt in ALLOWED_CODE_EXTENSIONS) { currentOpenedFileTypes.add(fileExt) } From 61026b4ea6c87c3d3e2f9b7845d617e1d79a9714 Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Wed, 11 Sep 2024 22:53:45 -0700 Subject: [PATCH 6/9] fixed runtime disposer exception --- .../telemetry/OpenedFileTypesMetrics.kt | 59 +++++++--------- .../telemetry/OpenedFileTypeMetricsTest.kt | 67 ++++++------------- .../src/main/resources/META-INF/plugin.xml | 5 +- 3 files changed, 50 insertions(+), 81 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index 707bdf82e99..e4b7d21e996 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -5,51 +5,36 @@ package software.aws.toolkits.jetbrains.services.telemetry import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.service import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.fileEditor.FileEditorManagerListener -import com.intellij.openapi.project.Project -import com.intellij.openapi.startup.ProjectActivity -import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Alarm -import software.aws.toolkits.jetbrains.utils.notifyInfo +import org.jetbrains.annotations.TestOnly import software.aws.toolkits.telemetry.IdeTelemetry -class OpenedFileTypesMetrics : ProjectActivity, Disposable { +class OpenedFileTypesMetricsListener : FileEditorManagerListener { + override fun fileOpened(source: FileEditorManager, file: VirtualFile) { + val extension = file.extension ?: return + source.project.service().addToExistingTelemetryBatch(extension) + } +} + +@Service(Service.Level.PROJECT) +class OpenedFileTypesMetricsService : Disposable { private val currentOpenedFileTypes = mutableSetOf() private val alarm = Alarm(Alarm.ThreadToUse.POOLED_THREAD, this) - override suspend fun execute(project: Project) { - // add already open file extensions - FileEditorManager.getInstance(project).openFiles.forEach { - val extension = it.extension ?: return@forEach - addToExistingTelemetryBatch(extension) - } + override fun dispose() {} - // add newly opened file extensions - project.messageBus.connect(this).subscribe( - FileEditorManagerListener.FILE_EDITOR_MANAGER, - object : FileEditorManagerListener { - override fun fileOpened(source: FileEditorManager, file: VirtualFile) { - val extension = file.extension ?: return - addToExistingTelemetryBatch(extension) - } - } - ) + init { scheduleNextMetricEvent() } - private fun addToExistingTelemetryBatch(fileExt: String) { - if (fileExt in ALLOWED_CODE_EXTENSIONS) { - currentOpenedFileTypes.add(fileExt) - } - } - - fun scheduleNextMetricEvent() { + private fun scheduleNextMetricEvent() { alarm.addRequest(this::emitFileTypeMetric, INTERVAL_BETWEEN_METRICS) } - override fun dispose() {} - fun emitFileTypeMetric() { currentOpenedFileTypes.forEach { emitMetric(it) @@ -60,11 +45,19 @@ class OpenedFileTypesMetrics : ProjectActivity, Disposable { } } - fun emitMetric(openFileExtension: String) { - IdeTelemetry.editCodeFile(project = null, filenameExt = openFileExtension) + @TestOnly + fun getOpenedFileTypes(): Set = currentOpenedFileTypes + + fun addToExistingTelemetryBatch(fileExt: String) { + if (fileExt in ALLOWED_CODE_EXTENSIONS) { + currentOpenedFileTypes.add(fileExt) + } } + private fun emitMetric(openFileExtension: String) = + IdeTelemetry.editCodeFile(project = null, filenameExt = openFileExtension) + companion object { - private const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 + const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 } } diff --git a/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt b/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt index a0466964df5..21aa8bd481c 100644 --- a/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt +++ b/plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypeMetricsTest.kt @@ -3,61 +3,34 @@ package software.aws.toolkits.jetbrains.services.telemetry -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.testFramework.LightVirtualFile -import com.intellij.testFramework.ProjectRule -import com.intellij.testFramework.runInEdtAndWait -import kotlinx.coroutines.test.runTest -import org.junit.Rule +import org.junit.After +import org.junit.Before import org.junit.Test -import org.mockito.kotlin.any -import org.mockito.kotlin.doAnswer -import org.mockito.kotlin.spy -import org.mockito.kotlin.stub -import org.mockito.kotlin.verify +import org.mockito.kotlin.times class OpenedFileTypeMetricsTest { - @Rule - @JvmField - val projectRule = ProjectRule() + private lateinit var service: OpenedFileTypesMetricsService + + @Before + fun setup() { + service = OpenedFileTypesMetricsService() + } + + @After + fun teardown() { + service.dispose() + } @Test - fun `metrics are recorded for already opened file types`() = runTest { - val dummyFile = LightVirtualFile("dummy.kt") - runInEdtAndWait { - FileEditorManager.getInstance(projectRule.project).openFile(dummyFile) - } - - val openedFileTypeMetrics = spy(OpenedFileTypesMetrics()) - openedFileTypeMetrics.stub { - on { openedFileTypeMetrics.scheduleNextMetricEvent() }.doAnswer { - openedFileTypeMetrics.emitFileTypeMetric() - } - } - - openedFileTypeMetrics.execute(projectRule.project) - - verify(openedFileTypeMetrics).emitMetric(".kt") + fun `test addToExistingTelemetryBatch with allowed extension`() { + service.addToExistingTelemetryBatch("kt") + assert(service.getOpenedFileTypes().contains("kt")) } @Test - fun `duplicate metrics are not emitted`() = runTest { - val testFile = LightVirtualFile("test1.kt") - val testFile2 = LightVirtualFile("test2.kt") - runInEdtAndWait { - FileEditorManager.getInstance(projectRule.project).openFile(testFile) - FileEditorManager.getInstance(projectRule.project).openFile(testFile2) - } - val openedFileTypeMetrics = spy(OpenedFileTypesMetrics()) - openedFileTypeMetrics.stub { - on { openedFileTypeMetrics.scheduleNextMetricEvent() }.doAnswer { - openedFileTypeMetrics.emitFileTypeMetric() - } - } - - openedFileTypeMetrics.execute(projectRule.project) - - verify(openedFileTypeMetrics).emitMetric(any()) + fun `test addToExistingTelemetryBatch with disallowed extension`() { + service.addToExistingTelemetryBatch("txt") + assert(service.getOpenedFileTypes().isEmpty()) } } diff --git a/plugins/core/src/main/resources/META-INF/plugin.xml b/plugins/core/src/main/resources/META-INF/plugin.xml index 49fe443a5dd..c26df8916dc 100644 --- a/plugins/core/src/main/resources/META-INF/plugin.xml +++ b/plugins/core/src/main/resources/META-INF/plugin.xml @@ -22,6 +22,9 @@ - + + + + From aacbab50f9a7264c13807511defee299c7f864b1 Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Wed, 11 Sep 2024 22:55:22 -0700 Subject: [PATCH 7/9] removed extra code --- .../jetbrains/services/telemetry/OpenedFileTypesMetrics.kt | 2 +- plugins/core/src/main/resources/META-INF/plugin.xml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index e4b7d21e996..1a43267a4cc 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -58,6 +58,6 @@ class OpenedFileTypesMetricsService : Disposable { IdeTelemetry.editCodeFile(project = null, filenameExt = openFileExtension) companion object { - const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 + private const val INTERVAL_BETWEEN_METRICS = 30 * 60 * 1000 } } diff --git a/plugins/core/src/main/resources/META-INF/plugin.xml b/plugins/core/src/main/resources/META-INF/plugin.xml index c26df8916dc..dbc7e6b3972 100644 --- a/plugins/core/src/main/resources/META-INF/plugin.xml +++ b/plugins/core/src/main/resources/META-INF/plugin.xml @@ -22,7 +22,6 @@ - From be64a947afb6d5d0e5d5be1d19e4d1da6360012d Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Fri, 13 Sep 2024 14:07:05 -0700 Subject: [PATCH 8/9] feedback 3 --- .../telemetry/OpenedFileTypesMetrics.kt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index 1a43267a4cc..3d23a0a10c4 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -11,7 +11,10 @@ import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.fileEditor.FileEditorManagerListener import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Alarm +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import org.jetbrains.annotations.TestOnly +import software.aws.toolkits.jetbrains.core.coroutines.getCoroutineBgContext import software.aws.toolkits.telemetry.IdeTelemetry class OpenedFileTypesMetricsListener : FileEditorManagerListener { @@ -36,12 +39,14 @@ class OpenedFileTypesMetricsService : Disposable { } fun emitFileTypeMetric() { - currentOpenedFileTypes.forEach { - emitMetric(it) - } - currentOpenedFileTypes.clear() - if (!ApplicationManager.getApplication().isUnitTestMode) { - scheduleNextMetricEvent() + CoroutineScope(getCoroutineBgContext()).launch { + currentOpenedFileTypes.forEach { + emitMetric(it) + } + currentOpenedFileTypes.clear() + if (!ApplicationManager.getApplication().isUnitTestMode) { + scheduleNextMetricEvent() + } } } From c686f1d442b8c791466e64153a866390e90d0621 Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Mon, 16 Sep 2024 15:26:45 -0700 Subject: [PATCH 9/9] feedback 4 --- .../telemetry/OpenedFileTypesMetrics.kt | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt index 3d23a0a10c4..43065a43a5a 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/services/telemetry/OpenedFileTypesMetrics.kt @@ -11,10 +11,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.fileEditor.FileEditorManagerListener import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Alarm -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch import org.jetbrains.annotations.TestOnly -import software.aws.toolkits.jetbrains.core.coroutines.getCoroutineBgContext import software.aws.toolkits.telemetry.IdeTelemetry class OpenedFileTypesMetricsListener : FileEditorManagerListener { @@ -38,21 +35,21 @@ class OpenedFileTypesMetricsService : Disposable { alarm.addRequest(this::emitFileTypeMetric, INTERVAL_BETWEEN_METRICS) } + @Synchronized fun emitFileTypeMetric() { - CoroutineScope(getCoroutineBgContext()).launch { - currentOpenedFileTypes.forEach { - emitMetric(it) - } - currentOpenedFileTypes.clear() - if (!ApplicationManager.getApplication().isUnitTestMode) { - scheduleNextMetricEvent() - } + currentOpenedFileTypes.forEach { + emitMetric(it) + } + currentOpenedFileTypes.clear() + if (!ApplicationManager.getApplication().isUnitTestMode) { + scheduleNextMetricEvent() } } @TestOnly fun getOpenedFileTypes(): Set = currentOpenedFileTypes + @Synchronized fun addToExistingTelemetryBatch(fileExt: String) { if (fileExt in ALLOWED_CODE_EXTENSIONS) { currentOpenedFileTypes.add(fileExt)