blob: 86617104b990d0078acf1964d89e7fabee88c1b7 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:JvmName("StudioUpdaterAnalyticsUtil")
package com.studio.updater
import com.android.tools.analytics.AnalyticsSettings
import com.android.tools.analytics.UsageTracker
import com.android.utils.StdLogger
import com.google.wireless.android.sdk.stats.AndroidStudioEvent
import com.google.wireless.android.sdk.stats.StudioPatchUpdaterEvent
import com.intellij.updater.UpdaterUI
import com.intellij.updater.ValidationResult
import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.TimeUnit
fun logProcessStart() {
AnalyticsSettings.initialize(StdLogger(StdLogger.Level.VERBOSE))
UsageTracker.initialize(ScheduledThreadPoolExecutor(0))
UsageTracker.setMaxJournalTime(10, TimeUnit.MINUTES)
UsageTracker.maxJournalSize = 1000
UsageTracker.log(
AndroidStudioEvent.newBuilder().apply {
kind = AndroidStudioEvent.EventKind.STUDIO_PATCH_UPDATER
studioPatchUpdaterEvent = StudioPatchUpdaterEvent.newBuilder().apply {
kind = StudioPatchUpdaterEvent.Kind.START
}.build()
})
// Ensure all events are flushed to disk before process exit.
Runtime.getRuntime().addShutdownHook(Thread(UsageTracker::deinitialize))
}
fun logProcessSuccess() {
UsageTracker.log(
AndroidStudioEvent.newBuilder().apply {
kind = AndroidStudioEvent.EventKind.STUDIO_PATCH_UPDATER
studioPatchUpdaterEvent = StudioPatchUpdaterEvent.newBuilder().apply {
kind = StudioPatchUpdaterEvent.Kind.EXIT_OK
}.build()
})
}
fun logProcessAbort() {
UsageTracker.log(
AndroidStudioEvent.newBuilder().apply {
kind = AndroidStudioEvent.EventKind.STUDIO_PATCH_UPDATER
studioPatchUpdaterEvent = StudioPatchUpdaterEvent.newBuilder().apply {
kind = StudioPatchUpdaterEvent.Kind.EXIT_ABORT
}.build()
})
}
fun logException() {
UsageTracker.log(
AndroidStudioEvent.newBuilder().apply {
kind = AndroidStudioEvent.EventKind.STUDIO_PATCH_UPDATER
studioPatchUpdaterEvent = StudioPatchUpdaterEvent.newBuilder().apply {
kind = StudioPatchUpdaterEvent.Kind.EXIT_EXCEPTION
}.build()
})
}
private fun toAnalytics(kind: ValidationResult.Kind): StudioPatchUpdaterEvent.IssueDialog.Issue.Kind {
return when (kind) {
ValidationResult.Kind.INFO -> StudioPatchUpdaterEvent.IssueDialog.Issue.Kind.INFO
ValidationResult.Kind.CONFLICT -> StudioPatchUpdaterEvent.IssueDialog.Issue.Kind.CONFLICT
ValidationResult.Kind.ERROR -> StudioPatchUpdaterEvent.IssueDialog.Issue.Kind.ERROR
}
}
private fun toAnalytics(action: ValidationResult.Action): StudioPatchUpdaterEvent.IssueDialog.Issue.Action {
return when (action) {
ValidationResult.Action.CREATE -> StudioPatchUpdaterEvent.IssueDialog.Issue.Action.CREATE
ValidationResult.Action.UPDATE -> StudioPatchUpdaterEvent.IssueDialog.Issue.Action.UPDATE
ValidationResult.Action.DELETE -> StudioPatchUpdaterEvent.IssueDialog.Issue.Action.DELETE
ValidationResult.Action.VALIDATE -> StudioPatchUpdaterEvent.IssueDialog.Issue.Action.VALIDATE
}
}
private fun toAnalytics(result: ValidationResult): StudioPatchUpdaterEvent.IssueDialog.Issue.Builder {
return StudioPatchUpdaterEvent.IssueDialog.Issue.newBuilder().apply {
action = toAnalytics(result.action)
kind = toAnalytics(result.kind)
result.options.forEach { addPresentedOption(toAnalytics(it)) }
}
}
private fun toAnalytics(value: ValidationResult.Option): StudioPatchUpdaterEvent.ValidationOption {
return when (value) {
ValidationResult.Option.NONE -> StudioPatchUpdaterEvent.ValidationOption.NONE
ValidationResult.Option.IGNORE -> StudioPatchUpdaterEvent.ValidationOption.IGNORE
ValidationResult.Option.KEEP -> StudioPatchUpdaterEvent.ValidationOption.KEEP
ValidationResult.Option.REPLACE -> StudioPatchUpdaterEvent.ValidationOption.REPLACE
ValidationResult.Option.DELETE -> StudioPatchUpdaterEvent.ValidationOption.DELETE
ValidationResult.Option.KILL_PROCESS -> StudioPatchUpdaterEvent.ValidationOption.KILL_PROCESS
}
}
fun logProcessFinish(result: Boolean) {
if (result) {
logProcessSuccess()
}
else {
logProcessAbort()
}
}
internal fun toAnalytics(phase: String): StudioPatchUpdaterEvent.Kind {
return when (phase) {
UpdaterUI.message("extracting.patch.file") -> StudioPatchUpdaterEvent.Kind.PHASE_EXTRACTING_PATCH_FILES
UpdaterUI.message("extracting.patch.files") -> StudioPatchUpdaterEvent.Kind.PHASE_EXTRACTING_PATCH_FILES
UpdaterUI.message("validating.installation") -> StudioPatchUpdaterEvent.Kind.PHASE_VALIDATING_INSTALLATION
UpdaterUI.message("backing.up.files") -> StudioPatchUpdaterEvent.Kind.PHASE_BACKING_UP_FILES
UpdaterUI.message("preparing.update") -> StudioPatchUpdaterEvent.Kind.PHASE_PREPARING_UPDATE
UpdaterUI.message("applying.patch") -> StudioPatchUpdaterEvent.Kind.PHASE_APPLYING_PATCH
UpdaterUI.message("reverting") -> StudioPatchUpdaterEvent.Kind.PHASE_REVERTING
UpdaterUI.message("cleaning.up") -> StudioPatchUpdaterEvent.Kind.PHASE_CLEANING_UP
else -> StudioPatchUpdaterEvent.Kind.PHASE_UNKNOWN
}
}
internal fun toAnalytics(results: List<ValidationResult>): StudioPatchUpdaterEvent.IssueDialog {
return StudioPatchUpdaterEvent.IssueDialog.newBuilder().apply {
results.forEach { addIssue(toAnalytics(it)) }
}.build()
}
internal fun toAnalytics(result: Map<String, ValidationResult.Option>): StudioPatchUpdaterEvent.IssueDialogChoices {
return StudioPatchUpdaterEvent.IssueDialogChoices.newBuilder().apply {
result.values.forEach { addChoice(validationToAnalytics(it)) }
}.build()
}
private fun validationToAnalytics(value: ValidationResult.Option): StudioPatchUpdaterEvent.IssueDialogChoices.Choice {
return StudioPatchUpdaterEvent.IssueDialogChoices.Choice.newBuilder().apply {
chosenOption = toAnalytics(value)
}.build()
}