Support weight for FUS metrics
If metric impact is different for different subprojects, corresponding metric could be reported with weight. Currently supported for numerical metrics with override policy AVERAGE.
This commit is contained in:
+27
-16
@@ -191,22 +191,33 @@ class KotlinBuildStatHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun report(sessionLogger: BuildSessionLogger, metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
internal fun report(
|
||||||
runSafe("report metric ${metric.name}") {
|
sessionLogger: BuildSessionLogger,
|
||||||
sessionLogger.report(metric, value, subprojectName)
|
metric: BooleanMetrics,
|
||||||
}
|
value: Boolean,
|
||||||
|
subprojectName: String?,
|
||||||
|
weight: Long? = null
|
||||||
|
) = runSafe("report metric ${metric.name}") {
|
||||||
|
sessionLogger.report(metric, value, subprojectName, weight)
|
||||||
|
} ?: false
|
||||||
|
|
||||||
}
|
internal fun report(
|
||||||
|
sessionLogger: BuildSessionLogger,
|
||||||
|
metric: NumericalMetrics,
|
||||||
|
value: Long,
|
||||||
|
subprojectName: String?,
|
||||||
|
weight: Long? = null
|
||||||
|
) = runSafe("report metric ${metric.name}") {
|
||||||
|
sessionLogger.report(metric, value, subprojectName, weight)
|
||||||
|
} as? Boolean ?: false
|
||||||
|
|
||||||
internal fun report(sessionLogger: BuildSessionLogger, metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
internal fun report(
|
||||||
runSafe("report metric ${metric.name}") {
|
sessionLogger: BuildSessionLogger,
|
||||||
sessionLogger.report(metric, value, subprojectName)
|
metric: StringMetrics,
|
||||||
}
|
value: String,
|
||||||
}
|
subprojectName: String?,
|
||||||
|
weight: Long? = null
|
||||||
internal fun report(sessionLogger: BuildSessionLogger, metric: StringMetrics, value: String, subprojectName: String?) {
|
) = runSafe("report metric ${metric.name}") {
|
||||||
runSafe("report metric ${metric.name}") {
|
sessionLogger.report(metric, value, subprojectName, weight)
|
||||||
sessionLogger.report(metric, value, subprojectName)
|
} as? Boolean ?: false
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-37
@@ -33,11 +33,11 @@ import kotlin.system.measureTimeMillis
|
|||||||
* of Kotlin Plugin and other classloaders
|
* of Kotlin Plugin and other classloaders
|
||||||
*/
|
*/
|
||||||
interface KotlinBuildStatsMXBean {
|
interface KotlinBuildStatsMXBean {
|
||||||
fun reportBoolean(name: String, value: Boolean, subprojectName: String?)
|
fun reportBoolean(name: String, value: Boolean, subprojectName: String?, weight: Long?): Boolean
|
||||||
|
|
||||||
fun reportNumber(name: String, value: Long, subprojectName: String?)
|
fun reportNumber(name: String, value: Long, subprojectName: String?, weight: Long?): Boolean
|
||||||
|
|
||||||
fun reportString(name: String, value: String, subprojectName: String?)
|
fun reportString(name: String, value: String, subprojectName: String?, weight: Long?): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -158,32 +158,29 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd
|
|||||||
internal class JMXKotlinBuildStatsService(private val mbs: MBeanServer, private val beanName: ObjectName) :
|
internal class JMXKotlinBuildStatsService(private val mbs: MBeanServer, private val beanName: ObjectName) :
|
||||||
KotlinBuildStatsService() {
|
KotlinBuildStatsService() {
|
||||||
|
|
||||||
private fun callJmx(method: String, type: String, metricName: String, value: Any, subprojectName: String?) {
|
private fun callJmx(method: String, type: String, metricName: String, value: Any, subprojectName: String?, weight: Long?): Any? {
|
||||||
mbs.invoke(
|
return mbs.invoke(
|
||||||
beanName,
|
beanName,
|
||||||
method,
|
method,
|
||||||
arrayOf(metricName, value, subprojectName),
|
arrayOf(metricName, value, subprojectName, weight),
|
||||||
arrayOf("java.lang.String", type, "java.lang.String")
|
arrayOf("java.lang.String", type, "java.lang.String", "java.lang.Long")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?, weight: Long?) =
|
||||||
runSafe("report metric ${metric.name}") {
|
runSafe("report metric ${metric.name}") {
|
||||||
callJmx("reportBoolean", "boolean", metric.name, value, subprojectName)
|
callJmx("reportBoolean", "boolean", metric.name, value, subprojectName, weight)
|
||||||
}
|
} as? Boolean ?: false
|
||||||
}
|
|
||||||
|
|
||||||
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?, weight: Long?) =
|
||||||
runSafe("report metric ${metric.name}") {
|
runSafe("report metric ${metric.name}") {
|
||||||
callJmx("reportNumber", "long", metric.name, value, subprojectName)
|
callJmx("reportNumber", "long", metric.name, value, subprojectName, weight)
|
||||||
}
|
} as? Boolean ?: false
|
||||||
}
|
|
||||||
|
|
||||||
override fun report(metric: StringMetrics, value: String, subprojectName: String?) {
|
override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?) =
|
||||||
runSafe("report metric ${metric.name}") {
|
runSafe("report metric ${metric.name}") {
|
||||||
callJmx("reportString", "java.lang.String", metric.name, value, subprojectName)
|
callJmx("reportString", "java.lang.String", metric.name, value, subprojectName, weight)
|
||||||
}
|
} as? Boolean ?: false
|
||||||
}
|
|
||||||
|
|
||||||
override fun buildFinished(result: BuildResult) {
|
override fun buildFinished(result: BuildResult) {
|
||||||
instance = null
|
instance = null
|
||||||
@@ -217,27 +214,21 @@ internal class DefaultKotlinBuildStatsService internal constructor(
|
|||||||
instance = null
|
instance = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?, weight: Long?): Boolean =
|
||||||
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName)
|
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName, weight)
|
||||||
}
|
|
||||||
|
|
||||||
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?, weight: Long?): Boolean =
|
||||||
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName)
|
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName, weight)
|
||||||
}
|
|
||||||
|
|
||||||
override fun report(metric: StringMetrics, value: String, subprojectName: String?) {
|
override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?): Boolean =
|
||||||
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName)
|
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName, weight)
|
||||||
}
|
|
||||||
|
|
||||||
override fun reportBoolean(name: String, value: Boolean, subprojectName: String?) {
|
override fun reportBoolean(name: String, value: Boolean, subprojectName: String?, weight: Long?): Boolean =
|
||||||
report(BooleanMetrics.valueOf(name), value, subprojectName)
|
report(BooleanMetrics.valueOf(name), value, subprojectName, weight)
|
||||||
}
|
|
||||||
|
|
||||||
override fun reportNumber(name: String, value: Long, subprojectName: String?) {
|
override fun reportNumber(name: String, value: Long, subprojectName: String?, weight: Long?): Boolean =
|
||||||
report(NumericalMetrics.valueOf(name), value, subprojectName)
|
report(NumericalMetrics.valueOf(name), value, subprojectName, weight)
|
||||||
}
|
|
||||||
|
|
||||||
override fun reportString(name: String, value: String, subprojectName: String?) {
|
override fun reportString(name: String, value: String, subprojectName: String?, weight: Long?): Boolean =
|
||||||
report(StringMetrics.valueOf(name), value, subprojectName)
|
report(StringMetrics.valueOf(name), value, subprojectName, weight)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+41
@@ -10,8 +10,12 @@ import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
|||||||
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.lang.management.ManagementFactory
|
import java.lang.management.ManagementFactory
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import javax.management.MBeanServer
|
import javax.management.MBeanServer
|
||||||
import javax.management.ObjectName
|
import javax.management.ObjectName
|
||||||
|
import javax.management.StandardMBean
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class BuildStatServiceTest {
|
class BuildStatServiceTest {
|
||||||
|
|
||||||
@@ -26,4 +30,41 @@ class BuildStatServiceTest {
|
|||||||
jmxService.report(NumericalMetrics.NUMBER_OF_SUBPROJECTS, 10)
|
jmxService.report(NumericalMetrics.NUMBER_OF_SUBPROJECTS, 10)
|
||||||
jmxService.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
jmxService.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testJmxServerWorks() {
|
||||||
|
val callsCount = AtomicInteger(0)
|
||||||
|
val instance = object : KotlinBuildStatsMXBean {
|
||||||
|
override fun reportBoolean(name: String, value: Boolean, subprojectName: String?, weight: Long?): Boolean {
|
||||||
|
callsCount.incrementAndGet()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportNumber(name: String, value: Long, subprojectName: String?, weight: Long?): Boolean {
|
||||||
|
callsCount.incrementAndGet()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportString(name: String, value: String, subprojectName: String?, weight: Long?): Boolean {
|
||||||
|
callsCount.incrementAndGet()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val beanName = ObjectName(KotlinBuildStatsService.JMX_BEAN_NAME)
|
||||||
|
val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer()
|
||||||
|
mbs.registerMBean(StandardMBean(instance, KotlinBuildStatsMXBean::class.java), beanName)
|
||||||
|
|
||||||
|
try {
|
||||||
|
val jmxService = JMXKotlinBuildStatsService(mbs, beanName)
|
||||||
|
assertTrue(jmxService.report(StringMetrics.KOTLIN_COMPILER_VERSION, "1.2.3"))
|
||||||
|
assertTrue(jmxService.report(NumericalMetrics.NUMBER_OF_SUBPROJECTS, 10))
|
||||||
|
assertTrue(jmxService.report(BooleanMetrics.ENABLED_DATABINDING, true))
|
||||||
|
assertEquals(3, callsCount.get())
|
||||||
|
} finally {
|
||||||
|
mbs.unregisterMBean(beanName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-9
@@ -154,15 +154,12 @@ class BuildSessionLogger(
|
|||||||
closeTrackingFile()
|
closeTrackingFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?, weight: Long?) =
|
||||||
metricsContainer.report(metric, value, subprojectName)
|
metricsContainer.report(metric, value, subprojectName, weight)
|
||||||
}
|
|
||||||
|
|
||||||
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?, weight: Long?) =
|
||||||
metricsContainer.report(metric, value, subprojectName)
|
metricsContainer.report(metric, value, subprojectName, weight)
|
||||||
}
|
|
||||||
|
|
||||||
override fun report(metric: StringMetrics, value: String, subprojectName: String?) {
|
override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?) =
|
||||||
metricsContainer.report(metric, value, subprojectName)
|
metricsContainer.report(metric, value, subprojectName, weight)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-6
@@ -104,31 +104,34 @@ class MetricsContainer : IStatisticsValuesConsumer {
|
|||||||
private fun getProjectHash(perProject: Boolean, subprojectName: String?) =
|
private fun getProjectHash(perProject: Boolean, subprojectName: String?) =
|
||||||
if (subprojectName == null) null else processProjectName(subprojectName, perProject)
|
if (subprojectName == null) null else processProjectName(subprojectName, perProject)
|
||||||
|
|
||||||
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?, weight: Long?): Boolean {
|
||||||
val projectHash = getProjectHash(metric.perProject, subprojectName)
|
val projectHash = getProjectHash(metric.perProject, subprojectName)
|
||||||
synchronized(metricsLock) {
|
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), weight)
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?, weight: Long?): Boolean {
|
||||||
val projectHash = getProjectHash(metric.perProject, subprojectName)
|
val projectHash = getProjectHash(metric.perProject, subprojectName)
|
||||||
synchronized(metricsLock) {
|
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), weight)
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: StringMetrics, value: String, subprojectName: String?) {
|
override fun report(metric: StringMetrics, value: String, subprojectName: String?, weight: Long?): Boolean {
|
||||||
val projectHash = getProjectHash(metric.perProject, subprojectName)
|
val projectHash = getProjectHash(metric.perProject, subprojectName)
|
||||||
synchronized(metricsLock) {
|
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), weight)
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun flush(trackingFile: IRecordLogger?) {
|
fun flush(trackingFile: IRecordLogger?) {
|
||||||
|
|||||||
+15
-13
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.statistics.metrics
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface IMetricContainer<T> {
|
interface IMetricContainer<T> {
|
||||||
fun addValue(t: T)
|
fun addValue(t: T, weight: Long? = null)
|
||||||
|
|
||||||
fun toStringRepresentation(): String
|
fun toStringRepresentation(): String
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ interface IMetricContainerFactory<T> {
|
|||||||
open class OverrideMetricContainer<T>() : IMetricContainer<T> {
|
open class OverrideMetricContainer<T>() : IMetricContainer<T> {
|
||||||
internal var myValue: T? = null
|
internal var myValue: T? = null
|
||||||
|
|
||||||
override fun addValue(t: T) {
|
override fun addValue(t: T, weight: Long?) {
|
||||||
myValue = t
|
myValue = t
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ class OverrideVersionMetricContainer() : OverrideMetricContainer<String>() {
|
|||||||
myValue = v
|
myValue = v
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addValue(t: String) {
|
override fun addValue(t: String, weight: Long?) {
|
||||||
if (myValue == null || myValue == "0.0.0") {
|
if (myValue == null || myValue == "0.0.0") {
|
||||||
myValue = t
|
myValue = t
|
||||||
}
|
}
|
||||||
@@ -56,22 +56,24 @@ class SumMetricContainer() : OverrideMetricContainer<Long>() {
|
|||||||
myValue = v
|
myValue = v
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addValue(t: Long) {
|
override fun addValue(t: Long, weight: Long?) {
|
||||||
myValue = (myValue ?: 0) + t
|
myValue = (myValue ?: 0) + t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AverageMetricContainer() : IMetricContainer<Long> {
|
class AverageMetricContainer() : IMetricContainer<Long> {
|
||||||
private var count = 0
|
private var totalWeight = 0L
|
||||||
private var myValue: Long? = null
|
private var totalSum: Long? = null
|
||||||
|
|
||||||
constructor(v: Long) : this() {
|
constructor(v: Long) : this() {
|
||||||
myValue = v
|
totalSum = v
|
||||||
|
totalWeight = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addValue(t: Long) {
|
override fun addValue(t: Long, weight: Long?) {
|
||||||
myValue = (myValue ?: 0) + t
|
val w = weight ?: 1
|
||||||
count++
|
totalSum = (totalSum ?: 0) + t * w
|
||||||
|
totalWeight += w
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toStringRepresentation(): String {
|
override fun toStringRepresentation(): String {
|
||||||
@@ -79,7 +81,7 @@ class AverageMetricContainer() : IMetricContainer<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getValue(): Long? {
|
override fun getValue(): Long? {
|
||||||
return myValue?.div(count)
|
return totalSum?.div(if (totalWeight > 0) totalWeight else 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +90,7 @@ class OrMetricContainer() : OverrideMetricContainer<Boolean>() {
|
|||||||
myValue = v
|
myValue = v
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addValue(t: Boolean) {
|
override fun addValue(t: Boolean, weight: Long?) {
|
||||||
myValue = (myValue ?: false) || t
|
myValue = (myValue ?: false) || t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +106,7 @@ class ConcatMetricContainer() : IMetricContainer<String> {
|
|||||||
myValues.addAll(values)
|
myValues.addAll(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addValue(t: String) {
|
override fun addValue(t: String, weight: Long?) {
|
||||||
myValues.add(t.replace(SEPARATOR, ","))
|
myValues.add(t.replace(SEPARATOR, ","))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -18,9 +18,9 @@ interface AdditiveStatisticsValue<T> : ReportStatisticsValue<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IStatisticsValuesConsumer {
|
interface IStatisticsValuesConsumer {
|
||||||
fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String? = null)
|
fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String? = null, weight: Long? = null): Boolean
|
||||||
|
|
||||||
fun report(metric: NumericalMetrics, value: Long, subprojectName: String? = null)
|
fun report(metric: NumericalMetrics, value: Long, subprojectName: String? = null, weight: Long? = null): Boolean
|
||||||
|
|
||||||
fun report(metric: StringMetrics, value: String, subprojectName: String? = null)
|
fun report(metric: StringMetrics, value: String, subprojectName: String? = null, weight: Long? = null): Boolean
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user