Skip to content

Commit 4a81fca

Browse files
authored
Issue-31: Support Configuration Cache
Issue-31: Support Configuration Cache
2 parents 07adf60 + 9a8fbec commit 4a81fca

File tree

7 files changed

+78
-199
lines changed

7 files changed

+78
-199
lines changed

CODE_OF_CONDUCT.md

-134
This file was deleted.

README.md

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# build-time-tracker
22

3-
Gradle plugin that prints the time taken by the tasks in a build.
3+
Gradle plugin that prints the time taken by the tasks in a build. If you like it, consider becoming a
4+
![GitHub Sponsor](https://img.shields.io/github/sponsors/asarkar?label=Sponsor&logo=GitHub).
45

56
[![](https://github.com/asarkar/build-time-tracker/workflows/CI%20Pipeline/badge.svg)](https://github.com/asarkar/build-time-tracker/actions?query=workflow%3A%22CI+Pipeline%22)
67

@@ -36,9 +37,10 @@ buildTimeTracker {
3637
3738
:information_source: Due to a
3839
[Gradle limitation](https://docs.gradle.org/6.5.1/userguide/upgrading_version_5.html#apis_buildlistener_buildstarted_and_gradle_buildstarted_have_been_deprecated)
39-
, the build duration can't be calculated precisely. The bars and percentages are rounded off such that the output
40-
provides a good indication of how long individual tasks took to complete relative to the build, but are not meant to be
41-
correct up to the milliseconds.
40+
and the ill-thought-out [Configuration Cache](https://github.com/gradle/gradle/issues/18520) design, the build duration
41+
can't be calculated precisely. The bars and percentages are rounded off such that the output provides a good indication
42+
of how long individual tasks took to complete relative to the build, but are not meant to be correct up to the
43+
milliseconds.
4244

4345
:information_source: It is sufficient to apply the plugin to the root project; applying to subprojects will result in
4446
duplication of the report.
@@ -55,14 +57,14 @@ is one way.
5557
- Java 11
5658
- Gradle 6.1
5759

58-
## Contribute
60+
## Contribution
5961

60-
This project is a volunteer effort. You are welcome to send pull requests, ask questions, or create issues. If you like
61-
it, you can help by spreading the word and "Starring" the GitHub repo!
62+
This project is a volunteer effort. You are welcome to send pull requests, ask questions, or create issues.
6263

6364
## Code of Conduct
6465

65-
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
66+
This project adheres to the Contributor Covenant [code of conduct](https://github.com/asarkar/.github/blob/main/CODE_OF_CONDUCT.md).
67+
By participating, you are expected to uphold this code.
6668

6769
## License
6870

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pluginImplementationClass = com.asarkar.gradle.buildtimetracker.BuildTimeTracker
1111
pluginDeclarationName = buildTimeTrackerPlugin
1212

1313
projectGroup = com.asarkar.gradle
14-
projectVersion = 4.0.0
14+
projectVersion = 4.1.0
1515

1616
junitVersion = latest.release
1717
assertjVersion = latest.release
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,40 @@
11
package com.asarkar.gradle.buildtimetracker
22

3-
import com.asarkar.gradle.buildtimetracker.Constants.EXTRA_EXTENSION_NAME
4-
import com.asarkar.gradle.buildtimetracker.Constants.LOGGER_KEY
53
import com.asarkar.gradle.buildtimetracker.Constants.PLUGIN_EXTENSION_NAME
64
import org.gradle.api.Plugin
75
import org.gradle.api.Project
8-
import org.gradle.api.plugins.ExtensionAware
96
import org.gradle.api.plugins.ReportingBasePlugin
10-
import org.gradle.api.reflect.TypeOf
7+
import org.gradle.build.event.BuildEventsListenerRegistry
8+
import javax.inject.Inject
119

12-
class BuildTimeTrackerPlugin : Plugin<Project> {
10+
@Suppress("UnstableApiUsage")
11+
class BuildTimeTrackerPlugin @Inject constructor(private val registry: BuildEventsListenerRegistry) : Plugin<Project> {
1312
override fun apply(project: Project) {
1413
project.pluginManager.apply(ReportingBasePlugin::class.java)
1514
val ext = project.extensions.create(
1615
PLUGIN_EXTENSION_NAME, BuildTimeTrackerPluginExtension::class.java, project
1716
)
18-
(ext as ExtensionAware).extensions.add(
19-
object : TypeOf<Map<String, Any>>() {},
20-
EXTRA_EXTENSION_NAME,
21-
mapOf<String, Any>(LOGGER_KEY to project.logger)
22-
)
23-
val timingRecorder = TimingRecorder(ext)
24-
project.gradle.addListener(timingRecorder)
17+
val clazz = TimingRecorder::class.java
18+
val timingRecorder =
19+
project.gradle.sharedServices.registerIfAbsent(clazz.simpleName, clazz) { spec ->
20+
val params = BuildTimeTrackerPluginParams(ext.reportsDir.get().asFile)
21+
spec.parameters.getParams().set(params)
22+
}
23+
24+
project.gradle.projectsEvaluated {
25+
copyParams(ext, timingRecorder.get().parameters.getParams().get())
26+
}
27+
28+
registry.onTaskCompletion(timingRecorder)
29+
}
30+
31+
private fun copyParams(src: BuildTimeTrackerPluginExtension, dest: BuildTimeTrackerPluginParams) {
32+
dest.barPosition = src.barPosition.get()
33+
dest.sort = src.sort.get()
34+
dest.output = src.output.get()
35+
dest.maxWidth = src.maxWidth.get()
36+
dest.minTaskDuration = src.minTaskDuration.get()
37+
dest.showBars = src.showBars.get()
38+
dest.reportsDir = src.reportsDir.get().asFile
2539
}
2640
}

src/main/kotlin/com/asarkar/gradle/buildtimetracker/BuildTimeTrackerPluginExtension.kt src/main/kotlin/com/asarkar/gradle/buildtimetracker/BuildTimeTrackerPluginHelper.kt

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import org.gradle.api.Project
44
import org.gradle.api.file.DirectoryProperty
55
import org.gradle.api.provider.Property
66
import org.gradle.api.reporting.ReportingExtension
7+
import java.io.File
78
import java.time.Duration
89

910
enum class BarPosition {
@@ -34,3 +35,12 @@ open class BuildTimeTrackerPluginExtension(private val project: Project) {
3435
get() = project.extensions.getByType(ReportingExtension::class.java)
3536
.baseDirectory
3637
}
38+
39+
open class BuildTimeTrackerPluginParams(var reportsDir: File) : java.io.Serializable {
40+
var barPosition = Constants.DEFAULT_BAR_POSITION
41+
var sort = Constants.DEFAULT_SORT
42+
var output = Constants.DEFAULT_OUTPUT
43+
var maxWidth = Constants.DEFAULT_MAX_WIDTH
44+
var minTaskDuration: Duration = Duration.ofSeconds(Constants.DEFAULT_MIN_TASK_DURATION)
45+
var showBars = Constants.DEFAULT_SHOW_BARS
46+
}

src/main/kotlin/com/asarkar/gradle/buildtimetracker/Printer.kt

+4-5
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,12 @@ interface Printer : Closeable {
7070

7171
private fun Int.format(): String = String.format("%d%%", this)
7272

73-
fun newInstance(ext: BuildTimeTrackerPluginExtension): Printer {
74-
return when (ext.output.get()) {
73+
fun newInstance(params: BuildTimeTrackerPluginParams): Printer {
74+
return when (params.output) {
7575
Output.CONSOLE -> ConsolePrinter()
7676
Output.CSV -> {
77-
val csvFile = ext.reportsDir.get()
78-
.file(Constants.CSV_FILENAME)
79-
.asFile
77+
val csvFile = params.reportsDir
78+
.resolve(Constants.CSV_FILENAME)
8079
CsvPrinter(newOutputStream(csvFile))
8180
}
8281
}
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,50 @@
11
package com.asarkar.gradle.buildtimetracker
22

3-
import org.gradle.BuildAdapter
4-
import org.gradle.BuildResult
5-
import org.gradle.api.Task
6-
import org.gradle.api.execution.TaskExecutionListener
7-
import org.gradle.api.invocation.Gradle
8-
import org.gradle.api.logging.Logger
9-
import org.gradle.api.plugins.ExtensionAware
10-
import org.gradle.api.reflect.TypeOf
11-
import org.gradle.api.tasks.TaskState
3+
import org.gradle.api.provider.Property
4+
import org.gradle.api.services.BuildService
5+
import org.gradle.api.services.BuildServiceParameters
6+
import org.gradle.tooling.events.FinishEvent
7+
import org.gradle.tooling.events.OperationCompletionListener
8+
import org.gradle.tooling.events.task.TaskFinishEvent
129
import java.time.Duration
1310
import java.time.Instant
14-
import java.util.concurrent.ConcurrentHashMap
1511
import java.util.concurrent.ConcurrentLinkedQueue
1612

17-
class TimingRecorder(private val ext: BuildTimeTrackerPluginExtension) : TaskExecutionListener, BuildAdapter() {
18-
private val taskStartTimings: MutableMap<String, Instant> = ConcurrentHashMap()
19-
private val taskDurations: MutableCollection<Pair<String, Long>> = ConcurrentLinkedQueue()
20-
private lateinit var buildStarted: Instant
21-
22-
override fun beforeExecute(task: Task) {
23-
taskStartTimings[task.path] = Instant.now()
13+
@Suppress("UnstableApiUsage")
14+
abstract class TimingRecorder : BuildService<TimingRecorder.Params>, OperationCompletionListener, AutoCloseable {
15+
interface Params : BuildServiceParameters {
16+
fun getParams(): Property<BuildTimeTrackerPluginParams>
2417
}
2518

26-
override fun afterExecute(task: Task, state: TaskState) {
27-
check(taskStartTimings.contains(task.path)) { "No start timing for task ${task.path}" }
28-
val duration = Duration.between(taskStartTimings[task.path], Instant.now()).seconds
29-
if (duration >= ext.minTaskDuration.get().seconds) {
30-
taskDurations.add(task.path to duration)
19+
private val taskDurations: MutableCollection<Pair<String, Long>> = ConcurrentLinkedQueue()
20+
private val buildStarted: Instant = Instant.now()
21+
22+
override fun onFinish(event: FinishEvent) {
23+
if (event is TaskFinishEvent) {
24+
val params = parameters.getParams().get()
25+
val duration = Duration.ofMillis(event.result.endTime - event.result.startTime).seconds
26+
if (duration >= params.minTaskDuration.seconds) {
27+
taskDurations.add(event.descriptor.taskPath to duration)
28+
}
3129
}
3230
}
3331

34-
override fun buildFinished(result: BuildResult) {
32+
override fun close() {
3533
if (taskDurations.isEmpty()) {
36-
val extra = (ext as ExtensionAware).extensions.getByType(
37-
object : TypeOf<Map<String, Any>>() {}
38-
)
39-
(extra[Constants.LOGGER_KEY] as Logger).lifecycle(
40-
"All tasks completed within the minimum threshold: {}s, no build summary to show",
41-
ext.minTaskDuration.get().seconds
42-
)
4334
return
4435
}
36+
val params = parameters.getParams().get()
4537
val buildDuration = Duration.between(buildStarted, Instant.now()).seconds
46-
Printer.newInstance(ext)
38+
Printer.newInstance(params)
4739
.use { printer ->
4840
val input = PrinterInput(
4941
buildDuration,
50-
if (ext.sort.get()) taskDurations.sortedBy { -it.second } else taskDurations,
51-
ext.maxWidth.get(),
52-
ext.showBars.get(),
53-
ext.barPosition.get()
42+
if (params.sort) taskDurations.sortedBy { -it.second } else taskDurations,
43+
params.maxWidth,
44+
params.showBars,
45+
params.barPosition
5446
)
5547
printer.print(input)
5648
}
5749
}
58-
59-
override fun projectsEvaluated(gradle: Gradle) {
60-
buildStarted = Instant.now()
61-
}
6250
}

0 commit comments

Comments
 (0)