Fixed possible hanging of metrics collection in KGP

#KT-50719 Fixed
This commit is contained in:
Hung Nguyen
2021-11-04 23:22:21 +03:00
committed by teamcity
parent 455b3143e7
commit 8d298bd25c
@@ -26,6 +26,8 @@ class MetricsContainer : IStatisticsValuesConsumer {
} }
} }
private val metricsLock = Object()
private val numericalMetrics = TreeMap<MetricDescriptor, IMetricContainer<Long>>() private val numericalMetrics = TreeMap<MetricDescriptor, IMetricContainer<Long>>()
private val booleanMetrics = TreeMap<MetricDescriptor, IMetricContainer<Boolean>>() private val booleanMetrics = TreeMap<MetricDescriptor, IMetricContainer<Boolean>>()
@@ -65,24 +67,30 @@ class MetricsContainer : IStatisticsValuesConsumer {
stringMetricsMap[name]?.also { metricType -> stringMetricsMap[name]?.also { metricType ->
metricType.type.fromStringRepresentation(representation)?.also { metricType.type.fromStringRepresentation(representation)?.also {
synchronized(container.metricsLock) {
container.stringMetrics[MetricDescriptor(name, subProjectHash)] = it container.stringMetrics[MetricDescriptor(name, subProjectHash)] = it
} }
} }
}
booleanMetricsMap[name]?.also { metricType -> booleanMetricsMap[name]?.also { metricType ->
metricType.type.fromStringRepresentation(representation)?.also { metricType.type.fromStringRepresentation(representation)?.also {
synchronized(container.metricsLock) {
container.booleanMetrics[MetricDescriptor(name, subProjectHash)] = it container.booleanMetrics[MetricDescriptor(name, subProjectHash)] = it
} }
} }
}
numericalMetricsMap[name]?.also { metricType -> numericalMetricsMap[name]?.also { metricType ->
metricType.type.fromStringRepresentation(representation)?.also { metricType.type.fromStringRepresentation(representation)?.also {
synchronized(container.metricsLock) {
container.numericalMetrics[MetricDescriptor(name, subProjectHash)] = it container.numericalMetrics[MetricDescriptor(name, subProjectHash)] = it
} }
} }
} }
} }
} }
}
} finally { } finally {
channel.close() channel.close()
} }
@@ -98,31 +106,39 @@ class MetricsContainer : IStatisticsValuesConsumer {
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) { override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
val projectHash = getProjectHash(metric.perProject, subprojectName) val projectHash = getProjectHash(metric.perProject, subprojectName)
synchronized(metricsLock) {
val metricContainer = booleanMetrics[MetricDescriptor(metric.name, projectHash)] ?: metric.type.newMetricContainer() val metricContainer = booleanMetrics[MetricDescriptor(metric.name, projectHash)] ?: metric.type.newMetricContainer()
.also { booleanMetrics[MetricDescriptor(metric.name, projectHash)] = it } .also { booleanMetrics[MetricDescriptor(metric.name, projectHash)] = it }
metricContainer.addValue(metric.anonymization.anonymize(value)) metricContainer.addValue(metric.anonymization.anonymize(value))
} }
}
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) { override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) {
val projectHash = getProjectHash(metric.perProject, subprojectName) val projectHash = getProjectHash(metric.perProject, subprojectName)
synchronized(metricsLock) {
val metricContainer = numericalMetrics[MetricDescriptor(metric.name, projectHash)] ?: metric.type.newMetricContainer() val metricContainer = numericalMetrics[MetricDescriptor(metric.name, projectHash)] ?: metric.type.newMetricContainer()
.also { numericalMetrics[MetricDescriptor(metric.name, projectHash)] = it } .also { numericalMetrics[MetricDescriptor(metric.name, projectHash)] = it }
metricContainer.addValue(metric.anonymization.anonymize(value)) metricContainer.addValue(metric.anonymization.anonymize(value))
} }
}
override fun report(metric: StringMetrics, value: String, subprojectName: String?) { override fun report(metric: StringMetrics, value: String, subprojectName: String?) {
val projectHash = if (subprojectName == null) null else processProjectName(subprojectName, metric.perProject) val projectHash = getProjectHash(metric.perProject, subprojectName)
synchronized(metricsLock) {
val metricContainer = stringMetrics[MetricDescriptor(metric.name, projectHash)] ?: metric.type.newMetricContainer() val metricContainer = stringMetrics[MetricDescriptor(metric.name, projectHash)] ?: metric.type.newMetricContainer()
.also { stringMetrics[MetricDescriptor(metric.name, projectHash)] = it } .also { stringMetrics[MetricDescriptor(metric.name, projectHash)] = it }
metricContainer.addValue(metric.anonymization.anonymize(value)) metricContainer.addValue(metric.anonymization.anonymize(value))
} }
}
fun flush(trackingFile: IRecordLogger?) { fun flush(trackingFile: IRecordLogger?) {
if (trackingFile == null) return if (trackingFile == null) return
val allMetrics = TreeMap<MetricDescriptor, IMetricContainer<out Any>>() val allMetrics = TreeMap<MetricDescriptor, IMetricContainer<out Any>>()
synchronized(metricsLock) {
allMetrics.putAll(numericalMetrics) allMetrics.putAll(numericalMetrics)
allMetrics.putAll(booleanMetrics) allMetrics.putAll(booleanMetrics)
allMetrics.putAll(stringMetrics) allMetrics.putAll(stringMetrics)
}
for (entry in allMetrics.entries) { for (entry in allMetrics.entries) {
val suffix = if (entry.key.projectHash == null) "" else ".${entry.key.projectHash}" val suffix = if (entry.key.projectHash == null) "" else ".${entry.key.projectHash}"
trackingFile.append("${entry.key.name}$suffix=${entry.value.toStringRepresentation()}") trackingFile.append("${entry.key.name}$suffix=${entry.value.toStringRepresentation()}")
@@ -130,14 +146,22 @@ class MetricsContainer : IStatisticsValuesConsumer {
trackingFile.append(BUILD_SESSION_SEPARATOR) trackingFile.append(BUILD_SESSION_SEPARATOR)
synchronized(metricsLock) {
stringMetrics.clear() stringMetrics.clear()
booleanMetrics.clear() booleanMetrics.clear()
numericalMetrics.clear() numericalMetrics.clear()
} }
}
fun getMetric(metric: NumericalMetrics): IMetricContainer<Long>? = numericalMetrics[MetricDescriptor(metric.name, null)]
fun getMetric(metric: NumericalMetrics): IMetricContainer<Long>? = synchronized(metricsLock) {
fun getMetric(metric: StringMetrics): IMetricContainer<String>? = stringMetrics[MetricDescriptor(metric.name, null)] numericalMetrics[MetricDescriptor(metric.name, null)]
}
fun getMetric(metric: BooleanMetrics): IMetricContainer<Boolean>? = booleanMetrics[MetricDescriptor(metric.name, null)]
fun getMetric(metric: StringMetrics): IMetricContainer<String>? = synchronized(metricsLock) {
stringMetrics[MetricDescriptor(metric.name, null)]
}
fun getMetric(metric: BooleanMetrics): IMetricContainer<Boolean>? = synchronized(metricsLock) {
booleanMetrics[MetricDescriptor(metric.name, null)]
}
} }