diff --git a/platform/platform-tests/testSrc/com/intellij/internal/statistics/metadata/EventSchemeBuilderTest.kt b/platform/platform-tests/testSrc/com/intellij/internal/statistics/metadata/EventSchemeBuilderTest.kt index 45bcbb9b9b8f..df9da04bae15 100644 --- a/platform/platform-tests/testSrc/com/intellij/internal/statistics/metadata/EventSchemeBuilderTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/internal/statistics/metadata/EventSchemeBuilderTest.kt @@ -25,7 +25,8 @@ import com.intellij.testFramework.fixtures.BasePlatformTestCase class EventSchemeBuilderTest : BasePlatformTestCase() { override fun setUp() { super.setUp() - RegisteredLogDescriptionsProcessor.reset(false) + RegisteredLogDescriptionsProcessor.configureDescriptionRegistration(false) + RegisteredLogDescriptionsProcessor.resetDescriptions() } fun `test generate string field validated by regexp`() { @@ -129,7 +130,8 @@ class EventSchemeBuilderTest : BasePlatformTestCase() { * when [RegisteredLogDescriptionsProcessor.isRegistered] is true. */ fun `test generate registered descriptions1`() { - RegisteredLogDescriptionsProcessor.reset(true) + RegisteredLogDescriptionsProcessor.configureDescriptionRegistration(true) + RegisteredLogDescriptionsProcessor.resetDescriptions() val groupDescription = "Test group description5" val eventDescription = "Description of test event" val fieldDescription = "Number of elements in event" @@ -152,7 +154,8 @@ class EventSchemeBuilderTest : BasePlatformTestCase() { * registered group description. */ fun `test generate registered descriptions for the same groups with different descriptions`() { - RegisteredLogDescriptionsProcessor.reset(true) + RegisteredLogDescriptionsProcessor.configureDescriptionRegistration(true) + RegisteredLogDescriptionsProcessor.resetDescriptions() val groupDescription = "Test group description" val eventDescription = "Description of test event" val fieldDescription = "Number of elements in event" @@ -176,7 +179,8 @@ class EventSchemeBuilderTest : BasePlatformTestCase() { * Validates the error message when attempting to overwrite an existing event description. */ fun `test generate registered descriptions for the same events with different descriptions`() { - RegisteredLogDescriptionsProcessor.reset(true) + RegisteredLogDescriptionsProcessor.configureDescriptionRegistration(true) + RegisteredLogDescriptionsProcessor.resetDescriptions() val groupDescription = "Test group description" val eventDescription = "Description of test event" val fieldDescription = "Number of elements in event" diff --git a/platform/statistics/api-dump.txt b/platform/statistics/api-dump.txt index 4e109ba38a32..6a4d5b1d7fcd 100644 --- a/platform/statistics/api-dump.txt +++ b/platform/statistics/api-dump.txt @@ -1,6 +1,9 @@ c:com.intellij.internal.statistic.eventLog.EventLogGroup +- b:(java.lang.String,I,java.lang.String,java.lang.String,I,kotlin.jvm.internal.DefaultConstructorMarker):V - f:getGroupData():java.util.List - f:registerEvent(java.lang.String,com.intellij.internal.statistic.eventLog.events.EventField,java.lang.String,I,java.lang.Object):com.intellij.internal.statistic.eventLog.events.EventId1 +f:com.intellij.internal.statistic.eventLog.EventLogGroupKt +- sf:FUS_RECORDER:java.lang.String com.intellij.internal.statistic.eventLog.StatisticsEventLogListener - a:onLogEvent(com.jetbrains.fus.reporting.model.lion3.LogEvent,java.lang.String,java.util.Map):V com.intellij.internal.statistic.eventLog.StatisticsEventLogger @@ -12,3 +15,5 @@ com.intellij.internal.statistic.eventLog.StatisticsEventLogger - a:logAsync(com.intellij.internal.statistic.eventLog.EventLogGroup,java.lang.String,kotlin.jvm.functions.Function0,Z):java.util.concurrent.CompletableFuture - logAsync(com.intellij.internal.statistic.eventLog.EventLogGroup,java.lang.String,Z):java.util.concurrent.CompletableFuture - a:rollOver():V +f:com.intellij.internal.statistic.eventLog.events.scheme.RegisteredLogDescriptionsProcessorKt +- sf:FUS_DESCRIPTION_REGISTRATION_ENABLED:java.lang.String diff --git a/platform/statistics/src/com/intellij/internal/statistic/eventLog/EventLogGroup.kt b/platform/statistics/src/com/intellij/internal/statistic/eventLog/EventLogGroup.kt index b406281491d6..4c48910ad811 100644 --- a/platform/statistics/src/com/intellij/internal/statistic/eventLog/EventLogGroup.kt +++ b/platform/statistics/src/com/intellij/internal/statistic/eventLog/EventLogGroup.kt @@ -3,9 +3,12 @@ package com.intellij.internal.statistic.eventLog import com.intellij.internal.statistic.IdeActivityDefinition import com.intellij.internal.statistic.eventLog.events.* +import com.intellij.internal.statistic.eventLog.events.scheme.FUS_DESCRIPTION_REGISTRATION_ENABLED import com.intellij.internal.statistic.eventLog.events.scheme.RegisteredLogDescriptionsProcessor import org.jetbrains.annotations.NonNls +const val FUS_RECORDER: String = "FUS" + /** * Represents a group of events used for feature usage statistics. * @@ -38,9 +41,8 @@ open class EventLogGroup { * @param description A textual description of the event group. * The description is not null and not an empty string. * The description is registered at event group initialization using the RegisteredLogDescriptionsProcessor. - * There is no description in the memory if [RegisteredLogDescriptionsProcessor.isRegistered] is false. - * [RegisteredLogDescriptionsProcessor.isRegistered] is true just for - * [com.intellij.internal.statistic.eventLog.events.scheme.EventsSchemeBuilderAppStarter] and tests + * There is no description in the memory if the environment variable [FUS_DESCRIPTION_REGISTRATION_ENABLED] is false. + * Descriptions are stored in memory just for [com.intellij.internal.statistic.eventLog.events.scheme.EventsSchemeBuilderAppStarter] and unit tests. * @param groupData EventFields in groupData are going to be appended to every event in the group. To provide the data, a supplier * function is passed along with each EventField. See [com.intellij.internal.statistic.eventLog.events.EventId] for appending logic. * @@ -49,7 +51,7 @@ open class EventLogGroup { constructor( @NonNls @EventIdName id: String, version: Int, - recorder: String, + recorder: String = FUS_RECORDER, description: String, groupData: List, FeatureUsageData.() -> Unit>> = emptyList(), ) { @@ -71,7 +73,7 @@ open class EventLogGroup { constructor( @NonNls @EventIdName id: String, version: Int, - recorder: String = "FUS", + recorder: String = FUS_RECORDER, ) { this.id = id this.version = version @@ -86,7 +88,7 @@ open class EventLogGroup { constructor( @NonNls @EventIdName id: String, version: Int, - recorder: String, + recorder: String = FUS_RECORDER, description: String?, ) : this(id, version, recorder) { RegisteredLogDescriptionsProcessor.registerGroupDescription(id, description) @@ -115,9 +117,8 @@ open class EventLogGroup { * @param description The unique identifier for the event. * The description is not null and not an empty string. * The description is registered at event initialization using the [RegisteredLogDescriptionsProcessor]. - * There is no description in the memory if [RegisteredLogDescriptionsProcessor.isRegistered] is false. - * [RegisteredLogDescriptionsProcessor.isRegistered] is true just - * for [com.intellij.internal.statistic.eventLog.events.scheme.EventsSchemeBuilderAppStarter] and tests + * There is no description in the memory if the environment variable [FUS_DESCRIPTION_REGISTRATION_ENABLED] is false. + * Descriptions are stored in memory just for [com.intellij.internal.statistic.eventLog.events.scheme.EventsSchemeBuilderAppStarter] and unit tests. * * For events with more than 3 fields use EventLogGroup.registerVarargEvent * diff --git a/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/EventId.kt b/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/EventId.kt index 1e88f43799d7..b111ea1966bd 100644 --- a/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/EventId.kt +++ b/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/EventId.kt @@ -6,6 +6,7 @@ import com.intellij.internal.statistic.eventLog.EventLogGroup import com.intellij.internal.statistic.eventLog.FeatureUsageData import com.intellij.internal.statistic.eventLog.StatisticsEventLogProviderUtil import com.intellij.internal.statistic.eventLog.StatisticsEventLogger +import com.intellij.internal.statistic.eventLog.events.scheme.FUS_DESCRIPTION_REGISTRATION_ENABLED import com.intellij.internal.statistic.eventLog.events.scheme.RegisteredLogDescriptionsProcessor import com.intellij.openapi.project.Project import org.jetbrains.annotations.NonNls @@ -24,8 +25,8 @@ import java.util.function.Consumer * The description is not an empty string. * The description is not null for new events. * The description is registered at event initialization using the [RegisteredLogDescriptionsProcessor]. - * There is no description in the memory if [RegisteredLogDescriptionsProcessor.isRegistered] is false. - * [RegisteredLogDescriptionsProcessor.isRegistered] is true just for [com.intellij.internal.statistic.eventLog.events.scheme.EventsSchemeBuilderAppStarter] and tests + * There is no description in the memory if the environment variable [FUS_DESCRIPTION_REGISTRATION_ENABLED] is false. + * Descriptions are stored in memory just for [com.intellij.internal.statistic.eventLog.events.scheme.EventsSchemeBuilderAppStarter] and unit tests. */ abstract class BaseEventId(groupId: String, val eventId: String, val recorder: String, description: String?) { init { diff --git a/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/EventsSchemeBuilderAppStarter.kt b/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/EventsSchemeBuilderAppStarter.kt index a4a0aac94c1b..fd44c6b3dd1e 100644 --- a/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/EventsSchemeBuilderAppStarter.kt +++ b/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/EventsSchemeBuilderAppStarter.kt @@ -52,7 +52,6 @@ internal class EventsSchemeBuilderAppStarter : ApplicationStarter { testEventsScheme = arg.substringAfter(testEventSchemeParameter).toBoolean() } } - RegisteredLogDescriptionsProcessor.reset(true) val groups: List try { groups = EventsSchemeBuilder.buildEventsScheme(recorderId, pluginId, getPluginsToSkipSchemeGeneration()) diff --git a/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/RegisteredLogDescriptionsProcessor.kt b/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/RegisteredLogDescriptionsProcessor.kt index cdc7321deaec..bbbaaaae3760 100644 --- a/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/RegisteredLogDescriptionsProcessor.kt +++ b/platform/statistics/src/com/intellij/internal/statistic/eventLog/events/scheme/RegisteredLogDescriptionsProcessor.kt @@ -3,12 +3,14 @@ package com.intellij.internal.statistic.eventLog.events.scheme import org.jetbrains.annotations.ApiStatus +const val FUS_DESCRIPTION_REGISTRATION_ENABLED: String = "FUS_DESCRIPTION_REGISTRATION_ENABLED" + /** * Internal processor for managing to store descriptions of event log groups and their events. * Provides functionality to store, retrieve descriptions for groups and their corresponding events. * - * Descriptions are registered and stored in the memory if [isRegistered] is true. - * Please use it just for [com.intellij.internal.statistic.eventLog.events.scheme.EventsSchemeBuilderAppStarter] and tests. + * Descriptions are registered and stored in the memory if the environment variable [FUS_DESCRIPTION_REGISTRATION_ENABLED] is true. + * Please use it just for [EventsSchemeBuilderAppStarter] and tests. * * It ensures that event and group descriptions are immutable once registered. * If an attempt is made to override an already registered description with a differing value, @@ -23,25 +25,31 @@ import org.jetbrains.annotations.ApiStatus object RegisteredLogDescriptionsProcessor { private val groupDescriptionsMap = HashMap() private val eventDescriptionsMap = HashMap>() - private var isRegistered = false + private var descriptionRegistrationEnabled = System.getenv(FUS_DESCRIPTION_REGISTRATION_ENABLED)?.toBoolean() ?: false /** - * Resets the state of the current instance by clearing all relevant data and updating registration status. - * - * @param isRegistered A boolean indicating the new registration status to set. + * Resets the descriptions of the current instance by clearing all relevant data. */ - fun reset(isRegistered: Boolean) { - this.isRegistered = isRegistered + fun resetDescriptions() { groupDescriptionsMap.clear() eventDescriptionsMap.clear() } /** - * Register a description for a specified group if [isRegistered] is true, the description is not empty and not null. + * Enables/disables description registration. + * + * @param descriptionRegistrationEnabled A boolean indicating the new registration status to set. + */ + fun configureDescriptionRegistration(isEnabled: Boolean) { + this.descriptionRegistrationEnabled = isEnabled + } + + /** + * Register a description for a specified group if [descriptionRegistrationEnabled] is true, the description is not empty and not null. * Throws an exception if the description for the group already exists and differs from the new one. */ fun registerGroupDescription(groupId: String, description: String?) { - if (!isRegistered || description == null || description.isEmpty()) return + if (!descriptionRegistrationEnabled || description == null || description.isEmpty()) return if (groupDescriptionsMap.containsKey(groupId) && groupDescriptionsMap[groupId] != description) { throw IllegalStateException("Trying to override registered event log group description in group '$groupId'. " + @@ -51,11 +59,11 @@ object RegisteredLogDescriptionsProcessor { } /** - * Register a description for an event within a specific group if [isRegistered] is true, the description is not empty and not null. + * Register a description for an event within a specific group if [descriptionRegistrationEnabled] is true, the description is not empty and not null. * Throws an exception if the description for the event already exists and differs from the new one. */ fun registerEventDescription(groupId: String, eventId: String, description: String?) { - if (!isRegistered || description == null || description.isEmpty()) return + if (!descriptionRegistrationEnabled || description == null || description.isEmpty()) return val groupMap = eventDescriptionsMap[groupId] if (groupMap == null) { @@ -75,18 +83,18 @@ object RegisteredLogDescriptionsProcessor { } /** - * Retrieves the description for a specified group or returns null if [isRegistered] is false or the group description is not registered. + * Retrieves the description for a specified group or returns null if [descriptionRegistrationEnabled] is false or the group description is not registered. */ fun calculateGroupDescription(groupId: String): String? { - if (!isRegistered) return null + if (!descriptionRegistrationEnabled) return null return groupDescriptionsMap[groupId] } /** - * Retrieves the description for a specific event in the group or returns null if [isRegistered] is false or the events description is not registered. + * Retrieves the description for a specific event in the group or returns null if [descriptionRegistrationEnabled] is false or the events description is not registered. */ fun calculateEventDescription(groupId: String, eventId: String): String? { - if (!isRegistered) return null + if (!descriptionRegistrationEnabled) return null val groupMap = eventDescriptionsMap[groupId] return groupMap?.get(eventId) }