From 8d61d23a40d00b1b6f81de9d014c88ab219ed7c2 Mon Sep 17 00:00:00 2001 From: Nikita Katkov Date: Fri, 7 Mar 2025 18:01:36 +0100 Subject: [PATCH] [fileTypes & FUS] IJPL-178816 Start counting file type's schemas in FUS GitOrigin-RevId: fe1951faa6aa39924ae79fd46309bb659c0040c2 --- .../fus/fileTypes/FileTypeSchemaCounter.kt | 32 +++++++++++++++++++ .../fileTypes/FileTypeUsagesCollector.java | 17 +++++----- 2 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeSchemaCounter.kt diff --git a/platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeSchemaCounter.kt b/platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeSchemaCounter.kt new file mode 100644 index 000000000000..a4f6d4c19933 --- /dev/null +++ b/platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeSchemaCounter.kt @@ -0,0 +1,32 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.internal.statistic.collectors.fus.fileTypes + +import com.intellij.internal.statistic.eventLog.events.ObjectEventData +import com.intellij.openapi.fileTypes.FileType +import org.jetbrains.annotations.NotNull +import kotlin.math.roundToInt + +internal class FileTypeSchemaCounter { + private val NO_SCHEMA = "" + private val fileTypeSchemaData: MutableMap<@NotNull FileType, MutableMap> = mutableMapOf() + + fun recordFileTypeWithSchema(effectiveType: FileType, schemaType: String?) { + val effectiveSchema = schemaType ?: NO_SCHEMA + + val schemasForType = fileTypeSchemaData.getOrPut(effectiveType) { mutableMapOf() } + val currentSchemaCount = schemasForType.getOrPut(effectiveSchema) { 0 } + fileTypeSchemaData[effectiveType]!![effectiveSchema] = currentSchemaCount + 1 + } + + fun getFileTypeSchemaUsagePercentage(effectiveType: FileType): List { + val schemaCounts = fileTypeSchemaData[effectiveType].orEmpty() + val allSchemasCount = schemaCounts.values.sum() + return schemaCounts.map { (schema, count) -> + val schemaPercentage = ((count.toDouble() / allSchemasCount) * 100).roundToInt() + ObjectEventData( + FileTypeUsagesCollector.SCHEMA with schema, + FileTypeUsagesCollector.PERCENT with schemaPercentage + ) + } + } +} \ No newline at end of file diff --git a/platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsagesCollector.java b/platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsagesCollector.java index f6b75218f131..cce5a6f0fbb0 100644 --- a/platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsagesCollector.java +++ b/platform/platform-impl/internal/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsagesCollector.java @@ -22,24 +22,22 @@ import com.intellij.util.containers.ObjectIntMap; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; +import static com.intellij.internal.statistic.collectors.fus.fileTypes.FileTypeUsageCounterCollector.findSchema; import static java.util.Collections.emptySet; @ApiStatus.Internal public final class FileTypeUsagesCollector extends ProjectUsagesCollector { private static final String DEFAULT_ID = "third.party"; - private final EventLogGroup GROUP = new EventLogGroup("file.types", 7); + private final EventLogGroup GROUP = new EventLogGroup("file.types", 8); private final RoundedIntEventField COUNT = EventFields.RoundedInt("count"); // temporary is not collected - private final EventField SCHEMA = EventFields.StringValidatedByCustomRule("schema", FileTypeSchemaValidator.class); - private final IntEventField PERCENT = EventFields.Int("percent"); + public static final EventField SCHEMA = EventFields.StringValidatedByCustomRule("schema", FileTypeSchemaValidator.class); + public static final IntEventField PERCENT = EventFields.Int("percent"); private final ObjectListEventField FILE_SCHEME_PERCENT = new ObjectListEventField("file_schema", SCHEMA, PERCENT); private final VarargEventId FILE_IN_PROJECT = GROUP.registerVarargEvent( @@ -62,10 +60,12 @@ public final class FileTypeUsagesCollector extends ProjectUsagesCollector { ProjectFileIndex projectFileIndex = ProjectFileIndex.getInstance(project); IProjectStore stateStore = ProjectKt.getStateStore(project); final ObjectIntMap filesByTypeCount = new ObjectIntHashMap<>(); + var schemaCounter = new FileTypeSchemaCounter(); projectFileIndex.iterateContent( file -> { FileType type = file.getFileType(); filesByTypeCount.put(type, filesByTypeCount.getOrDefault(type, 0) + 1); + schemaCounter.recordFileTypeWithSchema(type, findSchema(project, file)); return true; }, //skip files from .idea directory otherwise 99% of projects would have XML and PLAIN_TEXT file types @@ -74,10 +74,11 @@ public final class FileTypeUsagesCollector extends ProjectUsagesCollector { final Set events = new HashSet<>(); for (final FileType fileType : filesByTypeCount.keySet()) { - List> eventPairs = new ArrayList<>(3); + List> eventPairs = new ArrayList<>(4); eventPairs.add(EventFields.PluginInfoFromInstance.with(fileType)); eventPairs.add(EventFields.FileType.with(fileType)); eventPairs.add(COUNT.with(filesByTypeCount.get(fileType))); + eventPairs.add(FILE_SCHEME_PERCENT.with(schemaCounter.getFileTypeSchemaUsagePercentage(fileType))); events.add(FILE_IN_PROJECT.metric(eventPairs)); }