Skip to content

Commit

Permalink
Update build operations
Browse files Browse the repository at this point in the history
  • Loading branch information
alllex committed Feb 8, 2023
1 parent e92faa3 commit 51ea943
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 149 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.gradle.tools.trace.app

import org.gradle.tools.trace.app.buildops.*
import org.gradle.tools.trace.app.util.composeCsvRow
import java.io.File

class TraceToTimelineConverter : BuildOperationVisitor {
Expand Down Expand Up @@ -59,30 +61,31 @@ class TraceToTimelineConverter : BuildOperationVisitor {
}

private fun onExecuteTransform(record: BuildOperationRecord) {
val identity = TransformationIdentity.fromRecord(record)
val details = ExecuteScheduledTransformationStepBuildOperationDetails.fromRecord(record)

val node = Node(
description = createTransformationDescription(identity),
description = createTransformationDescription(details),
type = NodeType.TRANSFORM,
inTypeId = identity.transformationNodeId,
workType = identity.transformType,
buildPath = identity.buildPath,
projectPath = identity.projectPath,
inTypeId = details.transformationIdentity.transformationNodeId,
workType = details.transformType,
buildPath = details.transformationIdentity.buildPath,
projectPath = details.transformationIdentity.projectPath,
startTime = record.startTime,
duration = record.endTime - record.startTime,
)

nodes.add(node)
}

private fun createTransformationDescription(identity: TransformationIdentity): String {
return identity.componentId.toString() + compressAttributes(identity)
private fun createTransformationDescription(details: ExecuteScheduledTransformationStepBuildOperationDetails): String {
val identity = details.transformationIdentity
return identity.targetVariant.componentId.toString() + compressAttributes(details)
}

private fun compressAttributes(identity: TransformationIdentity): String {
private fun compressAttributes(details: ExecuteScheduledTransformationStepBuildOperationDetails): String {
return buildString {
for ((name, toValue) in identity.toAttributes) {
val fromValue = identity.fromAttributes[name]
for ((name, toValue) in details.toAttributes) {
val fromValue = details.fromAttributes[name]
if (toValue == fromValue) continue

append(" ").append(name).append("(")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,42 @@
package org.gradle.tools.trace.app

import org.gradle.tools.trace.app.buildops.ExecuteScheduledTransformationStepBuildOperationDetails
import org.gradle.tools.trace.app.buildops.TransformationIdentity
import org.gradle.tools.trace.app.buildops.isExecuteScheduledTransformationStep
import org.gradle.tools.trace.app.util.attributesMapToString
import org.gradle.tools.trace.app.util.composeCsvRow
import java.io.File

/**
* A unique identifier for a (single-artifact) transform that is determined by the `IdentifyStep`
* and doubles as a workspace identifier for transform outputs.
*/
@JvmInline
value class UniqueTransformIdentity(val value: String)

class TraceToTransformCsvConverter : BuildOperationVisitor {

data class TransformInfo(
val transformationIdentity: TransformationIdentity,
val identity: String,
val transformationIdentity: TransformationIdentity?,

val sourceAttributes: Map<String, String>,
val fromAttributes: Map<String, String>,
val toAttributes: Map<String, String>,
val artifactName: String,
val transformType: String,

val uniqueTransformIdentity: UniqueTransformIdentity,
var invocationCount: Int = 1,
var executionCount: Int = 0,
var executionTimeMillis: Long = 0,
)

private val transformByIdentity = mutableMapOf<String, TransformInfo>()
private var currentTransformation: TransformationIdentity? = null
// TODO: this mapping does not cover the case when the unique transform identity does not match the transformation identity
// This can happen if two consuming projects require the same transformed version of a producer project
private val transformByIdentity = mutableMapOf<UniqueTransformIdentity, TransformInfo>()

/* Visitor state */
private var currentTransformationDetails: ExecuteScheduledTransformationStepBuildOperationDetails? = null

fun convert(slice: BuildOperationTraceSlice, outputFile: File) {
BuildOperationVisitor.visitRecords(slice, this)
Expand Down Expand Up @@ -44,51 +67,51 @@ class TraceToTransformCsvConverter : BuildOperationVisitor {
}

private fun onTransformationNodeExecution(record: BuildOperationRecord): PostVisit {
val identity = TransformationIdentity.fromRecord(record)
if (currentTransformation != null) {
System.err.println("Unexpected transformation node execution: $currentTransformation, when entering $identity")
val details = ExecuteScheduledTransformationStepBuildOperationDetails.fromRecord(record)
currentTransformationDetails?.let {
System.err.println("Unexpected transformation node execution: ${it.transformationIdentity}, when entering ${details.transformationIdentity}")
}

currentTransformation = identity
currentTransformationDetails = details
return {
currentTransformation = null
currentTransformationDetails = null
}
}

@Suppress("UNCHECKED_CAST")
private fun onIdentifyTransform(record: BuildOperationRecord) {
val result = record.result!! as Map<String, Map<String, String>>
val transformIdentity = result["identity"]!!["uniqueId"]!!
val transformIdentity = UniqueTransformIdentity(result["identity"]!!["uniqueId"]!!)

val details = record.details!!
val transformType = details["workType"] as String
val componentId = details["componentId"] as String
val fromAttributes = namedAttributesToMap(details["fromAttributes"] as List<Map<String, String>>)
val toAttributes = namedAttributesToMap(details["toAttributes"] as List<Map<String, String>>)

val transformationIdentity = currentTransformation
?: TransformationIdentity(
// this happens for immediate transforms
buildPath = "",
projectPath = "",
componentId = ComponentIdentifier.Unknown(componentId, "TODO: not unpacked"),
sourceAttributes = emptyMap(),
transformType = transformType,
fromAttributes = fromAttributes.toSortedMap(),
toAttributes = toAttributes.toSortedMap(),
transformationNodeId = -1,
)
// Can be null for immediate transforms
val currentTransformationDetails = currentTransformationDetails
val currentTransformationIdentity = currentTransformationDetails?.transformationIdentity

val prevInfo = transformByIdentity[transformIdentity]
if (prevInfo != null) {
if (prevInfo.transformationIdentity != transformationIdentity) {
System.err.println("Unexpected identify transform (different transformation): $transformIdentity, $transformType, $componentId, $fromAttributes, $toAttributes")
if (prevInfo.transformationIdentity != currentTransformationIdentity) {
System.err.println("\n" + """
WARNING: Transform $transformIdentity has multiple transformation identities:
- ${prevInfo.transformationIdentity}
- $currentTransformationIdentity
""".trimIndent())
}
prevInfo.invocationCount++
} else {
transformByIdentity[transformIdentity] = TransformInfo(
transformationIdentity,
transformIdentity,
currentTransformationIdentity,
sourceAttributes = currentTransformationDetails?.sourceAttributes ?: emptyMap(),
fromAttributes = currentTransformationDetails?.fromAttributes ?: fromAttributes,
toAttributes = currentTransformationDetails?.toAttributes ?: toAttributes,
artifactName = currentTransformationIdentity?.artifactName ?: "",
transformType = transformType,
uniqueTransformIdentity = transformIdentity,
)
}
}
Expand All @@ -101,15 +124,15 @@ class TraceToTransformCsvConverter : BuildOperationVisitor {
return
}

val identity = (details["identity"] as Map<String, *>)["uniqueId"]!! as String
val uniqueTransformIdentity = UniqueTransformIdentity((details["identity"] as Map<String, *>)["uniqueId"]!! as String)
val executionTimeMillis = record.endTime - record.startTime
val transformInfo = transformByIdentity[identity] ?: run {
System.err.println("No transform info for identity $identity")
val transformInfo = transformByIdentity[uniqueTransformIdentity] ?: run {
System.err.println("No transform info for identity $uniqueTransformIdentity")
return
}

if (transformInfo.executionCount != 0) {
System.err.println("WARNING: Transform ${transformInfo.transformationIdentity.transformType} ($identity) executed multiple times")
System.err.println("WARNING: Transform ${transformInfo.transformType} ($uniqueTransformIdentity) executed multiple times")
}

transformInfo.executionTimeMillis += executionTimeMillis
Expand All @@ -135,27 +158,37 @@ class TraceToTransformCsvConverter : BuildOperationVisitor {
"buildPath",
"projectPath",
"componentId",
"targetAttributes",
"capabilities",
"artifactName",
"transformationNodeId",

"sourceAttributes",
"transformType",
"fromAttributes",
"toAttributes",
"transformationNodeId",
"identity",
"transformType",
"uniqueTransformIdentity",

"invocationCount",
"executionCount",
"executionTimeMillis"
).joinToString(",")

private fun composeRow(transformInfo: TransformInfo): String = composeCsvRow(
transformInfo.transformationIdentity.buildPath,
transformInfo.transformationIdentity.projectPath,
transformInfo.transformationIdentity.componentId.toString(),
transformInfo.transformationIdentity.sourceAttributes.attributesMapToString(),
transformInfo.transformationIdentity.transformType,
transformInfo.transformationIdentity.fromAttributes.attributesMapToString(),
transformInfo.transformationIdentity.toAttributes.attributesMapToString(),
transformInfo.transformationIdentity.transformationNodeId.toString(),
transformInfo.identity,
transformInfo.transformationIdentity?.buildPath,
transformInfo.transformationIdentity?.projectPath,
transformInfo.transformationIdentity?.targetVariant?.componentId?.toString(),
transformInfo.transformationIdentity?.targetVariant?.attributes?.attributesMapToString(),
transformInfo.transformationIdentity?.targetVariant?.capabilities?.joinToString(),
transformInfo.transformationIdentity?.artifactName,
transformInfo.transformationIdentity?.transformationNodeId?.toString(),

transformInfo.sourceAttributes.attributesMapToString(),
transformInfo.fromAttributes.attributesMapToString(),
transformInfo.toAttributes.attributesMapToString(),
transformInfo.transformType,
transformInfo.uniqueTransformIdentity.value,

transformInfo.invocationCount.toString(),
transformInfo.executionCount.toString(),
transformInfo.executionTimeMillis.toString(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package org.gradle.tools.trace.app
package org.gradle.tools.trace.app.buildops

import org.gradle.tools.trace.app.BuildOperationRecord

fun BuildOperationRecord.isExecuteTask() =
detailsClassName == "org.gradle.api.internal.tasks.execution.ExecuteTaskBuildOperationDetails"

fun BuildOperationRecord.isExecuteScheduledTransformationStep() =
detailsClassName == "org.gradle.api.internal.artifacts.transform.ExecuteScheduledTransformationStepBuildOperationDetails"

fun Map<String, String>.attributesMapToString() = entries
.joinToString(",", prefix = "{", postfix = "}") { "${it.key}=${it.value}" }

Loading

0 comments on commit 51ea943

Please sign in to comment.