Skip to content

Commit

Permalink
refactor: move report Analytics to AnalyticsScanListener
Browse files Browse the repository at this point in the history
  • Loading branch information
bastiandoetsch committed Nov 8, 2023
1 parent e627510 commit cfaac31
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 49 deletions.
3 changes: 2 additions & 1 deletion src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import snyk.iac.IacBulkFileListener
import snyk.oss.OssBulkFileListener
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.Date
import java.util.*

private val LOG = logger<SnykPostStartupActivity>()

Expand Down Expand Up @@ -67,6 +67,7 @@ class SnykPostStartupActivity : ProjectActivity {
if (!ApplicationManager.getApplication().isUnitTestMode) {
getSnykTaskQueueService(project)?.downloadLatestRelease()
getSnykTaskQueueService(project)?.initializeLanguageServer()
getAnalyticsScanListener(project)?.initScanListener()
}

val feedbackRequestShownMoreThenTwoWeeksAgo =
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/io/snyk/plugin/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import com.intellij.openapi.options.ShowSettingsUtil
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.wm.ToolWindow
Expand All @@ -24,6 +23,7 @@ import com.intellij.psi.PsiManager
import com.intellij.util.Alarm
import com.intellij.util.FileContentUtil
import com.intellij.util.messages.Topic
import io.snyk.plugin.analytics.AnalyticsScanListener
import io.snyk.plugin.net.ClientException
import io.snyk.plugin.services.SnykAnalyticsService
import io.snyk.plugin.services.SnykApiService
Expand Down Expand Up @@ -55,7 +55,6 @@ import snyk.oss.OssTextRangeFinder
import snyk.whoami.WhoamiService
import java.io.File
import java.net.URI
import java.net.URL
import java.nio.file.Path
import java.security.KeyStore
import java.util.Objects.nonNull
Expand All @@ -81,6 +80,7 @@ fun getSnykTaskQueueService(project: Project): SnykTaskQueueService? = project.s
fun getSnykToolWindowPanel(project: Project): SnykToolWindowPanel? = project.serviceIfNotDisposed()

fun getSnykCachedResults(project: Project): SnykCachedResults? = project.serviceIfNotDisposed()
fun getAnalyticsScanListener(project: Project): AnalyticsScanListener? = project.serviceIfNotDisposed()

fun getContainerService(project: Project): ContainerService? = project.serviceIfNotDisposed()

Expand Down
127 changes: 127 additions & 0 deletions src/main/kotlin/io/snyk/plugin/analytics/AnalyticsScanListener.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package io.snyk.plugin.analytics

import com.intellij.openapi.application.ApplicationInfo
import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project
import io.snyk.plugin.events.SnykScanListener
import io.snyk.plugin.getSnykTaskQueueService
import io.snyk.plugin.pluginSettings
import io.snyk.plugin.snykcode.SnykCodeResults
import org.apache.commons.lang.SystemUtils
import snyk.common.SnykError
import snyk.common.lsp.commands.ScanDoneEvent
import snyk.container.ContainerResult
import snyk.iac.IacResult
import snyk.oss.OssResult
import snyk.pluginInfo

@Service
class AnalyticsScanListener(val project: Project) {
fun initScanListener() = project.messageBus.connect().subscribe(
SnykScanListener.SNYK_SCAN_TOPIC,
object : SnykScanListener {
var start: Long = 0

private fun getScanDoneEvent(
duration: Long, product: String, critical: Int, high: Int, medium: Int, low: Int
): ScanDoneEvent {
return ScanDoneEvent(
ScanDoneEvent.Data(
type = "analytics",
attributes = ScanDoneEvent.Attributes(
deviceId = pluginSettings().userAnonymousId,
application = ApplicationInfo.getInstance().fullApplicationName,
applicationVersion = ApplicationInfo.getInstance().fullVersion,
os = SystemUtils.OS_NAME,
arch = SystemUtils.OS_ARCH,
integrationName = pluginInfo.integrationName,
integrationVersion = pluginInfo.integrationVersion,
integrationEnvironment = pluginInfo.integrationEnvironment,
integrationEnvironmentVersion = pluginInfo.integrationEnvironmentVersion,
eventType = "Scan done",
status = "Succeeded",
scanType = product,
uniqueIssueCount = ScanDoneEvent.UniqueIssueCount(
critical = critical,
high = high,
medium = medium,
low = low
),
durationMs = "$duration",
)
)
)
}

override fun scanningStarted() {
start = System.currentTimeMillis()
}

override fun scanningOssFinished(ossResult: OssResult) {
val scanDoneEvent = getScanDoneEvent(
System.currentTimeMillis() - start,
"Snyk Open Source",
ossResult.criticalSeveritiesCount(),
ossResult.highSeveritiesCount(),
ossResult.mediumSeveritiesCount(),
ossResult.lowSeveritiesCount()
)
getSnykTaskQueueService(project)?.ls?.sendReportAnalyticsCommand(scanDoneEvent)
}

override fun scanningSnykCodeFinished(snykCodeResults: SnykCodeResults?) {
snykCodeResults?.let {
val scanDoneEvent = getScanDoneEvent(
System.currentTimeMillis() - start,
"Snyk Code",
snykCodeResults.totalCriticalCount,
snykCodeResults.totalErrorsCount,
snykCodeResults.totalWarnsCount,
snykCodeResults.totalInfosCount,
)
getSnykTaskQueueService(project)?.ls?.sendReportAnalyticsCommand(scanDoneEvent)
}
}

override fun scanningIacFinished(iacResult: IacResult) {
val scanDoneEvent = getScanDoneEvent(
System.currentTimeMillis() - start,
"Snyk IaC",
iacResult.criticalSeveritiesCount(),
iacResult.highSeveritiesCount(),
iacResult.mediumSeveritiesCount(),
iacResult.lowSeveritiesCount()
)
getSnykTaskQueueService(project)?.ls?.sendReportAnalyticsCommand(scanDoneEvent)
}

override fun scanningOssError(snykError: SnykError) {
// do nothing
}

override fun scanningIacError(snykError: SnykError) {
// do nothing
}

override fun scanningSnykCodeError(snykError: SnykError) {
// do nothing
}

override fun scanningContainerFinished(containerResult: ContainerResult) {
val scanDoneEvent = getScanDoneEvent(
System.currentTimeMillis() - start,
"Snyk Container",
containerResult.criticalSeveritiesCount(),
containerResult.highSeveritiesCount(),
containerResult.mediumSeveritiesCount(),
containerResult.lowSeveritiesCount()
)
getSnykTaskQueueService(project)?.ls?.sendReportAnalyticsCommand(scanDoneEvent)
}

override fun scanningContainerError(snykError: SnykError) {
// do nothing
}
},
)
}
47 changes: 1 addition & 46 deletions src/main/kotlin/io/snyk/plugin/services/SnykTaskQueueService.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.snyk.plugin.services

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.openapi.application.ApplicationInfo
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.logger
Expand Down Expand Up @@ -34,12 +33,9 @@ import io.snyk.plugin.ui.SnykBalloonNotifications
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.apache.commons.lang.SystemUtils
import org.jetbrains.annotations.TestOnly
import snyk.common.SnykError
import snyk.common.lsp.LanguageServerWrapper
import snyk.common.lsp.commands.ScanDoneEvent
import snyk.pluginInfo
import snyk.trust.confirmScanningAndSetWorkspaceTrustedStateIfNeeded
import java.nio.file.Paths

Expand Down Expand Up @@ -198,6 +194,7 @@ class SnykTaskQueueService(val project: Project) {
settings.localCodeEngineEnabled = sastCliConfigSettings?.localCodeEngine?.enabled
settings.localCodeEngineUrl = sastCliConfigSettings?.localCodeEngine?.url
settings.reportFalsePositivesEnabled = sastCliConfigSettings?.reportFalsePositivesEnabled
val start = System.currentTimeMillis()

Check warning

Code scanning / detekt

Property is unused and should be removed. Warning

Private property start is unused.
when (settings.sastOnServerEnabled) {
true -> {
getSnykCode(project)?.scan()
Expand Down Expand Up @@ -231,7 +228,6 @@ class SnykTaskQueueService(val project: Project) {
taskQueue.run(object : Task.Backgroundable(project, "Snyk Open Source is scanning", true) {
override fun run(indicator: ProgressIndicator) {
if (!isCliInstalled()) return
val start = System.currentTimeMillis()
val snykCachedResults = getSnykCachedResults(project) ?: return
if (snykCachedResults.currentOssResults != null) return

Expand All @@ -243,23 +239,13 @@ class SnykTaskQueueService(val project: Project) {
} finally {
ossScanProgressIndicator = null
}
val end = System.currentTimeMillis()
if (ossResult == null || project.isDisposed) return

if (indicator.isCanceled) {
taskQueuePublisher?.stopped(wasOssRunning = true)
} else {
if (ossResult.isSuccessful()) {
scanPublisher?.scanningOssFinished(ossResult)
val scanDoneEvent = getScanDoneEvent(
end - start,
"Snyk Open Source",
ossResult.criticalSeveritiesCount(),
ossResult.highSeveritiesCount(),
ossResult.mediumSeveritiesCount(),
ossResult.lowSeveritiesCount()
)
ls.sendReportAnalyticsCommand(scanDoneEvent)
} else {
scanPublisher?.scanningOssError(ossResult.getFirstError()!!)
}
Expand All @@ -269,37 +255,6 @@ class SnykTaskQueueService(val project: Project) {
})
}

private fun getScanDoneEvent(
duration: Long, product: String, critical: Int, high: Int, medium: Int, low: Int
): ScanDoneEvent {
return ScanDoneEvent(
ScanDoneEvent.Data(
type = "analytics",
attributes = ScanDoneEvent.Attributes(
deviceId = settings.userAnonymousId,
application = ApplicationInfo.getInstance().fullApplicationName,
applicationVersion = ApplicationInfo.getInstance().fullVersion,
os = SystemUtils.OS_NAME,
arch = SystemUtils.OS_ARCH,
integrationName = pluginInfo.integrationName,
integrationVersion = pluginInfo.integrationVersion,
integrationEnvironment = pluginInfo.integrationEnvironment,
integrationEnvironmentVersion = pluginInfo.integrationEnvironmentVersion,
eventType = "Scan done",
status = "Succeeded",
scanType = product,
uniqueIssueCount = ScanDoneEvent.UniqueIssueCount(
critical = critical,
high = high,
medium = medium,
low = low
),
durationMs = "$duration",
)
)
)
}

private fun scheduleIacScan() {
taskQueueIac.run(object : Task.Backgroundable(project, "Snyk Infrastructure as Code is scanning", true) {
override fun run(indicator: ProgressIndicator) {
Expand Down

0 comments on commit cfaac31

Please sign in to comment.