mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DO-1529 fixed race condition in buildEventScheme generation
Descriptions in lifecycle group aren't generated because this group is initialized before resetDescriptions call. GitOrigin-RevId: c276320f4eb2f7f5e578e081020aba2a76bdf022
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8238bd08d7
commit
d18c7b9992
+8
-4
@@ -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"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
c:com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
- b:<init>(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
|
||||
|
||||
@@ -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<Pair<EventField<*>, 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
|
||||
*
|
||||
|
||||
@@ -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 {
|
||||
|
||||
-1
@@ -52,7 +52,6 @@ internal class EventsSchemeBuilderAppStarter : ApplicationStarter {
|
||||
testEventsScheme = arg.substringAfter(testEventSchemeParameter).toBoolean()
|
||||
}
|
||||
}
|
||||
RegisteredLogDescriptionsProcessor.reset(true)
|
||||
val groups: List<GroupDescriptor>
|
||||
try {
|
||||
groups = EventsSchemeBuilder.buildEventsScheme(recorderId, pluginId, getPluginsToSkipSchemeGeneration())
|
||||
|
||||
+24
-16
@@ -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<String, String>()
|
||||
private val eventDescriptionsMap = HashMap<String, HashMap<String, String>>()
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user