diff --git a/plugins/filePrediction/resources/META-INF/plugin.xml b/plugins/filePrediction/resources/META-INF/plugin.xml
index da981e617a2e..1c046b9f65b4 100644
--- a/plugins/filePrediction/resources/META-INF/plugin.xml
+++ b/plugins/filePrediction/resources/META-INF/plugin.xml
@@ -23,6 +23,7 @@
+
diff --git a/plugins/filePrediction/src/com/intellij/filePrediction/FileNavigationLogger.kt b/plugins/filePrediction/src/com/intellij/filePrediction/FileNavigationLogger.kt
index 7e504976cc63..7611966817fc 100644
--- a/plugins/filePrediction/src/com/intellij/filePrediction/FileNavigationLogger.kt
+++ b/plugins/filePrediction/src/com/intellij/filePrediction/FileNavigationLogger.kt
@@ -9,12 +9,16 @@ internal object FileNavigationLogger {
fun logEvent(project: Project,
event: String,
+ sessionId: Int,
features: FileFeaturesComputationResult,
filePath: String,
+ prevFilePath: String?,
refsComputation: Long,
probability: Double? = null) {
val data = FeatureUsageData().
+ addData("session_id", sessionId).
addAnonymizedPath(filePath).
+ addAnonymizedValue("prev_file_path", prevFilePath).
addData("refs_computation", refsComputation).
addData("features_computation", features.duration)
diff --git a/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionEditorManagerListener.kt b/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionEditorManagerListener.kt
index 74f612f1e0c2..bf5fe9b12588 100644
--- a/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionEditorManagerListener.kt
+++ b/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionEditorManagerListener.kt
@@ -10,7 +10,7 @@ internal class FilePredictionEditorManagerListener : FileEditorManagerListener {
override fun selectionChanged(event: FileEditorManagerEvent) {
val newFile = event.newFile ?: return
if (ApplicationManager.getApplication().isEAP && Registry.get("filePrediction.calculate.features").asBoolean()) {
- FilePredictionHandler.onFileOpened(event.manager.project, newFile, event.oldFile)
+ FilePredictionHandler.getInstance()?.onFileOpened(event.manager.project, newFile, event.oldFile)
}
}
}
\ No newline at end of file
diff --git a/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionHandler.kt b/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionHandler.kt
index fc8971cb0383..2a5f2eb565ee 100644
--- a/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionHandler.kt
+++ b/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionHandler.kt
@@ -2,18 +2,25 @@ package com.intellij.filePrediction
import com.intellij.filePrediction.history.FilePredictionHistory
import com.intellij.filePrediction.predictor.FileUsagePredictor
+import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.progress.util.BackgroundTaskUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.impl.ProjectManagerImpl
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.concurrency.NonUrgentExecutor
-object FilePredictionHandler {
- private const val CALCULATE_OPEN_FILE_PROBABILITY: Double = 0.5
+class FilePredictionHandler {
+ companion object {
+ private const val CALCULATE_OPEN_FILE_PROBABILITY: Double = 0.5
+ private const val CALCULATE_CANDIDATE_PROBABILITY: Double = 0.1
+
+ fun getInstance(): FilePredictionHandler? = ServiceManager.getService(FilePredictionHandler::class.java)
+ }
- private const val CALCULATE_CANDIDATE_PROBABILITY: Double = 0.1
private val predictor: FileUsagePredictor = FileUsagePredictor(30, 5, 10)
+ private var session: FilePredictionSessionHolder = FilePredictionSessionHolder()
+
fun onFileOpened(project: Project, newFile: VirtualFile, prevFile: VirtualFile?) {
if (ProjectManagerImpl.isLight(project)) {
return
@@ -21,21 +28,26 @@ object FilePredictionHandler {
NonUrgentExecutor.getInstance().execute {
BackgroundTaskUtil.runUnderDisposeAwareIndicator(project, Runnable {
- if (Math.random() < CALCULATE_OPEN_FILE_PROBABILITY) {
- logOpenedFile(project, newFile, prevFile)
+ val previousSession = session.getSession()
+ if (previousSession != null && previousSession.shouldLog(CALCULATE_OPEN_FILE_PROBABILITY)) {
+ logOpenedFile(project, previousSession.id, newFile, prevFile)
}
- if (Math.random() < CALCULATE_CANDIDATE_PROBABILITY) {
- predictor.predictNextFile(project, newFile)
+ val newSession = session.newSession()
+ if (newSession != null && newSession.shouldLog(CALCULATE_CANDIDATE_PROBABILITY)) {
+ predictor.predictNextFile(project, newSession.id, newFile)
}
FilePredictionHistory.getInstance(project).onFileOpened(newFile.url)
})
}
}
- private fun logOpenedFile(project: Project, newFile: VirtualFile, prevFile: VirtualFile?) {
+ private fun logOpenedFile(project: Project,
+ sessionId: Int,
+ newFile: VirtualFile,
+ prevFile: VirtualFile?) {
val result = FilePredictionFeaturesHelper.calculateExternalReferences(project, prevFile)
val features = FilePredictionFeaturesHelper.calculateFileFeatures(project, newFile, result.value, prevFile)
- FileNavigationLogger.logEvent(project, "file.opened", features, newFile.path, result.duration)
+ FileNavigationLogger.logEvent(project, "file.opened", sessionId, features, newFile.path, prevFile?.path, result.duration)
}
}
\ No newline at end of file
diff --git a/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionSession.kt b/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionSession.kt
new file mode 100644
index 000000000000..ab8c89ef75ac
--- /dev/null
+++ b/plugins/filePrediction/src/com/intellij/filePrediction/FilePredictionSession.kt
@@ -0,0 +1,27 @@
+package com.intellij.filePrediction
+
+import java.util.concurrent.atomic.AtomicInteger
+
+private val counter = AtomicInteger(0)
+
+internal class FilePredictionSessionHolder {
+ private var session: FilePredictionSession? = null
+
+ @Synchronized
+ fun getSession(): FilePredictionSession? = session
+
+ @Synchronized
+ fun newSession(): FilePredictionSession? {
+ session = FilePredictionSession()
+ return session
+ }
+}
+
+internal class FilePredictionSession {
+ val id = counter.incrementAndGet()
+ private val loggingProbability = Math.random()
+
+ fun shouldLog(threshold: Double): Boolean {
+ return loggingProbability < threshold
+ }
+}
\ No newline at end of file
diff --git a/plugins/filePrediction/src/com/intellij/filePrediction/predictor/FileUsagePredictor.kt b/plugins/filePrediction/src/com/intellij/filePrediction/predictor/FileUsagePredictor.kt
index 2755b1d69b59..06110bf4a9e3 100644
--- a/plugins/filePrediction/src/com/intellij/filePrediction/predictor/FileUsagePredictor.kt
+++ b/plugins/filePrediction/src/com/intellij/filePrediction/predictor/FileUsagePredictor.kt
@@ -14,27 +14,28 @@ import com.intellij.openapi.vfs.VirtualFile
internal class FileUsagePredictor(private val candidatesLimit: Int,
private val logTopLimit: Int,
private val logTotalLimit: Int) {
- fun predictNextFile(project: Project, file: VirtualFile) {
+ fun predictNextFile(project: Project, sessionId: Int, file: VirtualFile) {
val result = FilePredictionFeaturesHelper.calculateExternalReferences(project, file)
val model = getFilePredictionModel()
if (model != null) {
- predictAndLogCandidates(project, model, file, result)
+ predictAndLogCandidates(project, sessionId, model, file, result)
}
else {
- logCandidates(project, file, result)
+ logCandidates(project, sessionId, file, result)
}
}
- private fun logCandidates(project: Project, file: VirtualFile, refs: FileReferencesComputationResult) {
+ private fun logCandidates(project: Project, sessionId: Int, file: VirtualFile, refs: FileReferencesComputationResult) {
val candidateFiles = provideCandidates(project, file, refs.value.references, logTotalLimit)
for (candidate in candidateFiles) {
val features = FilePredictionFeaturesHelper.calculateFileFeatures(project, candidate, refs.value, file)
- FileNavigationLogger.logEvent(project, "candidate.calculated", features, candidate.path, refs.duration)
+ FileNavigationLogger.logEvent(project, "candidate.calculated", sessionId, features, candidate.path, file.path, refs.duration)
}
}
private fun predictAndLogCandidates(project: Project,
+ sessionId: Int,
model: FilePredictionModel,
file: VirtualFile,
refs: FileReferencesComputationResult) {
@@ -47,25 +48,35 @@ internal class FileUsagePredictor(private val candidatesLimit: Int,
}
candidates.sortByDescending { it.probability }
- logCandidatesWithProbability(project, candidates, refs.duration)
+ logCandidatesWithProbability(project, sessionId, file.path, candidates, refs.duration)
}
- private fun logCandidatesWithProbability(project: Project, candidates: MutableList, refsComputation: Long) {
+ private fun logCandidatesWithProbability(project: Project,
+ sessionId: Int,
+ prevPath: String?,
+ candidates: MutableList,
+ refsComputation: Long) {
val head = candidates.take(logTopLimit)
- logCalculatedCandidates(project, head, refsComputation)
+ logCalculatedCandidates(project, sessionId, prevPath, head, refsComputation)
if (candidates.size > logTopLimit) {
val tail = candidates.subList(logTopLimit, candidates.size)
val randomToLog = tail.shuffled().take(logTotalLimit - logTopLimit)
- logCalculatedCandidates(project, randomToLog, refsComputation)
+ logCalculatedCandidates(project, sessionId, prevPath, randomToLog, refsComputation)
}
}
- private fun logCalculatedCandidates(project: Project, candidates: Collection, refsComputation: Long) {
+ private fun logCalculatedCandidates(project: Project,
+ sessionId: Int,
+ prevPath:String?,
+ candidates: Collection,
+ refsComputation: Long) {
for (candidate in candidates) {
val probability = candidate.probability
val features = candidate.features
- FileNavigationLogger.logEvent(project, "candidate.calculated", features, candidate.path, refsComputation, probability)
+ FileNavigationLogger.logEvent(
+ project, "candidate.calculated", sessionId, features, candidate.path, prevPath, refsComputation, probability
+ )
}
}
}
diff --git a/plugins/filePrediction/test/com/intellij/filePrediction/predictor/FileUsagePredictorLoggerTest.kt b/plugins/filePrediction/test/com/intellij/filePrediction/predictor/FileUsagePredictorLoggerTest.kt
index f5381371b642..27e43a2e5442 100644
--- a/plugins/filePrediction/test/com/intellij/filePrediction/predictor/FileUsagePredictorLoggerTest.kt
+++ b/plugins/filePrediction/test/com/intellij/filePrediction/predictor/FileUsagePredictorLoggerTest.kt
@@ -29,7 +29,7 @@ class FileUsagePredictorLoggerTest : CodeInsightFixtureTestCase