Skip to content

Commit 8573a1b

Browse files
authored
Merge pull request #2489 from digma-ai/add-properties-to-daily-engagement-event
add properties to engagement score
2 parents e4f55ea + c4aa065 commit 8573a1b

File tree

8 files changed

+108
-37
lines changed

8 files changed

+108
-37
lines changed

ide-common/src/main/kotlin/org/digma/intellij/plugin/engagement/EngagementScorePersistence.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ class EngagementScoreData {
3737
@get:XMap(keyAttributeName = "day", valueAttributeName = "count")
3838
var meaningfulActionsCounters = mutableMapOf<String, Int>()
3939

40+
var latestRegisteredActiveDays: Long = 0
41+
var latestRegisteredAverage: Long = 0
42+
4043

4144
fun put(date: LocalDate, count: Int) {
4245
meaningfulActionsCounters[date.toString()] = count

ide-common/src/main/kotlin/org/digma/intellij/plugin/engagement/EngagementScoreService.kt

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ import kotlin.time.Duration.Companion.minutes
2626
class EngagementScoreService(private val cs: CoroutineScope) : DisposableAdaptor {
2727

2828
companion object {
29+
30+
@JvmStatic
31+
fun getInstance(): EngagementScoreService {
32+
return service<EngagementScoreService>()
33+
}
34+
2935
val MEANINGFUL_ACTIONS = setOf(
3036
"span link clicked",
3137
"insights insight card asset link clicked",
@@ -71,12 +77,12 @@ class EngagementScoreService(private val cs: CoroutineScope) : DisposableAdaptor
7177
LocalDate.parse(it.key) != today()
7278
}
7379

74-
if (daysForAverage.isEmpty()){
80+
if (daysForAverage.isEmpty()) {
7581
return
7682
}
7783

7884

79-
val activeDays = daysForAverage.size
85+
val activeDays = daysForAverage.size.toLong()
8086
val average = daysForAverage.values.average().let {
8187
if (it.isNaN()) 0 else it.roundToLong()
8288
}
@@ -102,15 +108,12 @@ class EngagementScoreService(private val cs: CoroutineScope) : DisposableAdaptor
102108

103109
project?.let {
104110

105-
//update last event time only if really sent the event
111+
//update only if really sent the event
106112
service<EngagementScorePersistence>().state.lastEventTime = today()
113+
service<EngagementScorePersistence>().state.latestRegisteredActiveDays = activeDays
114+
service<EngagementScorePersistence>().state.latestRegisteredAverage = average
107115

108-
ActivityMonitor.getInstance(it).registerCustomEvent(
109-
"daily engagement score", mapOf(
110-
"meaningful_actions_days" to activeDays,
111-
"meaningful_actions_avg" to average
112-
)
113-
)
116+
ActivityMonitor.getInstance(it).registerEngagementScore(activeDays, average)
114117
}
115118
}
116119
}
@@ -139,4 +142,13 @@ class EngagementScoreService(private val cs: CoroutineScope) : DisposableAdaptor
139142
}
140143
}
141144

145+
146+
fun getLatestRegisteredActiveDays(): Long {
147+
return service<EngagementScorePersistence>().state.latestRegisteredActiveDays
148+
}
149+
150+
fun getLatestRegisteredAverage(): Long {
151+
return service<EngagementScorePersistence>().state.latestRegisteredAverage
152+
}
153+
142154
}

ide-common/src/main/kotlin/org/digma/intellij/plugin/persistence/PersistenceData.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ internal data class PersistenceData(
1313
var userRegistrationEmail: String? = null,
1414
var isLocalEngineInstalled: Boolean? = null,
1515
var userId: String? = null,
16+
var userRequestedCourse: Boolean = false,
1617

1718
//lastInsightsEventTime is different from other timestamps in that it needs to be same format and
1819
// timezone as in the backend

ide-common/src/main/kotlin/org/digma/intellij/plugin/persistence/PersistenceService.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,5 +387,12 @@ class PersistenceService {
387387
return state.alreadyShowedNewRecentActivityNotification
388388
}
389389

390+
fun setUserRequestedCourse(courseRequested: Boolean) {
391+
state.userRequestedCourse = courseRequested
392+
}
393+
394+
fun isUserRequestedCourse():Boolean {
395+
return state.userRequestedCourse
396+
}
390397

391398
}

ide-common/src/main/kotlin/org/digma/intellij/plugin/posthog/ActivityMonitor.kt

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ private const val INSTALL_STATUS_PROPERTY_NAME = "install_status"
5050
private const val ENVIRONMENT_ADDED_PROPERTY_NAME = "environment_added"
5151
private const val LOAD_WARNING_APPEARED_PROPERTY_NAME = "load_warning_appeared"
5252
private const val JIRA_FIELD_COPIED_PROPERTY_NAME = "jira_field_copied"
53+
private const val USER_REQUESTED_COURSE_PROPERTY_NAME = "user_requested_course"
54+
private const val MEANINGFUL_ACTIONS_DAYS_PROPERTY_NAME = "meaningful_actions_days"
55+
private const val MEANINGFUL_ACTIONS_AVG_PROPERTY_NAME = "meaningful_actions_avg"
5356

5457
enum class InstallStatus { Active, Uninstalled, Disabled }
5558

@@ -155,6 +158,11 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
155158
}
156159

157160

161+
private fun identify(properties: Map<String, Any?>, propertiesSetOnce: Map<String, Any?>? = null) {
162+
postHog?.identify(UniqueGeneratedUserId.userId, properties, propertiesSetOnce)
163+
}
164+
165+
158166
private fun capture(eventName: String) {
159167
capture(eventName, mapOf())
160168
}
@@ -206,12 +214,22 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
206214
)
207215
}
208216

209-
fun registerEmail(email: String, courseRequested: Boolean) {
210-
postHog?.identify(
211-
UniqueGeneratedUserId.userId, mapOf(
217+
fun registerUserRequestedCourse() {
218+
identify(
219+
mapOf(
220+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse()
221+
)
222+
)
223+
}
224+
225+
226+
fun registerEmail(email: String) {
227+
228+
identify(
229+
mapOf(
212230
"email" to getEmailForEvent(),
213231
INSTALL_STATUS_PROPERTY_NAME to getCurrentInstallStatus(),
214-
"user_requested_course" to courseRequested.toString()
232+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse()
215233
)
216234
)
217235
postHog?.alias(UniqueGeneratedUserId.userId, email)
@@ -687,7 +705,7 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
687705
capture("project closed", mapOf("open.projects" to openProjects))
688706
}
689707

690-
fun registerPluginUninstalled(): String {
708+
fun registerPluginUninstalled() {
691709

692710
SessionMetadataProperties.getInstance().put(CURRENT_INSTALL_STATUS_KEY, InstallStatus.Uninstalled)
693711

@@ -700,7 +718,9 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
700718
ENVIRONMENT_ADDED_PROPERTY_NAME to PersistenceService.getInstance().isEnvironmentAdded(),
701719
LOAD_WARNING_APPEARED_PROPERTY_NAME to PersistenceService.getInstance().isLoadWarningAppeared(),
702720
JIRA_FIELD_COPIED_PROPERTY_NAME to PersistenceService.getInstance().isJiraFieldCopied(),
703-
"user_requested_course" to "false"
721+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse(),
722+
MEANINGFUL_ACTIONS_DAYS_PROPERTY_NAME to EngagementScoreService.getInstance().getLatestRegisteredActiveDays(),
723+
MEANINGFUL_ACTIONS_AVG_PROPERTY_NAME to EngagementScoreService.getInstance().getLatestRegisteredAverage()
704724
)
705725
)
706726
}
@@ -710,10 +730,9 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
710730
INSTALL_STATUS_PROPERTY_NAME + "_timestamp" to SessionMetadataProperties.getInstance().getCreatedAsString(CURRENT_INSTALL_STATUS_KEY)
711731
)
712732
)
713-
return UniqueGeneratedUserId.userId
714733
}
715734

716-
fun registerPluginDisabled(): String {
735+
fun registerPluginDisabled() {
717736

718737
SessionMetadataProperties.getInstance().put(CURRENT_INSTALL_STATUS_KEY, InstallStatus.Disabled)
719738

@@ -726,7 +745,9 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
726745
ENVIRONMENT_ADDED_PROPERTY_NAME to PersistenceService.getInstance().isEnvironmentAdded(),
727746
LOAD_WARNING_APPEARED_PROPERTY_NAME to PersistenceService.getInstance().isLoadWarningAppeared(),
728747
JIRA_FIELD_COPIED_PROPERTY_NAME to PersistenceService.getInstance().isJiraFieldCopied(),
729-
"user_requested_course" to "false"
748+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse(),
749+
MEANINGFUL_ACTIONS_DAYS_PROPERTY_NAME to EngagementScoreService.getInstance().getLatestRegisteredActiveDays(),
750+
MEANINGFUL_ACTIONS_AVG_PROPERTY_NAME to EngagementScoreService.getInstance().getLatestRegisteredAverage()
730751
)
731752
)
732753
}
@@ -736,7 +757,6 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
736757
INSTALL_STATUS_PROPERTY_NAME + "_timestamp" to SessionMetadataProperties.getInstance().getCreatedAsString(CURRENT_INSTALL_STATUS_KEY)
737758
)
738759
)
739-
return UniqueGeneratedUserId.userId
740760
}
741761

742762

@@ -913,11 +933,10 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
913933
)
914934
)
915935

916-
postHog?.identify(
917-
UniqueGeneratedUserId.userId,
936+
identify(
918937
mapOf(
919938
LOAD_WARNING_APPEARED_PROPERTY_NAME + "_timestamp" to PersistenceService.getInstance().getLoadWarningAppearedTimestamp(),
920-
"user_requested_course" to "false"
939+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse()
921940
),
922941
mapOf(
923942
LOAD_WARNING_APPEARED_PROPERTY_NAME to PersistenceService.getInstance().isLoadWarningAppeared(),
@@ -945,11 +964,10 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
945964
)
946965
registerUserAction(eventName, eventDetails)
947966

948-
postHog?.identify(
949-
UniqueGeneratedUserId.userId,
967+
identify(
950968
mapOf(
951969
ENVIRONMENT_ADDED_PROPERTY_NAME + "_timestamp" to PersistenceService.getInstance().getEnvironmentAddedTimestamp(),
952-
"user_requested_course" to "false"
970+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse()
953971
),
954972
mapOf(
955973
ENVIRONMENT_ADDED_PROPERTY_NAME to PersistenceService.getInstance().isEnvironmentAdded()
@@ -977,11 +995,10 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
977995
mutableDetails
978996
)
979997

980-
postHog?.identify(
981-
UniqueGeneratedUserId.userId,
998+
identify(
982999
mapOf(
9831000
JIRA_FIELD_COPIED_PROPERTY_NAME + "_timestamp" to PersistenceService.getInstance().getJiraFieldCopiedTimestamp(),
984-
"user_requested_course" to "false"
1001+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse()
9851002
),
9861003
mapOf(
9871004
JIRA_FIELD_COPIED_PROPERTY_NAME to PersistenceService.getInstance().isJiraFieldCopied()
@@ -1062,4 +1079,25 @@ class ActivityMonitor(private val project: Project, cs: CoroutineScope) : Dispos
10621079
capture("backend-data-found")
10631080
}
10641081

1082+
fun registerEngagementScore(activeDays: Long, average: Long) {
1083+
1084+
val details = mapOf(
1085+
MEANINGFUL_ACTIONS_DAYS_PROPERTY_NAME to activeDays,
1086+
MEANINGFUL_ACTIONS_AVG_PROPERTY_NAME to average,
1087+
INSTALL_STATUS_PROPERTY_NAME to getCurrentInstallStatus(),
1088+
USER_REQUESTED_COURSE_PROPERTY_NAME to PersistenceService.getInstance().isUserRequestedCourse()
1089+
)
1090+
1091+
capture("daily engagement score", details)
1092+
1093+
identify(
1094+
mapOf(
1095+
MEANINGFUL_ACTIONS_DAYS_PROPERTY_NAME to activeDays,
1096+
MEANINGFUL_ACTIONS_AVG_PROPERTY_NAME to average
1097+
)
1098+
)
1099+
1100+
}
1101+
1102+
10651103
}

ide-common/src/main/kotlin/org/digma/intellij/plugin/posthog/PluginActivityMonitor.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.intellij.openapi.diagnostic.Logger
1212
import com.intellij.openapi.project.Project
1313
import com.intellij.openapi.util.Disposer
1414
import org.digma.intellij.plugin.PluginId
15+
import org.digma.intellij.plugin.common.UniqueGeneratedUserId
1516
import org.digma.intellij.plugin.docker.LocalInstallationFacade
1617
import org.digma.intellij.plugin.log.Log
1718

@@ -36,9 +37,9 @@ class PluginActivityMonitor(private val project: Project) : PluginStateListener,
3637

3738

3839
val disabledListener = Runnable {
39-
if (DisabledPluginsState.getDisabledIds().contains(myPluginId)){
40-
val userId = ActivityMonitor.getInstance(project).registerPluginDisabled()
41-
BrowserUtil.browse("https://digma.ai/disabled?u=$userId", project)
40+
if (DisabledPluginsState.getDisabledIds().contains(myPluginId)) {
41+
ActivityMonitor.getInstance(project).registerPluginDisabled()
42+
BrowserUtil.browse("https://digma.ai/disabled?u=${UniqueGeneratedUserId.userId}", project)
4243
}
4344
}
4445

@@ -50,9 +51,9 @@ class PluginActivityMonitor(private val project: Project) : PluginStateListener,
5051
}
5152

5253
override fun uninstall(descriptor: IdeaPluginDescriptor) {
53-
if(descriptor.pluginId.idString == PluginId.PLUGIN_ID){
54-
val userId = ActivityMonitor.getInstance(project).registerPluginUninstalled()
55-
BrowserUtil.browse("https://digma.ai/uninstall?u=$userId", project)
54+
if (descriptor.pluginId.idString == PluginId.PLUGIN_ID) {
55+
ActivityMonitor.getInstance(project).registerPluginUninstalled()
56+
BrowserUtil.browse("https://digma.ai/uninstall?u=${UniqueGeneratedUserId.userId}", project)
5657

5758

5859
if (service<LocalInstallationFacade>().isLocalEngineInstalled()) {

src/main/kotlin/org/digma/intellij/plugin/ui/jcef/UserRegistrationManager.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,24 @@ class UserRegistrationManager(private val project: Project) {
3030
}
3131

3232

33+
//if UserRequestedCourse is already true don't change again, it depends on who called this method, and it may be that
34+
// the scope property doesn't exist but user already requested course before.
35+
if (!PersistenceService.getInstance().isUserRequestedCourse()) {
36+
val courseRequested = registrationMap["scope"] == "promotion"
37+
if (courseRequested) {
38+
PersistenceService.getInstance().setUserRequestedCourse(true)
39+
ActivityMonitor.getInstance(project).registerUserRequestedCourse()
40+
}
41+
}
42+
3343
if (PersistenceService.getInstance().getUserRegistrationEmail().isNullOrBlank() ||
3444
PersistenceService.getInstance().getUserRegistrationEmail() != email
3545
) {
3646

3747
ActivityMonitor.getInstance(project).registerCustomEvent("register local user", registrationMap)
3848
ActivityMonitor.getInstance(project).registerUserAction("local user registered", registrationMap)
39-
val courseRequested = registrationMap["scope"] == "promotion"
4049
PersistenceService.getInstance().setUserRegistrationEmail(email)
41-
ActivityMonitor.getInstance(project).registerEmail(email, courseRequested)//override the onboarding email
50+
ActivityMonitor.getInstance(project).registerEmail(email)//override the onboarding email
4251
project.messageBus.syncPublisher(UserRegistrationEvent.USER_REGISTRATION_TOPIC).userRegistered(email)
4352
}
4453
}

src/main/kotlin/org/digma/intellij/plugin/ui/wizard/InstallationWizardSidePanelWindowPanel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ fun createInstallationWizardSidePanelWindowPanel(project: Project, wizardSkipIns
210210
val email = payload?.email
211211
PersistenceService.getInstance().setUserEmail(email)
212212
if (email != null) {
213-
ActivityMonitor.getInstance(project).registerEmail(email, false)
213+
ActivityMonitor.getInstance(project).registerEmail(email)
214214
}
215215

216216
payload?.productKey?.let {

0 commit comments

Comments
 (0)