Revert "Refactor MetricContainers and read/write FUS file"

This reverts commit 8ccf4618ab5378ec4aa4868abdca7606cb0b29d7.
diff --git a/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api b/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api
index ed165ee..a28dad0 100644
--- a/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api
+++ b/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api
@@ -2108,8 +2108,6 @@
 	public final fun addToConsumer (Lorg/jetbrains/kotlin/statistics/metrics/StatisticsValuesConsumer;)V
 	public final fun put (Lorg/jetbrains/kotlin/statistics/metrics/BooleanMetrics;Z)Ljava/lang/Boolean;
 	public final fun put (Lorg/jetbrains/kotlin/statistics/metrics/NumericalMetrics;J)Ljava/lang/Long;
-	public final fun put (Lorg/jetbrains/kotlin/statistics/metrics/StringListMetrics;Ljava/lang/String;)Ljava/util/List;
-	public final fun put (Lorg/jetbrains/kotlin/statistics/metrics/StringListMetrics;Ljava/util/List;)Ljava/util/List;
 	public final fun put (Lorg/jetbrains/kotlin/statistics/metrics/StringMetrics;Ljava/lang/String;)Ljava/lang/String;
 }
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFinishBuildService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFinishBuildService.kt
index 376789f..0997573 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFinishBuildService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFinishBuildService.kt
@@ -25,7 +25,7 @@
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
 import org.jetbrains.kotlin.gradle.utils.kotlinErrorsDir
 import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer
-import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer.Companion.addMetricFromFusV2KotlinProfileFile
+import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer.Companion.addMetricFromFusKotlinProfileFile
 import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer.Companion.createValidateAndAnonymizeCopy
 import java.io.File
 import java.util.concurrent.atomic.AtomicBoolean
@@ -94,11 +94,11 @@
             log: Logger,
         ): Errors {
             try {
-                val metricContainer = MetricsContainer.createMetricsContainerForV1ProfileFile()
+                val metricContainer = MetricsContainer.createMetricsContainerForProfileFile()
 
-                fusReportDirectory.findV2FusFilesByBuildId(buildUid)
+                fusReportDirectory.findFusFilesByBuildId(buildUid)
                     ?.forEach {
-                        metricContainer.addMetricFromFusV2KotlinProfileFile(it)
+                        metricContainer.addMetricFromFusKotlinProfileFile(it)
                     }
 
                 val fusFile = fusReportDirectory.resolve("$buildUid.profile")
@@ -121,7 +121,7 @@
             return emptyList()
         }
 
-        internal fun File.findV2FusFilesByBuildId(buildUid: String): List<File>? = listFiles()
+        internal fun File.findFusFilesByBuildId(buildUid: String): List<File>? = listFiles()
             ?.sortedWith(compareBy({ it.lastModified() }, { it.name }))
             ?.filter { it.name.startsWith(buildUid) && (it.name.endsWith("plugin-profile") || it.name.endsWith("kotlin-profile")) }
     }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFusService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFusService.kt
index c7ca8b8..7bdd3c6 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFusService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/BuildFusService.kt
@@ -36,7 +36,6 @@
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
 import org.jetbrains.kotlin.statistics.metrics.StatisticsValuesConsumer
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import java.io.Serializable
 
 
@@ -236,7 +235,6 @@
     private val numericalMetrics = HashMap<NumericalMetrics, Long>()
     private val booleanMetrics = HashMap<BooleanMetrics, Boolean>()
     private val stringMetrics = HashMap<StringMetrics, String>()
-    private val stringListMetrics = HashMap<StringListMetrics, List<String>>()
 
     fun addToConsumer(metricsConsumer: StatisticsValuesConsumer) {
         for ((key, value) in numericalMetrics) {
@@ -248,16 +246,11 @@
         for ((key, value) in stringMetrics) {
             metricsConsumer.report(key, value)
         }
-        for ((key, value) in stringListMetrics) {
-            metricsConsumer.report(key, value)
-        }
     }
 
     fun put(metric: StringMetrics, value: String) = stringMetrics.put(metric, value)
     fun put(metric: BooleanMetrics, value: Boolean) = booleanMetrics.put(metric, value)
     fun put(metric: NumericalMetrics, value: Long) = numericalMetrics.put(metric, value)
-    fun put(metric: StringListMetrics, value: List<String>) = stringListMetrics.put(metric, value)
-    fun put(metric: StringListMetrics, value: String) = put(metric, listOf(value))
 }
 
 internal val Project.buildServiceShouldBeCreated
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/FusMetrics.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/FusMetrics.kt
index 9f841bc..8682589 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/FusMetrics.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/FusMetrics.kt
@@ -40,7 +40,6 @@
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
 import org.jetbrains.kotlin.statistics.metrics.StatisticsValuesConsumer
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
 
@@ -94,7 +93,7 @@
             is K2JVMCompilerArguments -> {
                 val args = K2JVMCompilerArguments()
                 parseCommandLineArguments(argsArray.toList(), args)
-                metricsConsumer.report(StringListMetrics.JVM_DEFAULTS, args.jvmDefaultStable ?: JvmDefaultMode.DISABLE.description)
+                metricsConsumer.report(StringMetrics.JVM_DEFAULTS, args.jvmDefaultStable ?: JvmDefaultMode.DISABLE.description)
 
                 val pluginPatterns = listOf(
                     Pair(BooleanMetrics.ENABLED_COMPILER_PLUGIN_ALL_OPEN, "kotlin-allopen-.*jar"),
@@ -127,7 +126,7 @@
 
                 if (args.irProduceJs) {
                     metricsConsumer.report(BooleanMetrics.JS_SOURCE_MAP, args.sourceMap)
-                    metricsConsumer.report(StringListMetrics.JS_PROPERTY_LAZY_INITIALIZATION, args.irPropertyLazyInitialization.toString())
+                    metricsConsumer.report(StringMetrics.JS_PROPERTY_LAZY_INITIALIZATION, args.irPropertyLazyInitialization.toString())
 
                     metricsConsumer.report(BooleanMetrics.JS_GENERATE_DTS, args.generateDts)
                     metricsConsumer.report(StringMetrics.JS_ES_TARGET, args.target ?: "default")
@@ -299,7 +298,7 @@
         if (firRunnerEnabled) {
             metricsContainer.report(BooleanMetrics.KOTLIN_INCREMENTAL_FIR_RUNNER_ENABLED, true)
         }
-        metricsContainer.report(StringListMetrics.KOTLIN_COMPILER_EXECUTION_POLICY, executionPolicy.propertyValue)
+        metricsContainer.report(StringMetrics.KOTLIN_COMPILER_EXECUTION_POLICY, executionPolicy.propertyValue)
     }
 }
 
@@ -328,7 +327,7 @@
         wasmCompilerMode: String,
         metricsConsumer: StatisticsValuesConsumer,
     ) {
-        metricsConsumer.report(StringListMetrics.WASM_COMPILER_MODE, wasmCompilerMode)
+        metricsConsumer.report(StringMetrics.WASM_COMPILER_MODE, wasmCompilerMode)
         metricsConsumer.report(BooleanMetrics.WASM_IR_INCREMENTAL, incrementalWasm)
     }
 }
@@ -362,10 +361,10 @@
             val isExecutableConfigured = jsTarget.binaries.withType<Executable>().isNotEmpty()
             project.addConfigurationMetrics { metricContainer ->
                 when {
-                    isLibraryConfigured && isExecutableConfigured -> metricContainer.put(StringListMetrics.JS_BINARY_TYPE, "both")
-                    isLibraryConfigured -> metricContainer.put(StringListMetrics.JS_BINARY_TYPE, "library")
-                    isExecutableConfigured -> metricContainer.put(StringListMetrics.JS_BINARY_TYPE, "executable")
-                    !isExecutableConfigured && !isLibraryConfigured -> metricContainer.put(StringListMetrics.JS_BINARY_TYPE, "none")
+                    isLibraryConfigured && isExecutableConfigured -> metricContainer.put(StringMetrics.JS_BINARY_TYPE, "both")
+                    isLibraryConfigured -> metricContainer.put(StringMetrics.JS_BINARY_TYPE, "library")
+                    isExecutableConfigured -> metricContainer.put(StringMetrics.JS_BINARY_TYPE, "executable")
+                    !isExecutableConfigured && !isLibraryConfigured -> metricContainer.put(StringMetrics.JS_BINARY_TYPE, "none")
                 }
             }
         }
@@ -376,10 +375,10 @@
     internal fun collectMetrics(isBrowserConfigured: Boolean, isNodejsConfigured: Boolean, project: Project) {
         project.addConfigurationMetrics { metricContainer ->
             when {
-                isBrowserConfigured && isNodejsConfigured -> metricContainer.put(StringListMetrics.JS_TARGET_MODE, "both")
-                isBrowserConfigured -> metricContainer.put(StringListMetrics.JS_TARGET_MODE, "browser")
-                isNodejsConfigured -> metricContainer.put(StringListMetrics.JS_TARGET_MODE, "nodejs")
-                !isBrowserConfigured && !isNodejsConfigured -> metricContainer.put(StringListMetrics.JS_TARGET_MODE, "none")
+                isBrowserConfigured && isNodejsConfigured -> metricContainer.put(StringMetrics.JS_TARGET_MODE, "both")
+                isBrowserConfigured -> metricContainer.put(StringMetrics.JS_TARGET_MODE, "browser")
+                isNodejsConfigured -> metricContainer.put(StringMetrics.JS_TARGET_MODE, "nodejs")
+                !isBrowserConfigured && !isNodejsConfigured -> metricContainer.put(StringMetrics.JS_TARGET_MODE, "none")
             }
         }
     }
@@ -391,7 +390,7 @@
         val targetName = if (target is KotlinNativeTarget) target.konanTarget.name
         else target.platformType.name
         project.addConfigurationMetrics {
-            it.put(StringListMetrics.MPP_PLATFORMS, targetName)
+            it.put(StringMetrics.MPP_PLATFORMS, targetName)
         }
     }
 }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsBeanService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsBeanService.kt
index bc75eaa..30692aa 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsBeanService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatsBeanService.kt
@@ -15,7 +15,6 @@
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.StatisticsValuesConsumer
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import java.io.Closeable
 import java.io.File
@@ -157,16 +156,6 @@
     ) = runMetricMethodSafely(logger, "report metric ${metric.name}") {
         sessionLogger.report(metric, value, subprojectName, weight)
     } ?: false
-
-    internal fun report(
-        sessionLogger: BuildSessionLogger,
-        metric: StringListMetrics,
-        value: List<String>,
-        subprojectName: String?,
-        weight: Long? = null,
-    ) = runMetricMethodSafely(logger, "report metric ${metric.name}") {
-        sessionLogger.report(metric, value, subprojectName, weight)
-    } ?: false
 }
 
 internal class DefaultKotlinBuildStatsBeanService internal constructor(
@@ -184,10 +173,6 @@
     override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?): Boolean =
         report(kotlinBuildLogger.sessionLogger, metric, value, subprojectName, weight)
 
-    override fun report(metric: StringListMetrics, value: List<String>, subprojectName: String?, weight: Long?): Boolean =
-        report(kotlinBuildLogger.sessionLogger, metric, value, subprojectName, weight)
-
-
     override fun reportBoolean(name: String, value: Boolean, subprojectName: String?, weight: Long?): Boolean =
         report(BooleanMetrics.valueOf(name), value, subprojectName, weight)
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/NonSynchronizedMetricsContainer.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/NonSynchronizedMetricsContainer.kt
index 4b418d0..1a5b3c3 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/NonSynchronizedMetricsContainer.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/NonSynchronizedMetricsContainer.kt
@@ -3,7 +3,6 @@
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
 import org.jetbrains.kotlin.statistics.metrics.StatisticsValuesConsumer
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import java.io.Serializable
 
@@ -29,8 +28,6 @@
 
     private val stringMetrics = HashMap<MetricDescriptor<StringMetrics>, MutableList<Pair<String, Long?>>>()
 
-    private val stringListMetrics = HashMap<MetricDescriptor<StringListMetrics>, MutableList<Pair<List<String>, Long?>>>()
-
     private fun <V, K : MetricDescriptor<*>> putToCollection(
         collection: MutableMap<K, MutableList<Pair<V, Long?>>>,
         key: K,
@@ -55,11 +52,6 @@
         return true
     }
 
-    override fun report(metric: StringListMetrics, value: List<String>, subprojectName: String?, weight: Long?): Boolean {
-        putToCollection(stringListMetrics, MetricDescriptor(metric, subprojectName), value, weight)
-        return true
-    }
-
     open fun readFromMetricConsumer(metricConsumer: NonSynchronizedMetricsContainer) {
         metricConsumer.booleanMetrics.forEach {
             it.value.forEach { (value, weight) -> putToCollection(booleanMetrics, MetricDescriptor(it.key.name, it.key.subprojectName), value, weight) }
@@ -70,9 +62,6 @@
         metricConsumer.numericalMetrics.forEach {
             it.value.forEach { (value, weight) -> putToCollection(numericalMetrics, MetricDescriptor(it.key.name, it.key.subprojectName), value, weight) }
         }
-        metricConsumer.stringListMetrics.forEach {
-            it.value.forEach { (value, weight) -> putToCollection(stringListMetrics, MetricDescriptor(it.key.name, it.key.subprojectName), value, weight) }
-        }
     }
 
     open fun sendToConsumer(metricConsumer: StatisticsValuesConsumer) {
@@ -85,8 +74,5 @@
         stringMetrics.forEach {
             it.value.forEach { (value, weight) -> metricConsumer.report(it.key.name, value, it.key.subprojectName, weight) }
         }
-        stringListMetrics.forEach {
-            it.value.forEach { (value, weight) -> metricConsumer.report(it.key.name, value, it.key.subprojectName, weight) }
-        }
     }
 }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/SynchronizedMetricsContainer.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/SynchronizedMetricsContainer.kt
index 75a185c7..08b59df 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/SynchronizedMetricsContainer.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/SynchronizedMetricsContainer.kt
@@ -30,18 +30,6 @@
         }
     }
 
-    override fun report(metric: StringListMetrics, value: List<String>, subprojectName: String?, weight: Long?): Boolean {
-        synchronized(metricsLock) {
-            return super.report(metric, value, subprojectName, weight)
-        }
-    }
-
-    override fun report(metric: StringListMetrics, value: String, subprojectName: String?, weight: Long?): Boolean {
-        synchronized(metricsLock) {
-            return super.report(metric, value, subprojectName, weight)
-        }
-    }
-
     override fun readFromMetricConsumer(metricConsumer: NonSynchronizedMetricsContainer) {
         synchronized(metricsLock) {
             super.readFromMetricConsumer(metricConsumer)
@@ -53,4 +41,4 @@
             super.sendToConsumer(metricConsumer)
         }
     }
-}
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/old/Pre232IdeaKotlinBuildStatsBeanService.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/old/Pre232IdeaKotlinBuildStatsBeanService.kt
index 8536bf5..cd20bcf 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/old/Pre232IdeaKotlinBuildStatsBeanService.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/old/Pre232IdeaKotlinBuildStatsBeanService.kt
@@ -9,13 +9,12 @@
 import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsBeanService
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import javax.management.ObjectName
 
 internal class Pre232IdeaKotlinBuildStatsBeanService internal constructor(
     project: Project,
-    beanName: ObjectName,
+    beanName: ObjectName
 ) : KotlinBuildStatsBeanService(project, beanName),
     Pre232IdeaKotlinBuildStatsMXBean {
 
@@ -28,9 +27,6 @@
     override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?): Boolean =
         report(kotlinBuildLogger.sessionLogger, metric, value, subprojectName, weight)
 
-    override fun report(metric: StringListMetrics, value: List<String>, subprojectName: String?, weight: Long?): Boolean =
-        report(kotlinBuildLogger.sessionLogger, metric, value, subprojectName, weight)
-
     override fun reportBoolean(name: String, value: Boolean, subprojectName: String?, weight: Long?): Boolean =
         report(BooleanMetrics.valueOf(name), value, subprojectName, weight)
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/fus/fusTestUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/fus/fusTestUtils.kt
index 4986a96..459fc8a 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/fus/fusTestUtils.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/fus/fusTestUtils.kt
@@ -13,7 +13,6 @@
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
 import org.jetbrains.kotlin.statistics.metrics.StatisticsValuesConsumer
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import kotlin.test.assertNotNull
 
@@ -51,7 +50,6 @@
     val booleanMetrics = mutableMapOf<BooleanMetrics, Boolean>()
     val numericalMetrics = mutableMapOf<NumericalMetrics, Long>()
     val stringMetrics = mutableMapOf<StringMetrics, String>()
-    val stringListMetrics = mutableMapOf<StringListMetrics, List<String>>()
 
     override fun report(
         metric: BooleanMetrics,
@@ -82,9 +80,4 @@
         stringMetrics[metric] = value
         return true
     }
-
-    override fun report(metric: StringListMetrics, value: List<String>, subprojectName: String?, weight: Long?): Boolean {
-        stringListMetrics[metric] = value
-        return true
-    }
-}
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatHandlerTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatHandlerTest.kt
index 39323ba..1a33e02 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatHandlerTest.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/plugin/statistics/KotlinBuildStatHandlerTest.kt
@@ -8,7 +8,6 @@
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
 import org.jetbrains.kotlin.konan.target.KonanTarget
 import org.jetbrains.kotlin.statistics.metrics.StringAnonymizationPolicy
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import kotlin.test.Test
 
@@ -16,7 +15,7 @@
 
     @Test // Checks that all KonanTarget names are presented in MPP_PLATFORMS statistic's report validator
     fun mppPlatformsShouldContainAllKonanTargetsTest() {
-        val regex = Regex(StringListMetrics.MPP_PLATFORMS.anonymization.validationRegexp())
+        val regex = Regex(StringMetrics.MPP_PLATFORMS.anonymization.validationRegexp())
 
         val konanTargetsMissedInMppPlatforms = KonanTarget::class.sealedSubclasses
             .mapNotNull { sealedClass -> sealedClass.objectInstance }
@@ -29,7 +28,7 @@
 
     @Test // Checks that all KotlinPlatformType names are presented in MPP_PLATFORMS statistic's report validator
     fun mppPlatformsShouldContainAllKotlinPlatformTypeTest() {
-        val regex = Regex(StringListMetrics.MPP_PLATFORMS.anonymization.validationRegexp())
+        val regex = Regex(StringMetrics.MPP_PLATFORMS.anonymization.validationRegexp())
 
         val kotlinPlatformTypesMissedInMppPlatforms = KotlinPlatformType.values()
             .map { platformType -> platformType.name }
@@ -44,7 +43,7 @@
     @Test // Checks that only values listed in KotlinPlatformType and KonanTarget are included in MPP_PLATFORMS
     fun mppPlatformsShouldContainOnlyKonanTargetsAndKotlinPlatformTypeTest() {
         val allowedMppValues =
-            (StringListMetrics.MPP_PLATFORMS.anonymization as StringAnonymizationPolicy.AllowedListAnonymizer)
+            (StringMetrics.MPP_PLATFORMS.anonymization as StringAnonymizationPolicy.AllowedListAnonymizer)
                 .allowedValues
 
         val kotlinPlatformTypesMissedInMppPlatforms = KotlinPlatformType.values()
@@ -61,4 +60,4 @@
                     " but they are presented neither in konan targets nor in kotlin platform types"
         }
     }
-}
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildFinishBuildServiceTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildFinishBuildServiceTest.kt
index 91b5dd3..fb7e77c 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildFinishBuildServiceTest.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildFinishBuildServiceTest.kt
@@ -7,11 +7,10 @@
 
 import org.gradle.api.logging.LogLevel
 import org.jetbrains.kotlin.gradle.plugin.statistics.BuildFinishBuildService
-import org.jetbrains.kotlin.gradle.plugin.statistics.BuildFinishBuildService.Companion.findV2FusFilesByBuildId
+import org.jetbrains.kotlin.gradle.plugin.statistics.BuildFinishBuildService.Companion.findFusFilesByBuildId
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.junit.jupiter.api.io.TempDir
 import java.io.File
 import kotlin.test.Test
@@ -37,7 +36,7 @@
 
                 ${NumericalMetrics.COMPILATION_DURATION}=10
                 ${StringMetrics.OS_VERSION}=1.0.0-SNAPSHOT
-                ${StringListMetrics.IDES_INSTALLED}=invalid_version,AS,WC
+                ${StringMetrics.IDES_INSTALLED}=invalid_version,AS,WC
                 ${BooleanMetrics.ENABLED_COMPILER_REFERENCE_INDEX}=true
                 ${BooleanMetrics.KOTLIN_PROGRESSIVE_MODE}=true
  
@@ -65,7 +64,7 @@
             """
                 ${BooleanMetrics.BUILD_SCAN_BUILD_REPORT}=true
                 ${StringMetrics.OS_VERSION}=2.0.0-SNAPSHOT
-                ${StringListMetrics.IDES_INSTALLED}=IU
+                ${StringMetrics.IDES_INSTALLED}=IU
                 ${BooleanMetrics.ENABLED_COMPILER_REFERENCE_INDEX}=false
                 ${BooleanMetrics.KOTLIN_PROGRESSIVE_MODE}=false
                 BUILD FINISHED
@@ -88,7 +87,7 @@
         val profileContent = fusProfileFile.readText()
         assertContains(profileContent, "${NumericalMetrics.COMPILATION_DURATION}=20", message = "Profile file should contain valid metrics")
         assertContains(profileContent, "${StringMetrics.OS_VERSION}=2.0.0-snapshot")
-        assertContains(profileContent, "${StringListMetrics.IDES_INSTALLED}=AS;IU;UNEXPECTED-VALUE;WC")
+        assertContains(profileContent, "${StringMetrics.IDES_INSTALLED}=AS;IU;WC;UNEXPECTED-VALUE")
         assertContains(profileContent, "${BooleanMetrics.ENABLED_COMPILER_REFERENCE_INDEX}=true")
         assertContains(profileContent, "${BooleanMetrics.KOTLIN_PROGRESSIVE_MODE}=false")
         assertTrue("Profile file should not contain metrics from another build") {
@@ -121,7 +120,7 @@
             it.setLastModified(modificationTime + 1)
         }
 
-        val fusFiles = fusReportDirectory.findV2FusFilesByBuildId(buildId)?.map { it.name }
+        val fusFiles = fusReportDirectory.findFusFilesByBuildId(buildId)?.map { it.name }
         assertEquals(listOf("$buildId.2.plugin-profile", "$buildId.3.kotlin-profile", "$buildId.1.plugin-profile"), fusFiles)
     }
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildSessionLoggerTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildSessionLoggerTest.kt
index 49a94bd..78b0964 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildSessionLoggerTest.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/statistics/BuildSessionLoggerTest.kt
@@ -8,11 +8,10 @@
 import org.jetbrains.kotlin.statistics.BuildSessionLogger
 import org.jetbrains.kotlin.statistics.BuildSessionLogger.Companion.FUS_KOTLIN_FILE_NAME_SUFFIX
 import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer
-import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer.Companion.addMetricFromFusV2KotlinProfileFile
+import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer.Companion.addMetricFromFusKotlinProfileFile
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringAnonymizationPolicy
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringOverridePolicy
 import java.io.File
@@ -118,7 +117,7 @@
         //FUS metrics file should contain "BUILD FINISHED", otherwise it will be skipped as invalid
         reportFile.appendText(
             """
-            ${StringListMetrics.USE_FIR.name}=true
+            ${StringMetrics.USE_FIR.name}=true
             BUILD FINISHED
            
             """.trimIndent()
@@ -152,7 +151,7 @@
         assertEquals(3, metrics.size, "only invalidReportFile file should be filtered")
         assertEquals(
             1,
-            metrics.filter { it.getMetric(StringListMetrics.USE_FIR)?.getValue() == listOf("true") }.size,
+            metrics.filter { it.getMetric(StringMetrics.USE_FIR)?.getValue() == "true" }.size,
             "USE_FIR metric should be red from reportFile"
         )
 
@@ -164,7 +163,7 @@
 
         assertEquals(
             0,
-            metrics.filter { it.getMetric(StringListMetrics.USE_OLD_BACKEND)?.getValue() != null }.size,
+            metrics.filter { it.getMetric(StringMetrics.USE_OLD_BACKEND)?.getValue() != null }.size,
             "USE_OLD_BACKEND metric should be red"
         )
     }
@@ -198,71 +197,24 @@
             logger.report(metric, System.currentTimeMillis())
         }
 
-        for (metric in StringListMetrics.entries) {
-            when (val anonymization = metric.anonymization) {
-                is StringAnonymizationPolicy.ComponentVersionAnonymizer -> {
-                    logger.report(metric, "1.2.3")
-                    logger.report(metric, "1.2.3-SNAPSHOT")
-                }
-                is StringAnonymizationPolicy.AllowedListAnonymizer -> {
-                    anonymization.allowedValues.sorted().forEach {
-                        logger.report(metric, it)
-                    }
-                }
-                is StringAnonymizationPolicy.RegexControlled -> logger.report(metric, metric.name)
-                else -> {
-                    logger.report(metric, "value")
-                    logger.report(metric, metric.name)
-                }
-            }
-        }
-
         logger.finishBuildSession() // create kotlin-profile fus file with comma-separated values
 
         // read metrics from kotlin-profile file in old format with semicolon-separated values
-        val metricContainer = MetricsContainer.createMetricsContainerForV1ProfileFile()
+        val metricContainer = MetricsContainer.createMetricsContainerForProfileFile()
 
-        metricContainer.addMetricFromFusV2KotlinProfileFile(statsFolder.listFiles()?.single() ?: fail("Could not find stat file"))
+        metricContainer.addMetricFromFusKotlinProfileFile(statsFolder.listFiles()?.single() ?: fail("Could not find stat file"))
 
         for (metric in StringMetrics.entries) {
             val metricValue = metricContainer.getMetric(metric)?.getValue() ?: fail("Could not find metric ${metric.name}")
 
             when (val anonymization = metric.anonymization) {
-                is StringAnonymizationPolicy.ComponentVersionAnonymizer -> validateMetricValueBasedOnOverrideRule(
-                    metric,
-                    listOf(
-                        "1.2.3",
-                        "1.2.3-snapshot"
-                    ),
-                    metricValue
-                )
-                is StringAnonymizationPolicy.AllowedListAnonymizer -> validateMetricValueBasedOnOverrideRule(
-                    metric,
-                    anonymization.allowedValues.sorted(),
-                    metricValue
-                )
-                is StringAnonymizationPolicy.RegexControlled -> assertMetricValueEquals(metric.name, metric.name, metricValue)
+                is StringAnonymizationPolicy.ComponentVersionAnonymizer -> validateMetricValueBasedOnOverrideRule(metric, listOf("1.2.3", "1.2.3-snapshot"), metricValue)
+                is StringAnonymizationPolicy.AllowedListAnonymizer -> validateMetricValueBasedOnOverrideRule(metric, anonymization.allowedValues.sorted(), metricValue)
+                is StringAnonymizationPolicy.RegexControlled -> assertMetricValueEquals(metric, metric.name, metricValue)
                 else -> validateMetricValueBasedOnOverrideRule(metric, listOf("value", metric.name), metricValue)
             }
         }
 
-        for (metric in StringListMetrics.entries) {
-            val metricValue = metricContainer.getMetric(metric)?.getValue() ?: fail("Could not find metric ${metric.name}")
-
-            when (val anonymization = metric.anonymization) {
-                is StringAnonymizationPolicy.AllowedListAnonymizer -> {
-                    val expectedValue = anonymization.allowedValues.sorted()
-
-                    assertEquals(
-                        expectedValue,
-                        metricValue,
-                        "Metric ${metric.name} contains unexpected value: expected $expectedValue, but found $metricValue"
-                    )
-                }
-                else -> fail("A $anonymization type should be supported here")
-            }
-        }
-
         for (metric in BooleanMetrics.entries) {
             assertTrue(metricContainer.getMetric(metric)?.getValue() != null, "Could not find metric ${metric.name}")
         }
@@ -274,20 +226,17 @@
 
     private fun validateMetricValueBasedOnOverrideRule(metric: StringMetrics, possibleExpectedValues: List<String>, actualValue: String) {
         when (metric.type) {
-            StringOverridePolicy.OVERRIDE -> assertMetricValueEquals(metric.name, possibleExpectedValues.last(), actualValue)
-            StringOverridePolicy.OVERRIDE_VERSION_IF_NOT_SET -> assertMetricValueEquals(
-                metric.name,
-                possibleExpectedValues.first(),
-                actualValue
-            )
+            StringOverridePolicy.OVERRIDE -> assertMetricValueEquals(metric, possibleExpectedValues.last(), actualValue)
+            StringOverridePolicy.OVERRIDE_VERSION_IF_NOT_SET -> assertMetricValueEquals(metric, possibleExpectedValues.first(), actualValue)
+            StringOverridePolicy.CONCAT -> assertMetricValueEquals(metric, possibleExpectedValues.joinToString(";"), actualValue)
         }
     }
 
-    private fun assertMetricValueEquals(metricName: String, expectedValue: String, actualValue: String) {
+    private fun assertMetricValueEquals(metric: StringMetrics, expectedValue: String, actualValue: String) {
         assertEquals(
             expectedValue,
             actualValue,
-            "Metric $metricName contains unexpected value: expected $expectedValue, but found $actualValue"
+            "Metric ${metric.name} contains unexpected value: expected $expectedValue, but found $actualValue"
         )
     }
 
diff --git a/libraries/tools/kotlin-gradle-statistics/ReadMe.md b/libraries/tools/kotlin-gradle-statistics/ReadMe.md
index c3cbd1f..55e0ba9 100644
--- a/libraries/tools/kotlin-gradle-statistics/ReadMe.md
+++ b/libraries/tools/kotlin-gradle-statistics/ReadMe.md
@@ -5,6 +5,5 @@
 * [BooleanMetrics.kt](src%2Fmain%2Fkotlin%2Forg%2Fjetbrains%2Fkotlin%2Fstatistics%2Fmetrics%2FBooleanMetrics.kt)
 * [NumericalMetrics.kt](src%2Fmain%2Fkotlin%2Forg%2Fjetbrains%2Fkotlin%2Fstatistics%2Fmetrics%2FNumericalMetrics.kt)
 * [StringMetrics.kt](src%2Fmain%2Fkotlin%2Forg%2Fjetbrains%2Fkotlin%2Fstatistics%2Fmetrics%2FStringMetrics.kt)
-* [StringListMetrics.kt](src%2Fmain%2Fkotlin%2Forg%2Fjetbrains%2Fkotlin%2Fstatistics%2Fmetrics%2FStringListMetrics.kt)
 
-The increasing of this value is necessary for auto increasing version in [KotlinGradleFUSCollector.kt](https://jetbrains.team/p/ij/repositories/intellij/files/community/plugins/kotlin/gradle/gradle/src/org/jetbrains/kotlin/idea/gradle/statistics/KotlinGradleFUSCollector.kt)
+The increasing of this value is necessary for auto increasing version in [KotlinGradleFUSCollector.kt](https://jetbrains.team/p/ij/repositories/intellij/files/community/plugins/kotlin/gradle/gradle/src/org/jetbrains/kotlin/idea/gradle/statistics/KotlinGradleFUSCollector.kt)
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/BuildSessionLogger.kt b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/BuildSessionLogger.kt
index b3567a1..280fdbd 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/BuildSessionLogger.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/BuildSessionLogger.kt
@@ -47,7 +47,7 @@
     private var buildSession: BuildSession? = null
 
     //New FUS file should use comma (,) as a separator, but for old FUS files a semicolon (;) is used
-    private val metricsContainer = MetricsContainer.createMetricsContainerForV2KotlinProfileFile(forceValuesValidation)
+    private val metricsContainer = MetricsContainer.createMetricsContainerForKotlinProfileFile(forceValuesValidation)
 
     @Synchronized
     fun startBuildSession(buildUid: String) {
@@ -116,8 +116,4 @@
 
     override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?) =
         metricsContainer.report(metric, value, subprojectName, weight)
-
-    override fun report(metric: StringListMetrics, value: List<String>, subprojectName: String?, weight: Long?) =
-        metricsContainer.report(metric, value, subprojectName, weight)
-
 }
diff --git a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/fileloggers/MetricsContainer.kt b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/fileloggers/MetricsContainer.kt
index a154a00..39ee9b2 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/fileloggers/MetricsContainer.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/fileloggers/MetricsContainer.kt
@@ -23,7 +23,7 @@
  */
 class MetricsContainer(
     private val forceValuesValidation: Boolean = false,
-    private val metricConcatContainerValuesSeparator: String = FUS_METRIC_SEPARATOR_FOR_BACKWARD_COMPATIBILITY_PROFILE_FILE,
+    private val metricValuesSeparator: String = FUS_METRIC_SEPARATOR_FOR_BACKWARD_COMPATIBILITY_PROFILE_FILE,
 ) : StatisticsValuesConsumer {
     data class MetricDescriptor(val name: String, val projectHash: String?) : Comparable<MetricDescriptor> {
         override fun compareTo(other: MetricDescriptor): Int {
@@ -44,8 +44,6 @@
 
     private val stringMetrics = TreeMap<MetricDescriptor, IMetricContainer<String>>()
 
-    private val stringListMetrics = TreeMap<MetricDescriptor, IMetricContainer<List<String>>>()
-
     companion object {
         private const val BUILD_SESSION_SEPARATOR = "BUILD FINISHED"
         private const val METRIC_SEPARATOR = '='
@@ -57,124 +55,91 @@
 
         private val stringMetricsMap = StringMetrics.values().associateBy(StringMetrics::name)
 
-        private val stringListMetricsMap = StringListMetrics.values().associateBy(StringListMetrics::name)
-
         private val booleanMetricsMap = BooleanMetrics.values().associateBy(BooleanMetrics::name)
 
         private val numericalMetricsMap = NumericalMetrics.values().associateBy(NumericalMetrics::name)
 
-        fun createMetricsContainerForV1ProfileFile(forceValuesValidation: Boolean = false) =
+        fun createMetricsContainerForProfileFile(forceValuesValidation: Boolean = false) =
             MetricsContainer(
                 forceValuesValidation = forceValuesValidation,
-                metricConcatContainerValuesSeparator = FUS_METRIC_SEPARATOR_FOR_BACKWARD_COMPATIBILITY_PROFILE_FILE
+                metricValuesSeparator = FUS_METRIC_SEPARATOR_FOR_BACKWARD_COMPATIBILITY_PROFILE_FILE
             )
 
-        fun createMetricsContainerForV2KotlinProfileFile(forceValuesValidation: Boolean = false) =
+        fun createMetricsContainerForKotlinProfileFile(forceValuesValidation: Boolean = false) =
             MetricsContainer(
                 forceValuesValidation = forceValuesValidation,
-                metricConcatContainerValuesSeparator = FUS_METRIC_SEPARATOR_FOR_KOTLIN_PROFILE_FILE
+                metricValuesSeparator = FUS_METRIC_SEPARATOR_FOR_KOTLIN_PROFILE_FILE
             )
 
         private fun MetricsContainer.addMetricToContainer(
             metricDescriptor: MetricDescriptor,
             representation: String,
+            separator: String = metricValuesSeparator,
         ) {
-            fun <MetricType, MetricContainer: IMetricContainer<*>> addValueFromStringPresentation(
-                metricTypeByMetricDescriptorName: Map<String, MetricType>,
-                metricContainerByMetricDescriptor: MutableMap<MetricDescriptor, MetricContainer>,
-                metricDescriptor: MetricDescriptor,
-                metricContainerFactory: MetricType.() -> MetricContainer,
-            ) {
-                val metricType = metricTypeByMetricDescriptorName[metricDescriptor.name] ?: return
+            stringMetricsMap[metricDescriptor.name]?.also { metricType ->
                 synchronized(metricsLock) {
-                    metricContainerByMetricDescriptor.getOrPut(metricDescriptor) {
-                        metricContainerFactory(metricType)
-                    }.addValueFromStringPresentation(representation)
+                    stringMetrics.getOrPut(metricDescriptor) {
+                        metricType.type.newMetricContainer()
+                    }.addValueFromStringPresentation(representation, separator)
                 }
             }
 
-            addValueFromStringPresentation(stringMetricsMap, stringMetrics, metricDescriptor) { type.newMetricContainer() }
-            addValueFromStringPresentation(stringListMetricsMap, stringListMetrics, metricDescriptor) { type.newMetricContainer() }
-            addValueFromStringPresentation(numericalMetricsMap, numericalMetrics, metricDescriptor) { type.newMetricContainer() }
-            addValueFromStringPresentation(booleanMetricsMap, booleanMetrics, metricDescriptor) { type.newMetricContainer() }
+            booleanMetricsMap[metricDescriptor.name]?.also { metricType ->
+                synchronized(metricsLock) {
+                    booleanMetrics.getOrPut(metricDescriptor) {
+                        metricType.type.newMetricContainer()
+                    }.addValueFromStringPresentation(representation, separator)
+                }
+            }
+
+            numericalMetricsMap[metricDescriptor.name]?.also { metricType ->
+                synchronized(metricsLock) {
+                    numericalMetrics.getOrPut(metricDescriptor) {
+                        metricType.type.newMetricContainer()
+                    }.addValueFromStringPresentation(representation, separator)
+                }
+            }
         }
 
         // for new Fus files a comma (,) separator is used, but for old FUS files a semicolon (;) is used
-        fun MetricsContainer.addMetricFromFusV2KotlinProfileFile(file: File) {
-            copy(fromContainer = deserializeV2KotlinProfileMetricsContainer(file))
-        }
-
-        fun deserializeV2KotlinProfileMetricsContainer(file: File): MetricsContainer {
-            val container = MetricsContainer(metricConcatContainerValuesSeparator = FUS_METRIC_SEPARATOR_FOR_KOTLIN_PROFILE_FILE)
+        private fun MetricsContainer.addMetricFromFusFile(file: File, separator: String) =
             FileChannel.open(Paths.get(file.toURI()), StandardOpenOption.WRITE, StandardOpenOption.READ).use { channel ->
                 BufferedReader(InputStreamReader(Channels.newInputStream(channel), ENCODING)).use {
                     it.forEachLine { line ->
                         if (line.contains(METRIC_SEPARATOR)) {
                             // format: metricName.hash=string representation
                             parseLine(line)?.also { (metricDescriptor, representation) ->
-                                container.addMetricToContainer(metricDescriptor, representation)
+                                addMetricToContainer(metricDescriptor, representation, separator)
                             }
                         }
                     }
                 }
             }
-            return container
-        }
 
-        fun deserializeV1ProfileFileContainersStream(channel: FileChannel): Sequence<MetricsContainer> {
-            return sequence {
-                var container =
-                    MetricsContainer(metricConcatContainerValuesSeparator = FUS_METRIC_SEPARATOR_FOR_BACKWARD_COMPATIBILITY_PROFILE_FILE)
-                BufferedReader(InputStreamReader(Channels.newInputStream(channel), ENCODING)).use {
-                    it.lineSequence().forEach { line ->
-                        if (BUILD_SESSION_SEPARATOR == line) {
-                            yield(container)
-                            container =
-                                MetricsContainer(metricConcatContainerValuesSeparator = FUS_METRIC_SEPARATOR_FOR_BACKWARD_COMPATIBILITY_PROFILE_FILE)
-                        } else if (line.contains(METRIC_SEPARATOR)) {
-                            // format: metricName.hash=string representation
-                            parseLine(line)?.also { (metricDescriptor, representation) ->
-                                container.addMetricToContainer(
-                                    metricDescriptor,
-                                    representation,
-                                )
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        fun MetricsContainer.copy(fromContainer: MetricsContainer) {
-            val toContainer = this
-
-            fun <MetricValue> copy(
-                fromContainerMetrics: Map<MetricDescriptor, IMetricContainer<MetricValue>>,
-                toContainerMetrics: MutableMap<MetricDescriptor, IMetricContainer<MetricValue>>,
-                toContainerMetricContainerFactory: (MetricDescriptor) -> IMetricContainer<MetricValue>,
-            ) {
-                fromContainerMetrics.forEach { (metricDescriptor, metricContainer) ->
-                    val value = metricContainer.getValue() ?: return@forEach
-                    toContainerMetrics.getOrPut(metricDescriptor) {
-                        toContainerMetricContainerFactory(metricDescriptor)
-                    }.addValue(value, null)
-                }
-            }
-
-            copy(fromContainer.stringMetrics, toContainer.stringMetrics) { stringMetricsMap[it.name]?.type!!.newMetricContainer() }
-            copy(fromContainer.stringListMetrics,toContainer.stringListMetrics) { stringListMetricsMap[it.name]?.type!!.newMetricContainer() }
-            copy(fromContainer.numericalMetrics, toContainer.numericalMetrics) { numericalMetricsMap[it.name]?.type!!.newMetricContainer() }
-            copy(fromContainer.booleanMetrics, toContainer.booleanMetrics) { booleanMetricsMap[it.name]?.type!!.newMetricContainer() }
-        }
+        fun MetricsContainer.addMetricFromFusKotlinProfileFile(file: File) =
+            addMetricFromFusFile(file, separator = FUS_METRIC_SEPARATOR_FOR_KOTLIN_PROFILE_FILE)
 
         // This method also used IntelliJ project in KotlinGradleFUSLoggerProcessor#process.
         // It expects to read a fus file with a semicolon (;) separator for metric values.
         fun readFromFile(file: File, consumer: (MetricsContainer) -> Unit): Boolean {
             val channel = FileChannel.open(Paths.get(file.toURI()), StandardOpenOption.WRITE, StandardOpenOption.READ)
             channel.tryLock() ?: return false
+
+            val inputStream = Channels.newInputStream(channel)
+
             try {
-                deserializeV1ProfileFileContainersStream(channel).forEach {
-                    consumer(it)
+                var container = MetricsContainer()
+                // Note: close is called at forEachLine
+                BufferedReader(InputStreamReader(inputStream, ENCODING)).forEachLine { line ->
+                    if (BUILD_SESSION_SEPARATOR == line) {
+                        consumer.invoke(container)
+                        container = MetricsContainer()
+                    } else if (line.contains(METRIC_SEPARATOR)) {
+                        // format: metricName.hash=string representation
+                        parseLine(line)?.also { (metricDescriptor, representation) ->
+                            container.addMetricToContainer(metricDescriptor, representation)
+                        }
+                    }
                 }
             } finally {
                 channel.close()
@@ -194,35 +159,33 @@
         }
 
         fun MetricsContainer.createValidateAndAnonymizeCopy(): MetricsContainer {
-            fun <MetricType, MetricValue> reportMetrics(
-                metrics: Map<MetricDescriptor, IMetricContainer<MetricValue>>,
-                metricTypeByMetricDescriptorName: Map<String, MetricType>,
-                report: (metric: MetricType, value: MetricValue, projectHash: String?) -> (Unit),
-            ) {
-                metrics.forEach { (metricDescriptor, container) ->
-                    val value = container.getValue() ?: return@forEach
-                    val metricType = metricTypeByMetricDescriptorName[metricDescriptor.name] ?: return@forEach
-                    report(metricType, value, metricDescriptor.projectHash)
+            val metricsContainer = MetricsContainer(forceValuesValidation, metricValuesSeparator)
+            numericalMetrics.forEach { (metricDescriptor, container) ->
+                val metric = numericalMetricsMap[metricDescriptor.name]
+                val value = container.getValue()
+                if (metric != null && value != null) {
+                    metricsContainer.report(metric, value, metricDescriptor.projectHash, null)
                 }
             }
-
-            val metricsContainer = MetricsContainer(forceValuesValidation, metricConcatContainerValuesSeparator)
-            reportMetrics(numericalMetrics, numericalMetricsMap) { metric, value, projectHash ->
-                metricsContainer.report(metric, value, projectHash, null)
+            booleanMetrics.forEach { (metricDescriptor, container) ->
+                val metric = booleanMetricsMap[metricDescriptor.name]
+                val value = container.getValue()
+                if (metric != null && value != null) {
+                    metricsContainer.report(metric, value, metricDescriptor.projectHash, null)
+                }
             }
-            reportMetrics(booleanMetrics, booleanMetricsMap) { metric, value, projectHash ->
-                metricsContainer.report(metric, value, projectHash, null)
-            }
-            reportMetrics(stringMetrics, stringMetricsMap) { metric, value, projectHash ->
-                metricsContainer.report(metric, value, projectHash, null)
-            }
-            reportMetrics(stringListMetrics, stringListMetricsMap) { metric, value, projectHash ->
-                metricsContainer.report(metric, value, projectHash, null)
+            stringMetrics.forEach { (metricDescriptor, container) ->
+                val metric = stringMetricsMap[metricDescriptor.name]
+                val value = container.getValue()
+                if (metric != null && value != null) {
+                    metricsContainer.report(metric, value, metricDescriptor.projectHash, null)
+                }
             }
             return metricsContainer
         }
     }
 
+
     private fun processProjectName(subprojectName: String?, perProject: Boolean) =
         if (perProject && subprojectName != null) sha256(subprojectName) else null
 
@@ -233,7 +196,7 @@
         val projectHash = getProjectHash(metric.perProject, subprojectName)
         synchronized(metricsLock) {
             val metricContainer = booleanMetrics.getOrPut(MetricDescriptor(metric.name, projectHash)) { metric.type.newMetricContainer() }
-            metricContainer.addValue(metric.anonymization.anonymize(value, metricConcatContainerValuesSeparator), weight)
+            metricContainer.addValue(metric.anonymization.anonymize(value, metricValuesSeparator), weight)
         }
         return true
     }
@@ -242,93 +205,44 @@
         val projectHash = getProjectHash(metric.perProject, subprojectName)
         synchronized(metricsLock) {
             val metricContainer = numericalMetrics.getOrPut(MetricDescriptor(metric.name, projectHash)) { metric.type.newMetricContainer() }
-            metricContainer.addValue(metric.anonymization.anonymize(value, metricConcatContainerValuesSeparator), weight)
+            metricContainer.addValue(metric.anonymization.anonymize(value, metricValuesSeparator), weight)
         }
         return true
     }
 
+    internal fun validateMetric(metric: StringMetrics, value: String) {
+        if (value.contains(UNEXPECTED_VALUE) || !value.matches(Regex(metric.anonymization.validationRegexp(metricValuesSeparator)))) {
+            throw MetricValueValidationFailed("Metric ${metric.name} has value [${value}]. Validation regex: ${metric.anonymization.validationRegexp()}.")
+        }
+    }
+
+    internal fun anonymizeMetric(metric: StringMetrics, value: String) = metric.anonymization.anonymize(value, metricValuesSeparator)
+
     override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?): Boolean {
         val projectHash = getProjectHash(metric.perProject, subprojectName)
         synchronized(metricsLock) {
             val metricContainer = stringMetrics.getOrPut(MetricDescriptor(metric.name, projectHash)) { metric.type.newMetricContainer() }
 
-            val anonymizedValue = anonymizeMetric(metric.anonymization, value)
+            val anonymizedValue = anonymizeMetric(metric, value)
             if (forceValuesValidation && !metric.anonymization.anonymizeOnIdeSize()) {
-                validateMetric(metric.name, metric.anonymization, anonymizedValue)
+                validateMetric(metric, anonymizedValue)
             }
             metricContainer.addValue(anonymizedValue, weight)
         }
         return true
     }
 
-    override fun report(metric: StringListMetrics, value: List<String>, subprojectName: String?, weight: Long?): Boolean {
-        val projectHash = getProjectHash(metric.perProject, subprojectName)
-        synchronized(metricsLock) {
-
-            val metricContainer =
-                stringListMetrics.getOrPut(MetricDescriptor(metric.name, projectHash)) { metric.type.newMetricContainer() }
-
-            val anonymizedValues = value.map {
-                val anonymizedValue = anonymizeMetric(metric.anonymization, it)
-                if (forceValuesValidation && !metric.anonymization.anonymizeOnIdeSize()) {
-                    validateMetric(metric.name, metric.anonymization, anonymizedValue)
-                }
-                anonymizedValue
-            }
-
-            metricContainer.addValue(anonymizedValues, weight)
-        }
-        return true
-    }
-
-    internal fun validateMetric(metricName: String, anonymization: StringAnonymizationPolicy, value: String) {
-        if (value.contains(UNEXPECTED_VALUE) || !value.matches(
-                Regex(
-                    anonymization.validationRegexp(
-                        metricConcatContainerValuesSeparator
-                    )
-                )
-            )
-        ) {
-            throw MetricValueValidationFailed("Metric $metricName has value [${value}]. Validation regex: ${anonymization.validationRegexp()}.")
-        }
-    }
-
-    internal fun anonymizeMetric(anonymization: StringAnonymizationPolicy, value: String) =
-        anonymization.anonymize(value, metricConcatContainerValuesSeparator)
-
-    fun StringListOverridePolicy.newMetricContainer(): IMetricContainer<List<String>> = when (this) {
-        StringListOverridePolicy.CONCAT -> ConcatMetricContainer(metricConcatContainerValuesSeparator)
-    }
-
-    fun StringOverridePolicy.newMetricContainer() = when (this) {
-        StringOverridePolicy.OVERRIDE -> OverrideStringMetricContainer()
-        StringOverridePolicy.OVERRIDE_VERSION_IF_NOT_SET -> OverrideVersionMetricContainer()
-    }
-
-    fun BooleanOverridePolicy.newMetricContainer() = when (this) {
-        BooleanOverridePolicy.OVERRIDE -> OverrideBooleanMetricContainer()
-        BooleanOverridePolicy.OR -> OrMetricContainer()
-    }
-
-    fun NumberOverridePolicy.newMetricContainer() = when (this) {
-        NumberOverridePolicy.OVERRIDE -> OverrideLongMetricContainer()
-        NumberOverridePolicy.SUM -> SumMetricContainer()
-        NumberOverridePolicy.AVERAGE -> AverageMetricContainer()
-    }
-
     fun flush(writer: BufferedWriter) {
         val allMetrics = TreeMap<MetricDescriptor, IMetricContainer<out Any>>()
         synchronized(metricsLock) {
             allMetrics.putAll(numericalMetrics)
             allMetrics.putAll(booleanMetrics)
             allMetrics.putAll(stringMetrics)
-            allMetrics.putAll(stringListMetrics)
         }
         writer.appendLine()
         for (entry in allMetrics.entries) {
             val suffix = if (entry.key.projectHash == null) "" else ".${entry.key.projectHash}"
-            writer.appendLine("${entry.key.name}$suffix$METRIC_SEPARATOR${entry.value.toStringRepresentation()}")
+            writer.appendLine("${entry.key.name}$suffix$METRIC_SEPARATOR${entry.value.toStringRepresentation(metricValuesSeparator)}")
         }
 
         writer.appendLine(BUILD_SESSION_SEPARATOR)
@@ -337,7 +251,6 @@
             stringMetrics.clear()
             booleanMetrics.clear()
             numericalMetrics.clear()
-            stringListMetrics.clear()
         }
     }
 
@@ -349,17 +262,13 @@
         stringMetrics[MetricDescriptor(metric.name, null)]
     }
 
-    fun getStringMetricPresentation(metric: StringMetrics): String? = getMetric(metric)?.toStringRepresentation()
+    fun getStringMetricPresentation(metric: StringMetrics): String? = getMetric(metric)?.toStringRepresentation(metricValuesSeparator)
 
     fun getMetric(metric: BooleanMetrics): IMetricContainer<Boolean>? = synchronized(metricsLock) {
         booleanMetrics[MetricDescriptor(metric.name, null)]
     }
 
-    fun getMetric(metric: StringListMetrics): IMetricContainer<List<String>>? = synchronized(metricsLock) {
-        stringListMetrics[MetricDescriptor(metric.name, null)]
-    }
-
     fun isEmpty(): Boolean = synchronized(metricsLock) {
-        numericalMetrics.isEmpty() && booleanMetrics.isEmpty() && stringMetrics.isEmpty() && stringListMetrics.isEmpty()
+        numericalMetrics.isEmpty() && booleanMetrics.isEmpty() && stringMetrics.isEmpty()
     }
 }
diff --git a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricContainers.kt b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricContainers.kt
index b920a0e..6051c8a 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricContainers.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricContainers.kt
@@ -5,20 +5,26 @@
 
 package org.jetbrains.kotlin.statistics.metrics
 
+import org.jetbrains.kotlin.statistics.DEFAULT_SEPARATOR
 import java.io.Serializable
 import java.util.*
 
-// This container is a value in a key/value pair such as MPP_PLATFORMS=...
 interface IMetricContainer<T> : Serializable {
     fun addValue(t: T, weight: Long? = null)
 
-    fun addValueFromStringPresentation(str: String)
+    fun addValueFromStringPresentation(str: String, separator: String)
 
-    fun toStringRepresentation(): String
+    fun toStringRepresentation(separator: String? = DEFAULT_SEPARATOR): String
 
     fun getValue(): T?
 }
 
+interface IMetricContainerFactory<T> {
+    fun newMetricContainer(): IMetricContainer<T>
+
+    fun fromStringRepresentation(state: String, separator: String = DEFAULT_SEPARATOR): IMetricContainer<T>?
+}
+
 abstract class OverrideMetricContainer<T>() : IMetricContainer<T> {
     internal var myValue: T? = null
 
@@ -26,7 +32,7 @@
         myValue = t
     }
 
-    override fun toStringRepresentation(): String {
+    override fun toStringRepresentation(separator: String?): String {
         return myValue?.toString() ?: "null"
     }
 
@@ -34,19 +40,19 @@
 }
 
 open class OverrideStringMetricContainer() : OverrideMetricContainer<String>() {
-    override fun addValueFromStringPresentation(str: String) {
+    override fun addValueFromStringPresentation(str: String, separator: String) {
         addValue(str, null)
     }
 }
 
 open class OverrideLongMetricContainer() : OverrideMetricContainer<Long>() {
-    override fun addValueFromStringPresentation(str: String) {
+    override fun addValueFromStringPresentation(str: String, separator: String) {
         str.toLongOrNull()?.also { addValue(it, null) }
     }
 }
 
 open class OverrideBooleanMetricContainer(): OverrideMetricContainer<Boolean>() {
-    override fun addValueFromStringPresentation(str: String) {
+    override fun addValueFromStringPresentation(str: String, separator: String) {
         str.toBooleanStrictOrNull()?.also { addValue(it, null) }
     }
 }
@@ -62,7 +68,7 @@
         }
     }
 
-    override fun addValueFromStringPresentation(str: String) {
+    override fun addValueFromStringPresentation(str: String, separator: String) {
         addValue(str, null)
     }
 }
@@ -76,7 +82,7 @@
         myValue = (myValue ?: 0) + t
     }
 
-    override fun addValueFromStringPresentation(str: String) {
+    override fun addValueFromStringPresentation(str: String, separator: String) {
         str.toLongOrNull()?.also { addValue(it, null) }
     }
 }
@@ -96,11 +102,11 @@
         totalWeight += w
     }
 
-    override fun addValueFromStringPresentation(str: String) {
+    override fun addValueFromStringPresentation(str: String, separator: String) {
         str.toLongOrNull()?.also { addValue(it, null) }
     }
 
-    override fun toStringRepresentation(): String {
+    override fun toStringRepresentation(separator: String?): String {
         return getValue()?.toString() ?: "null"
     }
 
@@ -118,25 +124,29 @@
         myValue = (myValue ?: false) || t
     }
 
-    override fun addValueFromStringPresentation(str: String) {
+    override fun addValueFromStringPresentation(str: String, separator: String) {
         str.toBooleanStrictOrNull()?.also { addValue(it, null) }
     }
 }
 
-class ConcatMetricContainer(val separator: String) : IMetricContainer<List<String>> {
+class ConcatMetricContainer() : IMetricContainer<String> {
     private val myValues = TreeSet<String>()
 
-    override fun addValue(t: List<String>, weight: Long?) {
-        myValues.addAll(t)
+    constructor(values: Collection<String>) : this() {
+        myValues.addAll(values)
     }
 
-    override fun addValueFromStringPresentation(str: String) {
-        addValue(str.split(separator), null)
+    override fun addValue(t: String, weight: Long?) {
+        myValues.add(t)
     }
 
-    override fun toStringRepresentation(): String {
-        return myValues.sorted().joinToString(separator)
+    override fun addValueFromStringPresentation(str: String, separator: String) {
+        str.split(separator).forEach { addValue(it, null) }
     }
 
-    override fun getValue() = myValues.toList()
+    override fun toStringRepresentation(separator: String?): String {
+        return myValues.sorted().joinToString(separator.toString())
+    }
+
+    override fun getValue() = toStringRepresentation()
 }
diff --git a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricPolicies.kt b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricPolicies.kt
index 0323c18..67d81e8 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricPolicies.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/MetricPolicies.kt
@@ -10,13 +10,30 @@
 import org.jetbrains.kotlin.statistics.anonymizeComponentVersion
 import kotlin.math.abs
 
-enum class StringListOverridePolicy {
-    CONCAT,
-}
 
-enum class StringOverridePolicy {
-    OVERRIDE,
-    OVERRIDE_VERSION_IF_NOT_SET
+enum class StringOverridePolicy : IMetricContainerFactory<String> {
+    OVERRIDE {
+        override fun newMetricContainer(): IMetricContainer<String> = OverrideStringMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<String>? =
+            OverrideStringMetricContainer().also {
+                it.addValueFromStringPresentation(state, separator)
+            }
+    },
+    OVERRIDE_VERSION_IF_NOT_SET {
+        override fun newMetricContainer(): IMetricContainer<String> = OverrideVersionMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<String>? =
+            OverrideVersionMetricContainer(state)
+    },
+    CONCAT {
+        override fun newMetricContainer(): IMetricContainer<String> = ConcatMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<String>? = ConcatMetricContainer().also {
+            it.addValueFromStringPresentation(state, separator)
+        }
+    }
+
     //Should be useful counting container?
 }
 
@@ -29,15 +46,46 @@
     }
 }
 
-enum class NumberOverridePolicy  {
-    OVERRIDE,
-    SUM,
-    AVERAGE
+enum class NumberOverridePolicy : IMetricContainerFactory<Long> {
+    OVERRIDE {
+        override fun newMetricContainer(): IMetricContainer<Long> = OverrideLongMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<Long>? = applyIfLong(state) { value ->
+            OverrideLongMetricContainer().also { it.addValue(value) }
+        }
+    },
+    SUM {
+        override fun newMetricContainer(): IMetricContainer<Long> = SumMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<Long>? = SumMetricContainer().also {
+            it.addValueFromStringPresentation(state, separator)
+        }
+    },
+    AVERAGE {
+        override fun newMetricContainer(): IMetricContainer<Long> = AverageMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<Long>? = AverageMetricContainer().also {
+            it.addValueFromStringPresentation(state, separator)
+        }
+
+    }
 }
 
-enum class BooleanOverridePolicy {
-    OVERRIDE,
-    OR,
+enum class BooleanOverridePolicy : IMetricContainerFactory<Boolean> {
+    OVERRIDE {
+        override fun newMetricContainer(): IMetricContainer<Boolean> = OverrideBooleanMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<Boolean>? =
+            OverrideBooleanMetricContainer().also {
+                it.addValueFromStringPresentation(state, separator)
+            }
+    },
+    OR {
+        override fun newMetricContainer(): IMetricContainer<Boolean> = OrMetricContainer()
+
+        override fun fromStringRepresentation(state: String, separator: String): IMetricContainer<Boolean>? =
+            OrMetricContainer(state.toBoolean())
+    }
 
     // may be add disctribution counter metric container
 }
diff --git a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StatisticsValues.kt b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StatisticsValues.kt
index d902fb7..2ae074f 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StatisticsValues.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StatisticsValues.kt
@@ -11,8 +11,4 @@
     fun report(metric: NumericalMetrics, value: Long, subprojectName: String? = null, weight: Long? = null): Boolean
 
     fun report(metric: StringMetrics, value: String, subprojectName: String? = null, weight: Long? = null): Boolean
-
-    fun report(metric: StringListMetrics, value: List<String>, subprojectName: String? = null, weight: Long? = null): Boolean
-
-    fun report(metric: StringListMetrics, value: String, subprojectName: String? = null, weight: Long? = null): Boolean = report(metric, listOf(value), subprojectName, weight)
 }
diff --git a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StringListMetrics.kt b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StringListMetrics.kt
deleted file mode 100644
index 5cc07bd..0000000
--- a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StringListMetrics.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2010-2026 JetBrains s.r.o. and Kotlin Programming Language contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
- */
-
-package org.jetbrains.kotlin.statistics.metrics
-
-import org.jetbrains.kotlin.statistics.metrics.StringAnonymizationPolicy.AllowedListAnonymizer
-import org.jetbrains.kotlin.statistics.metrics.StringListOverridePolicy.CONCAT
-
-enum class StringListMetrics(
-    val type: StringListOverridePolicy,
-    val anonymization: StringAnonymizationPolicy,
-    val perProject: Boolean = false,
-) {
-    IDES_INSTALLED(CONCAT, AllowedListAnonymizer(listOf("AS", "OC", "CL", "IU", "IC", "WC"))),
-
-    // Build script
-    MPP_PLATFORMS(
-        CONCAT, AllowedListAnonymizer(
-            listOf(
-                "common",
-                "native",
-                "jvm",
-                "js",
-                "android_x64",
-                "android_x86",
-                "androidJvm",
-                "android_arm32",
-                "android_arm64",
-                "ios_arm64",
-                "ios_simulator_arm64",
-                "ios_x64",
-                "watchos_arm32",
-                "watchos_arm64",
-                "watchos_x64",
-                "watchos_simulator_arm64",
-                "watchos_device_arm64",
-                "tvos_arm64",
-                "tvos_x64",
-                "tvos_simulator_arm64",
-                "linux_arm32_hfp",
-                "linux_arm64",
-                "linux_x64",
-                "macos_x64",
-                "macos_arm64",
-                "mingw_x64",
-                "wasm"
-            )
-        )
-    ),
-
-    JS_COMPILER_MODE(CONCAT, AllowedListAnonymizer(listOf("ir", "legacy", "both", "UNKNOWN"))),
-    JS_GENERATE_EXECUTABLE_DEFAULT(CONCAT, AllowedListAnonymizer(listOf("true", "false"))),
-    JS_TARGET_MODE(CONCAT, AllowedListAnonymizer(listOf("both", "browser", "nodejs", "none"))),
-    JS_BINARY_TYPE(CONCAT, AllowedListAnonymizer(listOf("both", "library", "executable", "none"))),
-
-    WASM_COMPILER_MODE(CONCAT, AllowedListAnonymizer(listOf("monolith", "multimodule-open-world", "multimodule-closed-world"))),
-
-    // Compiler parameters
-    JVM_DEFAULTS(CONCAT, AllowedListAnonymizer(listOf("enable", "no-compatibility", "disable"))),
-    USE_OLD_BACKEND(CONCAT, AllowedListAnonymizer(listOf("true", "false"))),
-    USE_FIR(CONCAT, AllowedListAnonymizer(listOf("true", "false"))),
-    KOTLIN_COMPILER_EXECUTION_POLICY(CONCAT, AllowedListAnonymizer(listOf("in-process", "daemon"))),
-    JS_PROPERTY_LAZY_INITIALIZATION(CONCAT, AllowedListAnonymizer(listOf("true", "false")));
-
-
-    companion object {
-        const val VERSION = 1
-    }
-}
diff --git a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt
index ae32148..a715958 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/main/kotlin/org/jetbrains/kotlin/statistics/metrics/StringMetrics.kt
@@ -7,7 +7,7 @@
 
 import org.jetbrains.kotlin.statistics.metrics.StringAnonymizationPolicy.*
 import org.jetbrains.kotlin.statistics.metrics.StringOverridePolicy.*
-import org.jetbrains.kotlin.statistics.metrics.StringListOverridePolicy.*
+
 
 enum class StringMetrics(val type: StringOverridePolicy, val anonymization: StringAnonymizationPolicy, val perProject: Boolean = false) {
 
@@ -18,6 +18,46 @@
     OS_TYPE(OVERRIDE, RegexControlled("(Windows|Windows |Windows Server |Mac|Linux|FreeBSD|Solaris|Other|Mac OS X)\\d*", false)),
     OS_VERSION(OVERRIDE, ComponentVersionAnonymizer()),
 
+    IDES_INSTALLED(CONCAT, AllowedListAnonymizer(listOf("AS", "OC", "CL", "IU", "IC", "WC"))),
+
+    // Build script
+    MPP_PLATFORMS(
+        CONCAT, AllowedListAnonymizer(
+            listOf(
+                "common",
+                "native",
+                "jvm",
+                "js",
+                "android_x64",
+                "android_x86",
+                "androidJvm",
+                "android_arm32",
+                "android_arm64",
+                "ios_arm64",
+                "ios_simulator_arm64",
+                "ios_x64",
+                "watchos_arm32",
+                "watchos_arm64",
+                "watchos_x64",
+                "watchos_simulator_arm64",
+                "watchos_device_arm64",
+                "tvos_arm64",
+                "tvos_x64",
+                "tvos_simulator_arm64",
+                "linux_arm32_hfp",
+                "linux_arm64",
+                "linux_x64",
+                "macos_x64",
+                "macos_arm64",
+                "mingw_x64",
+                "wasm"
+            )
+        )
+    ),
+    JS_COMPILER_MODE(CONCAT, AllowedListAnonymizer(listOf("ir", "legacy", "both", "UNKNOWN"))),
+
+    WASM_COMPILER_MODE(CONCAT, AllowedListAnonymizer(listOf("monolith", "multimodule-open-world", "multimodule-closed-world"))),
+
     // Component versions
     LIBRARY_SPRING_VERSION(OVERRIDE_VERSION_IF_NOT_SET, ComponentVersionAnonymizer()),
     LIBRARY_VAADIN_VERSION(OVERRIDE_VERSION_IF_NOT_SET, ComponentVersionAnonymizer()),
@@ -38,11 +78,23 @@
     // Features
     KOTLIN_LANGUAGE_VERSION(OVERRIDE, ComponentVersionAnonymizer()),
     KOTLIN_API_VERSION(OVERRIDE, ComponentVersionAnonymizer()),
+    JS_GENERATE_EXECUTABLE_DEFAULT(CONCAT, AllowedListAnonymizer(listOf("true", "false"))),
+    JS_TARGET_MODE(CONCAT, AllowedListAnonymizer(listOf("both", "browser", "nodejs", "none"))),
+    JS_BINARY_TYPE(CONCAT, AllowedListAnonymizer(listOf("both", "library", "executable", "none"))),
     JS_OUTPUT_GRANULARITY(OVERRIDE, RegexControlled("(whole_program|per_module|per_file)", false)),
     JS_ES_TARGET(OVERRIDE, AllowedListAnonymizer(listOf("es5", "es2015", "default"))),
-    JS_MODULE_SYSTEM(OVERRIDE, AllowedListAnonymizer(listOf("plain", "amd", "commonjs", "umd", "es", "default")));
+    JS_MODULE_SYSTEM(OVERRIDE, AllowedListAnonymizer(listOf("plain", "amd", "commonjs", "umd", "es", "default"))),
+
+    // Compiler parameters
+    JVM_DEFAULTS(CONCAT, AllowedListAnonymizer(listOf("enable", "no-compatibility", "disable"))),
+    USE_OLD_BACKEND(CONCAT, AllowedListAnonymizer(listOf("true", "false"))),
+    USE_FIR(CONCAT, AllowedListAnonymizer(listOf("true", "false"))),
+
+    KOTLIN_COMPILER_EXECUTION_POLICY(CONCAT, AllowedListAnonymizer(listOf("in-process", "daemon"))),
+    JS_PROPERTY_LAZY_INITIALIZATION(CONCAT, AllowedListAnonymizer(listOf("true", "false")));
+
 
     companion object {
-        const val VERSION = 12
+        const val VERSION = 11
     }
 }
diff --git a/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/MetricPolicyTest.kt b/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/MetricPolicyTest.kt
index a714f36..4dcc49c 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/MetricPolicyTest.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/MetricPolicyTest.kt
@@ -6,9 +6,10 @@
 package org.jetbrains.kotlin.statistics
 
 import org.jetbrains.kotlin.statistics.fileloggers.MetricsContainer
+import org.jetbrains.kotlin.statistics.metrics.ConcatMetricContainer
 import org.jetbrains.kotlin.statistics.metrics.NumberAnonymizationPolicy.RANDOM_10_PERCENT
 import org.jetbrains.kotlin.statistics.metrics.StringAnonymizationPolicy
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
+import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
@@ -60,12 +61,12 @@
     @Test
     fun versionStringValidation() {
         val separator = "0123"
-        val container = MetricsContainer(metricConcatContainerValuesSeparator = separator)
+        val container = MetricsContainer(metricValuesSeparator = separator)
         fun whenAdded(newValue: String, expected: String) {
-            container.report(StringListMetrics.MPP_PLATFORMS, newValue)
-            val currentValue = container.getMetric(StringListMetrics.MPP_PLATFORMS)!!.toStringRepresentation()
+            container.report(StringMetrics.MPP_PLATFORMS, newValue)
+            val currentValue = container.getStringMetricPresentation(StringMetrics.MPP_PLATFORMS)!!
             assertEquals(expected, currentValue)
-            val regex = StringListMetrics.MPP_PLATFORMS.anonymization.validationRegexp(separator)
+            val regex = StringMetrics.MPP_PLATFORMS.anonymization.validationRegexp(separator)
             assertTrue(currentValue.matches(Regex(regex)), "'${currentValue}' should match '${regex}'")
         }
         whenAdded("js", "js")
diff --git a/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/ModuleChangesCatchingTest.kt b/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/ModuleChangesCatchingTest.kt
index 9625869..1ab88e2 100644
--- a/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/ModuleChangesCatchingTest.kt
+++ b/libraries/tools/kotlin-gradle-statistics/src/test/kotlin/org/jetbrains/kotlin/statistics/ModuleChangesCatchingTest.kt
@@ -7,7 +7,6 @@
 
 import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
 import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
-import org.jetbrains.kotlin.statistics.metrics.StringListMetrics
 import org.jetbrains.kotlin.statistics.metrics.StringMetrics
 import org.junit.Test
 import java.io.File
@@ -15,7 +14,6 @@
 import java.nio.file.Path
 import java.nio.file.Paths
 import java.security.MessageDigest
-import kotlin.reflect.KClass
 import kotlin.test.assertEquals
 
 private const val SOURCE_CODE_RELATIVE_PATH =
@@ -23,18 +21,16 @@
 private const val BOOLEAN_METRICS_RELATIVE_PATH = "$SOURCE_CODE_RELATIVE_PATH/BooleanMetrics.kt"
 private const val STRING_METRICS_RELATIVE_PATH = "$SOURCE_CODE_RELATIVE_PATH/StringMetrics.kt"
 private const val NUMERICAL_METRICS_RELATIVE_PATH = "$SOURCE_CODE_RELATIVE_PATH/NumericalMetrics.kt"
-private const val STRING_LIST_METRICS_RELATIVE_PATH = "$SOURCE_CODE_RELATIVE_PATH/StringListMetrics.kt"
 
-private val STRING_METRICS_EXPECTED_VERSION_AND_HASH = Pair(12, "3ae4ad64e1d61f2627284d3f518e2d5e")
+private val STRING_METRICS_EXPECTED_VERSION_AND_HASH = Pair(11, "75e7b86c04e7cee3262093dcb21b493d")
 private val BOOLEAN_METRICS_EXPECTED_VERSION_AND_HASH = Pair(29, "1996c736f9263217f073e662baf41373")
 private val NUMERICAL_METRICS_EXPECTED_VERSION_AND_HASH = Pair(3, "bcc6f0dba7d9db8e58408f8c0ff57965")
-private val STRING_LIST_METRICS_EXPECTED_VERSION_AND_HASH = Pair(1, "a62836836049ec8726227799ddebad22")
 private val SOURCE_FOLDER_EXPECTED_VERSION_AND_HASH =
     Pair(
         STRING_METRICS_EXPECTED_VERSION_AND_HASH.first +
                 BOOLEAN_METRICS_EXPECTED_VERSION_AND_HASH.first +
-                NUMERICAL_METRICS_EXPECTED_VERSION_AND_HASH.first + STRING_LIST_METRICS_EXPECTED_VERSION_AND_HASH.first,
-        "626062cba4ec71e2306715a0a16909f3"
+                NUMERICAL_METRICS_EXPECTED_VERSION_AND_HASH.first,
+        "86fb86878cd730955f7685f935bfc152"
     )
 private const val HASH_ALG = "MD5"
 
@@ -53,7 +49,8 @@
             Pair(StringMetrics.VERSION, calculateFileChecksum(STRING_METRICS_RELATIVE_PATH))
         assertEquals(
             STRING_METRICS_EXPECTED_VERSION_AND_HASH, actualStringMetricsVersionAndHash,
-            errorMessage(StringMetrics::class)
+            "Hash of ${StringMetrics::class.qualifiedName} has been changed, please increase VERSION value. " +
+                    "Also you need to update hash and version in this test class."
         )
     }
 
@@ -66,7 +63,8 @@
             Pair(BooleanMetrics.VERSION, calculateFileChecksum(BOOLEAN_METRICS_RELATIVE_PATH))
         assertEquals(
             BOOLEAN_METRICS_EXPECTED_VERSION_AND_HASH, actualBooleanMetricsVersionAndHash,
-            errorMessage(BooleanMetrics::class)
+            "Hash of ${BooleanMetrics::class.qualifiedName} has been changed, please increase VERSION value. " +
+                    "Also you need to update hash and version in this test class."
         )
     }
 
@@ -79,39 +77,22 @@
             Pair(NumericalMetrics.VERSION, calculateFileChecksum(NUMERICAL_METRICS_RELATIVE_PATH))
         assertEquals(
             NUMERICAL_METRICS_EXPECTED_VERSION_AND_HASH, actualNumericalMetricsVersionAndHash,
-            errorMessage(NumericalMetrics::class)
+            "Hash of ${NumericalMetrics::class.qualifiedName} has been changed, please increase VERSION value. " +
+                    "Also you need to update hash and version in this test class."
         )
     }
 
-    /**
-     * Test checks for that the version of [StringListMetrics] was increased after changes in this file
-     */
-    @Test
-    fun testChecksCorrectChangingStringListMetricsVersion() {
-        val actualVersionAndHash =
-            Pair(StringListMetrics.VERSION, calculateFileChecksum(STRING_LIST_METRICS_RELATIVE_PATH))
-        assertEquals(
-            STRING_LIST_METRICS_EXPECTED_VERSION_AND_HASH, actualVersionAndHash,
-            errorMessage(StringListMetrics::class)
-        )
-    }
-
-    private fun errorMessage(clazz: KClass<*>): String =
-        "Hash of ${clazz.qualifiedName} has been changed, please increase VERSION value. " +
-                "Also you need to update hash and version in this test class."
-
     @Test
     fun testChecksTotalFilesChecksum() {
         val pathToExclude =
             setOf(
                 Paths.get(STRING_METRICS_RELATIVE_PATH).toAbsolutePath().toString(),
                 Paths.get(BOOLEAN_METRICS_RELATIVE_PATH).toAbsolutePath().toString(),
-                Paths.get(NUMERICAL_METRICS_RELATIVE_PATH).toAbsolutePath().toString(),
-                Paths.get(STRING_LIST_METRICS_RELATIVE_PATH).toAbsolutePath().toString()
+                Paths.get(NUMERICAL_METRICS_RELATIVE_PATH).toAbsolutePath().toString()
             )
         val actualSourceFolderVersionAndHash =
             Pair(
-                NumericalMetrics.VERSION + StringMetrics.VERSION + BooleanMetrics.VERSION + StringListMetrics.VERSION,
+                NumericalMetrics.VERSION + StringMetrics.VERSION + BooleanMetrics.VERSION,
                 calculateDirectoryCheckSum(SOURCE_CODE_RELATIVE_PATH, pathToExclude)
             )
         assertEquals(