Skip to content

Commit

Permalink
Issue-31: Support Configuration Cache
Browse files Browse the repository at this point in the history
Issue-31: Support Configuration Cache
  • Loading branch information
asarkar authored Apr 3, 2022
2 parents 07adf60 + 9a8fbec commit 4a81fca
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 199 deletions.
134 changes: 0 additions & 134 deletions CODE_OF_CONDUCT.md

This file was deleted.

18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# build-time-tracker

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

[![](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)

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

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

## Contribute
## Contribution

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

## Code of Conduct

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

## License

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pluginImplementationClass = com.asarkar.gradle.buildtimetracker.BuildTimeTracker
pluginDeclarationName = buildTimeTrackerPlugin

projectGroup = com.asarkar.gradle
projectVersion = 4.0.0
projectVersion = 4.1.0

junitVersion = latest.release
assertjVersion = latest.release
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
package com.asarkar.gradle.buildtimetracker

import com.asarkar.gradle.buildtimetracker.Constants.EXTRA_EXTENSION_NAME
import com.asarkar.gradle.buildtimetracker.Constants.LOGGER_KEY
import com.asarkar.gradle.buildtimetracker.Constants.PLUGIN_EXTENSION_NAME
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.plugins.ReportingBasePlugin
import org.gradle.api.reflect.TypeOf
import org.gradle.build.event.BuildEventsListenerRegistry
import javax.inject.Inject

class BuildTimeTrackerPlugin : Plugin<Project> {
@Suppress("UnstableApiUsage")
class BuildTimeTrackerPlugin @Inject constructor(private val registry: BuildEventsListenerRegistry) : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply(ReportingBasePlugin::class.java)
val ext = project.extensions.create(
PLUGIN_EXTENSION_NAME, BuildTimeTrackerPluginExtension::class.java, project
)
(ext as ExtensionAware).extensions.add(
object : TypeOf<Map<String, Any>>() {},
EXTRA_EXTENSION_NAME,
mapOf<String, Any>(LOGGER_KEY to project.logger)
)
val timingRecorder = TimingRecorder(ext)
project.gradle.addListener(timingRecorder)
val clazz = TimingRecorder::class.java
val timingRecorder =
project.gradle.sharedServices.registerIfAbsent(clazz.simpleName, clazz) { spec ->
val params = BuildTimeTrackerPluginParams(ext.reportsDir.get().asFile)
spec.parameters.getParams().set(params)
}

project.gradle.projectsEvaluated {
copyParams(ext, timingRecorder.get().parameters.getParams().get())
}

registry.onTaskCompletion(timingRecorder)
}

private fun copyParams(src: BuildTimeTrackerPluginExtension, dest: BuildTimeTrackerPluginParams) {
dest.barPosition = src.barPosition.get()
dest.sort = src.sort.get()
dest.output = src.output.get()
dest.maxWidth = src.maxWidth.get()
dest.minTaskDuration = src.minTaskDuration.get()
dest.showBars = src.showBars.get()
dest.reportsDir = src.reportsDir.get().asFile
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
import org.gradle.api.reporting.ReportingExtension
import java.io.File
import java.time.Duration

enum class BarPosition {
Expand Down Expand Up @@ -34,3 +35,12 @@ open class BuildTimeTrackerPluginExtension(private val project: Project) {
get() = project.extensions.getByType(ReportingExtension::class.java)
.baseDirectory
}

open class BuildTimeTrackerPluginParams(var reportsDir: File) : java.io.Serializable {
var barPosition = Constants.DEFAULT_BAR_POSITION
var sort = Constants.DEFAULT_SORT
var output = Constants.DEFAULT_OUTPUT
var maxWidth = Constants.DEFAULT_MAX_WIDTH
var minTaskDuration: Duration = Duration.ofSeconds(Constants.DEFAULT_MIN_TASK_DURATION)
var showBars = Constants.DEFAULT_SHOW_BARS
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,12 @@ interface Printer : Closeable {

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

fun newInstance(ext: BuildTimeTrackerPluginExtension): Printer {
return when (ext.output.get()) {
fun newInstance(params: BuildTimeTrackerPluginParams): Printer {
return when (params.output) {
Output.CONSOLE -> ConsolePrinter()
Output.CSV -> {
val csvFile = ext.reportsDir.get()
.file(Constants.CSV_FILENAME)
.asFile
val csvFile = params.reportsDir
.resolve(Constants.CSV_FILENAME)
CsvPrinter(newOutputStream(csvFile))
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,50 @@
package com.asarkar.gradle.buildtimetracker

import org.gradle.BuildAdapter
import org.gradle.BuildResult
import org.gradle.api.Task
import org.gradle.api.execution.TaskExecutionListener
import org.gradle.api.invocation.Gradle
import org.gradle.api.logging.Logger
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.reflect.TypeOf
import org.gradle.api.tasks.TaskState
import org.gradle.api.provider.Property
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
import org.gradle.tooling.events.FinishEvent
import org.gradle.tooling.events.OperationCompletionListener
import org.gradle.tooling.events.task.TaskFinishEvent
import java.time.Duration
import java.time.Instant
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue

class TimingRecorder(private val ext: BuildTimeTrackerPluginExtension) : TaskExecutionListener, BuildAdapter() {
private val taskStartTimings: MutableMap<String, Instant> = ConcurrentHashMap()
private val taskDurations: MutableCollection<Pair<String, Long>> = ConcurrentLinkedQueue()
private lateinit var buildStarted: Instant

override fun beforeExecute(task: Task) {
taskStartTimings[task.path] = Instant.now()
@Suppress("UnstableApiUsage")
abstract class TimingRecorder : BuildService<TimingRecorder.Params>, OperationCompletionListener, AutoCloseable {
interface Params : BuildServiceParameters {
fun getParams(): Property<BuildTimeTrackerPluginParams>
}

override fun afterExecute(task: Task, state: TaskState) {
check(taskStartTimings.contains(task.path)) { "No start timing for task ${task.path}" }
val duration = Duration.between(taskStartTimings[task.path], Instant.now()).seconds
if (duration >= ext.minTaskDuration.get().seconds) {
taskDurations.add(task.path to duration)
private val taskDurations: MutableCollection<Pair<String, Long>> = ConcurrentLinkedQueue()
private val buildStarted: Instant = Instant.now()

override fun onFinish(event: FinishEvent) {
if (event is TaskFinishEvent) {
val params = parameters.getParams().get()
val duration = Duration.ofMillis(event.result.endTime - event.result.startTime).seconds
if (duration >= params.minTaskDuration.seconds) {
taskDurations.add(event.descriptor.taskPath to duration)
}
}
}

override fun buildFinished(result: BuildResult) {
override fun close() {
if (taskDurations.isEmpty()) {
val extra = (ext as ExtensionAware).extensions.getByType(
object : TypeOf<Map<String, Any>>() {}
)
(extra[Constants.LOGGER_KEY] as Logger).lifecycle(
"All tasks completed within the minimum threshold: {}s, no build summary to show",
ext.minTaskDuration.get().seconds
)
return
}
val params = parameters.getParams().get()
val buildDuration = Duration.between(buildStarted, Instant.now()).seconds
Printer.newInstance(ext)
Printer.newInstance(params)
.use { printer ->
val input = PrinterInput(
buildDuration,
if (ext.sort.get()) taskDurations.sortedBy { -it.second } else taskDurations,
ext.maxWidth.get(),
ext.showBars.get(),
ext.barPosition.get()
if (params.sort) taskDurations.sortedBy { -it.second } else taskDurations,
params.maxWidth,
params.showBars,
params.barPosition
)
printer.print(input)
}
}

override fun projectsEvaluated(gradle: Gradle) {
buildStarted = Instant.now()
}
}

0 comments on commit 4a81fca

Please sign in to comment.