Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
ru.tinkoff.plugins.buildmetrics.internal.BuildMetricsService.kt Maven / Gradle / Ivy
package ru.tinkoff.plugins.buildmetrics.internal
import org.gradle.api.flow.BuildWorkResult
import org.gradle.api.provider.ListProperty
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
import org.gradle.internal.operations.BuildOperationDescriptor
import org.gradle.internal.operations.BuildOperationListener
import org.gradle.internal.operations.OperationFinishEvent
import org.gradle.internal.operations.OperationIdentifier
import org.gradle.internal.operations.OperationProgressEvent
import org.gradle.internal.operations.OperationStartEvent
import ru.tinkoff.plugins.buildmetrics.api.Reinitializable
import ru.tinkoff.plugins.buildmetrics.api.builds.BuildWorkResultListener
import ru.tinkoff.plugins.buildmetrics.api.builds.internal.BuildOperationData
import ru.tinkoff.plugins.buildmetrics.api.builds.internal.BuildOperationDataListener
import ru.tinkoff.plugins.buildmetrics.api.factories.Factory
import ru.tinkoff.plugins.buildmetrics.api.handlers.BuildHandler
import ru.tinkoff.plugins.buildmetrics.api.labels.Label
import ru.tinkoff.plugins.buildmetrics.api.metrics.Metric
import ru.tinkoff.plugins.buildmetrics.api.publishers.Publisher
abstract class BuildMetricsService : BuildService,
BuildOperationListener,
AutoCloseable {
interface Params : BuildServiceParameters {
val metrics: ListProperty>
val labels: ListProperty>
val metricsFactories: ListProperty
val labelsFactories: ListProperty
val publishers: ListProperty
val buildHandlers: ListProperty
}
private val locker: Any = Any()
private val buildOperationsDataBuffer: MutableList = mutableListOf()
private class ServiceData(
metrics: ListProperty>,
labels: ListProperty>,
metricsFactories: ListProperty,
labelsFactories: ListProperty,
publishers: ListProperty,
buildHandlers: ListProperty,
) {
val metrics: List> = metrics.get()
val labels: List> = labels.get()
val metricsFactories: List = metricsFactories.get()
val labelsFactories: List = labelsFactories.get()
val publishers: List = publishers.get()
val buildHandlers: List = buildHandlers.get()
val buildOperationDataListeners: List
val buildWorkResultListeners: List
val buildOperationsDataBufferEnabled: Boolean
init {
this.metricsFactories.plus(this.labelsFactories)
.plus(this.publishers)
.plus(this.buildHandlers)
.also { items ->
buildOperationDataListeners = items.filterIsInstance()
buildWorkResultListeners = items.filterIsInstance()
}
buildOperationsDataBufferEnabled = buildOperationDataListeners.isNotEmpty()
}
fun reinitialize() {
metricsFactories.plus(labelsFactories)
.plus(publishers)
.plus(buildHandlers)
.forEach { item ->
if (item is Reinitializable) {
item.reinitialize()
}
}
}
}
private var serviceData: ServiceData = ServiceData(
metrics = parameters.metrics,
labels = parameters.labels,
metricsFactories = parameters.metricsFactories,
labelsFactories = parameters.labelsFactories,
publishers = parameters.publishers,
buildHandlers = parameters.buildHandlers,
).apply {
reinitialize()
}
fun setup(
metrics: ListProperty>,
labels: ListProperty>,
metricsFactories: ListProperty,
labelsFactories: ListProperty,
publishers: ListProperty,
buildHandlers: ListProperty
) {
synchronized(locker) {
serviceData = ServiceData(
metrics = metrics,
labels = labels,
metricsFactories = metricsFactories,
labelsFactories = labelsFactories,
publishers = publishers,
buildHandlers = buildHandlers,
)
}
}
override fun started(buildOperation: BuildOperationDescriptor, startEvent: OperationStartEvent) {}
override fun progress(operationIdentifier: OperationIdentifier, progressEvent: OperationProgressEvent) {}
override fun finished(buildOperation: BuildOperationDescriptor, finishEvent: OperationFinishEvent) {
onBuildOperationData(
data = BuildOperationData(
id = buildOperation.id?.id ?: -1L,
parentId = buildOperation.parentId?.id ?: -1L,
startTime = finishEvent.startTime,
endTime = finishEvent.endTime,
durationMs = finishEvent.endTime - finishEvent.startTime,
name = buildOperation.name,
metadata = buildOperation.metadata,
details = buildOperation.details,
result = finishEvent.result,
failure = finishEvent.failure,
)
)
}
private fun onBuildOperationData(data: BuildOperationData) {
synchronized(locker) {
if (serviceData.buildOperationDataListeners.isEmpty()) {
if (serviceData.buildOperationsDataBufferEnabled) {
buildOperationsDataBuffer.add(data)
}
} else {
if (buildOperationsDataBuffer.isNotEmpty()) {
flushBuildOperationsDataBuffer()
}
serviceData.buildOperationDataListeners.forEach { listener ->
listener.onBuildOperationData(data = data)
}
}
}
}
fun onBuildWorkResult(buildWorkResult: BuildWorkResult) {
synchronized(locker) {
serviceData.buildWorkResultListeners.forEach { listener ->
listener.onBuildWorkResult(result = buildWorkResult)
}
}
}
private fun flushBuildOperationsDataBuffer() {
buildOperationsDataBuffer.forEach { bufferedData ->
serviceData.buildOperationDataListeners.forEach { listener ->
listener.onBuildOperationData(data = bufferedData)
}
}
buildOperationsDataBuffer.clear()
}
override fun close() {
synchronized(locker) {
if (buildOperationsDataBuffer.isNotEmpty()) {
flushBuildOperationsDataBuffer()
}
val metrics = createMetrics(labels = createLabels())
serviceData.publishers.forEach { publisher -> publisher.publish(metrics = metrics) }
serviceData.buildHandlers.forEach { handler -> handler.handle() }
}
}
private fun createLabels(): List> {
return serviceData.labelsFactories.flatMap { factory -> factory.create() }
.plus(serviceData.labels)
}
private fun createMetrics(labels: List>): List> {
return serviceData.metricsFactories.flatMap { factory -> factory.create() }
.plus(serviceData.metrics)
.map { metric ->
Metric(
name = metric.name,
value = metric.value,
labels = metric.labels + labels,
)
}
}
}